summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGard Spreemann <gspr@nonempty.org>2020-06-03 09:27:46 +0200
committerGard Spreemann <gspr@nonempty.org>2020-06-03 09:27:46 +0200
commitef141880d9515589bc66045ae2eade507dcba65d (patch)
treee7d8e7db8a2d9f93de1c3d66b140273bfa76cce7
parent1b9285fe226b95ab79481d69d9a989ff88d4d840 (diff)
parent803fd45bc77103813895ac045a278157554fd39a (diff)
Merge branch 'dfsg/latest' into debian/sid
-rw-r--r--.gitignore37
-rw-r--r--README.txt41
-rw-r--r--bottleneck/CMakeLists.txt38
-rw-r--r--bottleneck/README98
-rw-r--r--bottleneck/example/CMakeLists.txt27
-rw-r--r--bottleneck/example/bottleneck_dist.cpp96
-rw-r--r--bottleneck/include/basic_defs_bt.h569
-rw-r--r--bottleneck/include/bottleneck.h153
-rw-r--r--bottleneck/include/bottleneck_detail.h90
-rw-r--r--bottleneck/include/bottleneck_detail.hpp636
-rw-r--r--bottleneck/include/bound_match.h109
-rw-r--r--bottleneck/include/bound_match.hpp511
-rw-r--r--bottleneck/include/def_debug_bt.h42
-rw-r--r--bottleneck/include/diagram_reader.h196
-rw-r--r--bottleneck/include/diagram_traits.h45
-rw-r--r--bottleneck/include/dnn/geometry/euclidean-fixed.h162
-rw-r--r--bottleneck/include/dnn/local/kd-tree.h106
-rw-r--r--bottleneck/include/dnn/local/kd-tree.hpp296
-rw-r--r--bottleneck/include/dnn/local/search-functors.h119
-rw-r--r--bottleneck/include/dnn/parallel/tbb.h233
-rw-r--r--bottleneck/include/dnn/parallel/utils.h100
-rw-r--r--bottleneck/include/dnn/utils.h47
-rw-r--r--bottleneck/include/neighb_oracle.h295
-rw-r--r--bottleneck/tests/data/test_001_A1
-rw-r--r--bottleneck/tests/data/test_001_B1
-rw-r--r--bottleneck/tests/data/test_002_A1
-rw-r--r--bottleneck/tests/data/test_002_B1
-rw-r--r--bottleneck/tests/data/test_003_A2
-rw-r--r--bottleneck/tests/data/test_003_B2
-rw-r--r--bottleneck/tests/data/test_004_A2
-rw-r--r--bottleneck/tests/data/test_004_B3
-rw-r--r--bottleneck/tests/data/test_005_A6
-rw-r--r--bottleneck/tests/data/test_005_B6
-rw-r--r--bottleneck/tests/data/test_006_A7
-rw-r--r--bottleneck/tests/data/test_006_B7
-rw-r--r--bottleneck/tests/data/test_007_A0
-rw-r--r--bottleneck/tests/data/test_007_B0
-rw-r--r--bottleneck/tests/data/test_008_A1
-rw-r--r--bottleneck/tests/data/test_008_B1
-rw-r--r--bottleneck/tests/data/test_009_A1
-rw-r--r--bottleneck/tests/data/test_009_B1
-rw-r--r--bottleneck/tests/data/test_010_A100
-rw-r--r--bottleneck/tests/data/test_010_B100
-rw-r--r--bottleneck/tests/data/test_011_A200
-rw-r--r--bottleneck/tests/data/test_011_B200
-rw-r--r--bottleneck/tests/data/test_012_A5000
-rw-r--r--bottleneck/tests/data/test_012_B5000
-rw-r--r--bottleneck/tests/data/test_013_A5
-rw-r--r--bottleneck/tests/data/test_013_B5
-rw-r--r--bottleneck/tests/data/test_014_A1
-rw-r--r--bottleneck/tests/data/test_014_B1
-rw-r--r--bottleneck/tests/data/test_015_A1
-rw-r--r--bottleneck/tests/data/test_015_B1
-rw-r--r--bottleneck/tests/data/test_016_A220
-rw-r--r--bottleneck/tests/data/test_016_B193
-rw-r--r--bottleneck/tests/data/test_100_A2
-rw-r--r--bottleneck/tests/data/test_100_B2
-rw-r--r--bottleneck/tests/data/test_101_A2
-rw-r--r--bottleneck/tests/data/test_101_B2
-rw-r--r--bottleneck/tests/data/test_102_A2
-rw-r--r--bottleneck/tests/data/test_102_B2
-rw-r--r--bottleneck/tests/data/test_103_A2
-rw-r--r--bottleneck/tests/data/test_103_B2
-rw-r--r--bottleneck/tests/data/test_104_A2
-rw-r--r--bottleneck/tests/data/test_104_B2
-rw-r--r--bottleneck/tests/data/test_105_A2
-rw-r--r--bottleneck/tests/data/test_105_B2
-rw-r--r--bottleneck/tests/data/test_106_A2
-rw-r--r--bottleneck/tests/data/test_106_B2
-rw-r--r--bottleneck/tests/data/test_107_A2
-rw-r--r--bottleneck/tests/data/test_107_B2
-rw-r--r--bottleneck/tests/data/test_108_A2
-rw-r--r--bottleneck/tests/data/test_108_B2
-rw-r--r--bottleneck/tests/data/test_109_A2
-rw-r--r--bottleneck/tests/data/test_109_B2
-rw-r--r--bottleneck/tests/data/test_110_A2
-rw-r--r--bottleneck/tests/data/test_110_B2
-rw-r--r--bottleneck/tests/data/test_111_A2
-rw-r--r--bottleneck/tests/data/test_111_B2
-rw-r--r--bottleneck/tests/data/test_112_A2
-rw-r--r--bottleneck/tests/data/test_112_B2
-rw-r--r--bottleneck/tests/data/test_113_A2
-rw-r--r--bottleneck/tests/data/test_113_B2
-rw-r--r--bottleneck/tests/data/test_114_A2
-rw-r--r--bottleneck/tests/data/test_114_B2
-rw-r--r--bottleneck/tests/data/test_115_A2
-rw-r--r--bottleneck/tests/data/test_115_B2
-rw-r--r--bottleneck/tests/data/test_116_A2
-rw-r--r--bottleneck/tests/data/test_116_B2
-rw-r--r--bottleneck/tests/data/test_117_A2
-rw-r--r--bottleneck/tests/data/test_117_B2
-rw-r--r--bottleneck/tests/data/test_118_A2
-rw-r--r--bottleneck/tests/data/test_118_B2
-rw-r--r--bottleneck/tests/data/test_119_A2
-rw-r--r--bottleneck/tests/data/test_119_B2
-rw-r--r--bottleneck/tests/data/test_120_A3
-rw-r--r--bottleneck/tests/data/test_120_B3
-rw-r--r--bottleneck/tests/data/test_121_A3
-rw-r--r--bottleneck/tests/data/test_121_B3
-rw-r--r--bottleneck/tests/data/test_122_A3
-rw-r--r--bottleneck/tests/data/test_122_B3
-rw-r--r--bottleneck/tests/data/test_123_A3
-rw-r--r--bottleneck/tests/data/test_123_B3
-rw-r--r--bottleneck/tests/data/test_124_A3
-rw-r--r--bottleneck/tests/data/test_124_B3
-rw-r--r--bottleneck/tests/data/test_125_A3
-rw-r--r--bottleneck/tests/data/test_125_B3
-rw-r--r--bottleneck/tests/data/test_126_A3
-rw-r--r--bottleneck/tests/data/test_126_B3
-rw-r--r--bottleneck/tests/data/test_127_A3
-rw-r--r--bottleneck/tests/data/test_127_B3
-rw-r--r--bottleneck/tests/data/test_128_A3
-rw-r--r--bottleneck/tests/data/test_128_B3
-rw-r--r--bottleneck/tests/data/test_129_A3
-rw-r--r--bottleneck/tests/data/test_129_B3
-rw-r--r--bottleneck/tests/data/test_130_A3
-rw-r--r--bottleneck/tests/data/test_130_B3
-rw-r--r--bottleneck/tests/data/test_131_A3
-rw-r--r--bottleneck/tests/data/test_131_B3
-rw-r--r--bottleneck/tests/data/test_132_A3
-rw-r--r--bottleneck/tests/data/test_132_B3
-rw-r--r--bottleneck/tests/data/test_133_A3
-rw-r--r--bottleneck/tests/data/test_133_B3
-rw-r--r--bottleneck/tests/data/test_134_A3
-rw-r--r--bottleneck/tests/data/test_134_B3
-rw-r--r--bottleneck/tests/data/test_135_A3
-rw-r--r--bottleneck/tests/data/test_135_B3
-rw-r--r--bottleneck/tests/data/test_136_A3
-rw-r--r--bottleneck/tests/data/test_136_B3
-rw-r--r--bottleneck/tests/data/test_137_A3
-rw-r--r--bottleneck/tests/data/test_137_B3
-rw-r--r--bottleneck/tests/data/test_138_A3
-rw-r--r--bottleneck/tests/data/test_138_B3
-rw-r--r--bottleneck/tests/data/test_139_A3
-rw-r--r--bottleneck/tests/data/test_139_B3
-rw-r--r--bottleneck/tests/data/test_140_A4
-rw-r--r--bottleneck/tests/data/test_140_B4
-rw-r--r--bottleneck/tests/data/test_141_A4
-rw-r--r--bottleneck/tests/data/test_141_B4
-rw-r--r--bottleneck/tests/data/test_142_A4
-rw-r--r--bottleneck/tests/data/test_142_B4
-rw-r--r--bottleneck/tests/data/test_143_A4
-rw-r--r--bottleneck/tests/data/test_143_B4
-rw-r--r--bottleneck/tests/data/test_144_A4
-rw-r--r--bottleneck/tests/data/test_144_B4
-rw-r--r--bottleneck/tests/data/test_145_A4
-rw-r--r--bottleneck/tests/data/test_145_B4
-rw-r--r--bottleneck/tests/data/test_146_A4
-rw-r--r--bottleneck/tests/data/test_146_B4
-rw-r--r--bottleneck/tests/data/test_147_A4
-rw-r--r--bottleneck/tests/data/test_147_B4
-rw-r--r--bottleneck/tests/data/test_148_A4
-rw-r--r--bottleneck/tests/data/test_148_B4
-rw-r--r--bottleneck/tests/data/test_149_A4
-rw-r--r--bottleneck/tests/data/test_149_B4
-rw-r--r--bottleneck/tests/data/test_150_A4
-rw-r--r--bottleneck/tests/data/test_150_B4
-rw-r--r--bottleneck/tests/data/test_151_A4
-rw-r--r--bottleneck/tests/data/test_151_B4
-rw-r--r--bottleneck/tests/data/test_152_A4
-rw-r--r--bottleneck/tests/data/test_152_B4
-rw-r--r--bottleneck/tests/data/test_153_A4
-rw-r--r--bottleneck/tests/data/test_153_B4
-rw-r--r--bottleneck/tests/data/test_154_A4
-rw-r--r--bottleneck/tests/data/test_154_B4
-rw-r--r--bottleneck/tests/data/test_155_A4
-rw-r--r--bottleneck/tests/data/test_155_B4
-rw-r--r--bottleneck/tests/data/test_156_A4
-rw-r--r--bottleneck/tests/data/test_156_B4
-rw-r--r--bottleneck/tests/data/test_157_A4
-rw-r--r--bottleneck/tests/data/test_157_B4
-rw-r--r--bottleneck/tests/data/test_158_A4
-rw-r--r--bottleneck/tests/data/test_158_B4
-rw-r--r--bottleneck/tests/data/test_159_A4
-rw-r--r--bottleneck/tests/data/test_159_B4
-rw-r--r--bottleneck/tests/data/test_160_A5
-rw-r--r--bottleneck/tests/data/test_160_B5
-rw-r--r--bottleneck/tests/data/test_161_A5
-rw-r--r--bottleneck/tests/data/test_161_B5
-rw-r--r--bottleneck/tests/data/test_162_A5
-rw-r--r--bottleneck/tests/data/test_162_B5
-rw-r--r--bottleneck/tests/data/test_163_A5
-rw-r--r--bottleneck/tests/data/test_163_B5
-rw-r--r--bottleneck/tests/data/test_164_A5
-rw-r--r--bottleneck/tests/data/test_164_B5
-rw-r--r--bottleneck/tests/data/test_165_A5
-rw-r--r--bottleneck/tests/data/test_165_B5
-rw-r--r--bottleneck/tests/data/test_166_A5
-rw-r--r--bottleneck/tests/data/test_166_B5
-rw-r--r--bottleneck/tests/data/test_167_A5
-rw-r--r--bottleneck/tests/data/test_167_B5
-rw-r--r--bottleneck/tests/data/test_168_A5
-rw-r--r--bottleneck/tests/data/test_168_B5
-rw-r--r--bottleneck/tests/data/test_169_A5
-rw-r--r--bottleneck/tests/data/test_169_B5
-rw-r--r--bottleneck/tests/data/test_170_A5
-rw-r--r--bottleneck/tests/data/test_170_B5
-rw-r--r--bottleneck/tests/data/test_171_A5
-rw-r--r--bottleneck/tests/data/test_171_B5
-rw-r--r--bottleneck/tests/data/test_172_A5
-rw-r--r--bottleneck/tests/data/test_172_B5
-rw-r--r--bottleneck/tests/data/test_173_A5
-rw-r--r--bottleneck/tests/data/test_173_B5
-rw-r--r--bottleneck/tests/data/test_174_A5
-rw-r--r--bottleneck/tests/data/test_174_B5
-rw-r--r--bottleneck/tests/data/test_175_A5
-rw-r--r--bottleneck/tests/data/test_175_B5
-rw-r--r--bottleneck/tests/data/test_176_A5
-rw-r--r--bottleneck/tests/data/test_176_B5
-rw-r--r--bottleneck/tests/data/test_177_A5
-rw-r--r--bottleneck/tests/data/test_177_B5
-rw-r--r--bottleneck/tests/data/test_178_A5
-rw-r--r--bottleneck/tests/data/test_178_B5
-rw-r--r--bottleneck/tests/data/test_179_A5
-rw-r--r--bottleneck/tests/data/test_179_B5
-rw-r--r--bottleneck/tests/data/test_180_A6
-rw-r--r--bottleneck/tests/data/test_180_B6
-rw-r--r--bottleneck/tests/data/test_181_A6
-rw-r--r--bottleneck/tests/data/test_181_B6
-rw-r--r--bottleneck/tests/data/test_182_A6
-rw-r--r--bottleneck/tests/data/test_182_B6
-rw-r--r--bottleneck/tests/data/test_183_A6
-rw-r--r--bottleneck/tests/data/test_183_B6
-rw-r--r--bottleneck/tests/data/test_184_A6
-rw-r--r--bottleneck/tests/data/test_184_B6
-rw-r--r--bottleneck/tests/data/test_185_A6
-rw-r--r--bottleneck/tests/data/test_185_B6
-rw-r--r--bottleneck/tests/data/test_186_A6
-rw-r--r--bottleneck/tests/data/test_186_B6
-rw-r--r--bottleneck/tests/data/test_187_A6
-rw-r--r--bottleneck/tests/data/test_187_B6
-rw-r--r--bottleneck/tests/data/test_188_A6
-rw-r--r--bottleneck/tests/data/test_188_B6
-rw-r--r--bottleneck/tests/data/test_189_A6
-rw-r--r--bottleneck/tests/data/test_189_B6
-rw-r--r--bottleneck/tests/data/test_190_A6
-rw-r--r--bottleneck/tests/data/test_190_B6
-rw-r--r--bottleneck/tests/data/test_191_A6
-rw-r--r--bottleneck/tests/data/test_191_B6
-rw-r--r--bottleneck/tests/data/test_192_A6
-rw-r--r--bottleneck/tests/data/test_192_B6
-rw-r--r--bottleneck/tests/data/test_193_A6
-rw-r--r--bottleneck/tests/data/test_193_B6
-rw-r--r--bottleneck/tests/data/test_194_A6
-rw-r--r--bottleneck/tests/data/test_194_B6
-rw-r--r--bottleneck/tests/data/test_195_A6
-rw-r--r--bottleneck/tests/data/test_195_B6
-rw-r--r--bottleneck/tests/data/test_196_A6
-rw-r--r--bottleneck/tests/data/test_196_B6
-rw-r--r--bottleneck/tests/data/test_197_A6
-rw-r--r--bottleneck/tests/data/test_197_B6
-rw-r--r--bottleneck/tests/data/test_198_A6
-rw-r--r--bottleneck/tests/data/test_198_B6
-rw-r--r--bottleneck/tests/data/test_199_A6
-rw-r--r--bottleneck/tests/data/test_199_B6
-rw-r--r--bottleneck/tests/data/test_200_A7
-rw-r--r--bottleneck/tests/data/test_200_B7
-rw-r--r--bottleneck/tests/data/test_201_A7
-rw-r--r--bottleneck/tests/data/test_201_B7
-rw-r--r--bottleneck/tests/data/test_202_A7
-rw-r--r--bottleneck/tests/data/test_202_B7
-rw-r--r--bottleneck/tests/data/test_203_A7
-rw-r--r--bottleneck/tests/data/test_203_B7
-rw-r--r--bottleneck/tests/data/test_204_A7
-rw-r--r--bottleneck/tests/data/test_204_B7
-rw-r--r--bottleneck/tests/data/test_205_A7
-rw-r--r--bottleneck/tests/data/test_205_B7
-rw-r--r--bottleneck/tests/data/test_206_A7
-rw-r--r--bottleneck/tests/data/test_206_B7
-rw-r--r--bottleneck/tests/data/test_207_A7
-rw-r--r--bottleneck/tests/data/test_207_B7
-rw-r--r--bottleneck/tests/data/test_208_A7
-rw-r--r--bottleneck/tests/data/test_208_B7
-rw-r--r--bottleneck/tests/data/test_209_A7
-rw-r--r--bottleneck/tests/data/test_209_B7
-rw-r--r--bottleneck/tests/data/test_210_A7
-rw-r--r--bottleneck/tests/data/test_210_B7
-rw-r--r--bottleneck/tests/data/test_211_A7
-rw-r--r--bottleneck/tests/data/test_211_B7
-rw-r--r--bottleneck/tests/data/test_212_A7
-rw-r--r--bottleneck/tests/data/test_212_B7
-rw-r--r--bottleneck/tests/data/test_213_A7
-rw-r--r--bottleneck/tests/data/test_213_B7
-rw-r--r--bottleneck/tests/data/test_214_A7
-rw-r--r--bottleneck/tests/data/test_214_B7
-rw-r--r--bottleneck/tests/data/test_215_A7
-rw-r--r--bottleneck/tests/data/test_215_B7
-rw-r--r--bottleneck/tests/data/test_216_A7
-rw-r--r--bottleneck/tests/data/test_216_B7
-rw-r--r--bottleneck/tests/data/test_217_A7
-rw-r--r--bottleneck/tests/data/test_217_B7
-rw-r--r--bottleneck/tests/data/test_218_A7
-rw-r--r--bottleneck/tests/data/test_218_B7
-rw-r--r--bottleneck/tests/data/test_219_A7
-rw-r--r--bottleneck/tests/data/test_219_B7
-rw-r--r--bottleneck/tests/data/test_220_A8
-rw-r--r--bottleneck/tests/data/test_220_B8
-rw-r--r--bottleneck/tests/data/test_221_A8
-rw-r--r--bottleneck/tests/data/test_221_B8
-rw-r--r--bottleneck/tests/data/test_222_A8
-rw-r--r--bottleneck/tests/data/test_222_B8
-rw-r--r--bottleneck/tests/data/test_223_A8
-rw-r--r--bottleneck/tests/data/test_223_B8
-rw-r--r--bottleneck/tests/data/test_224_A8
-rw-r--r--bottleneck/tests/data/test_224_B8
-rw-r--r--bottleneck/tests/data/test_225_A8
-rw-r--r--bottleneck/tests/data/test_225_B8
-rw-r--r--bottleneck/tests/data/test_226_A8
-rw-r--r--bottleneck/tests/data/test_226_B8
-rw-r--r--bottleneck/tests/data/test_227_A8
-rw-r--r--bottleneck/tests/data/test_227_B8
-rw-r--r--bottleneck/tests/data/test_228_A8
-rw-r--r--bottleneck/tests/data/test_228_B8
-rw-r--r--bottleneck/tests/data/test_229_A8
-rw-r--r--bottleneck/tests/data/test_229_B8
-rw-r--r--bottleneck/tests/data/test_230_A8
-rw-r--r--bottleneck/tests/data/test_230_B8
-rw-r--r--bottleneck/tests/data/test_231_A8
-rw-r--r--bottleneck/tests/data/test_231_B8
-rw-r--r--bottleneck/tests/data/test_232_A8
-rw-r--r--bottleneck/tests/data/test_232_B8
-rw-r--r--bottleneck/tests/data/test_233_A8
-rw-r--r--bottleneck/tests/data/test_233_B8
-rw-r--r--bottleneck/tests/data/test_234_A8
-rw-r--r--bottleneck/tests/data/test_234_B8
-rw-r--r--bottleneck/tests/data/test_235_A8
-rw-r--r--bottleneck/tests/data/test_235_B8
-rw-r--r--bottleneck/tests/data/test_236_A8
-rw-r--r--bottleneck/tests/data/test_236_B8
-rw-r--r--bottleneck/tests/data/test_237_A8
-rw-r--r--bottleneck/tests/data/test_237_B8
-rw-r--r--bottleneck/tests/data/test_238_A8
-rw-r--r--bottleneck/tests/data/test_238_B8
-rw-r--r--bottleneck/tests/data/test_239_A8
-rw-r--r--bottleneck/tests/data/test_239_B8
-rw-r--r--bottleneck/tests/data/test_240_A9
-rw-r--r--bottleneck/tests/data/test_240_B9
-rw-r--r--bottleneck/tests/data/test_241_A9
-rw-r--r--bottleneck/tests/data/test_241_B9
-rw-r--r--bottleneck/tests/data/test_242_A9
-rw-r--r--bottleneck/tests/data/test_242_B9
-rw-r--r--bottleneck/tests/data/test_243_A9
-rw-r--r--bottleneck/tests/data/test_243_B9
-rw-r--r--bottleneck/tests/data/test_244_A9
-rw-r--r--bottleneck/tests/data/test_244_B9
-rw-r--r--bottleneck/tests/data/test_245_A9
-rw-r--r--bottleneck/tests/data/test_245_B9
-rw-r--r--bottleneck/tests/data/test_246_A9
-rw-r--r--bottleneck/tests/data/test_246_B9
-rw-r--r--bottleneck/tests/data/test_247_A9
-rw-r--r--bottleneck/tests/data/test_247_B9
-rw-r--r--bottleneck/tests/data/test_248_A9
-rw-r--r--bottleneck/tests/data/test_248_B9
-rw-r--r--bottleneck/tests/data/test_249_A9
-rw-r--r--bottleneck/tests/data/test_249_B9
-rw-r--r--bottleneck/tests/data/test_250_A9
-rw-r--r--bottleneck/tests/data/test_250_B9
-rw-r--r--bottleneck/tests/data/test_251_A9
-rw-r--r--bottleneck/tests/data/test_251_B9
-rw-r--r--bottleneck/tests/data/test_252_A9
-rw-r--r--bottleneck/tests/data/test_252_B9
-rw-r--r--bottleneck/tests/data/test_253_A9
-rw-r--r--bottleneck/tests/data/test_253_B9
-rw-r--r--bottleneck/tests/data/test_254_A9
-rw-r--r--bottleneck/tests/data/test_254_B9
-rw-r--r--bottleneck/tests/data/test_255_A9
-rw-r--r--bottleneck/tests/data/test_255_B9
-rw-r--r--bottleneck/tests/data/test_256_A9
-rw-r--r--bottleneck/tests/data/test_256_B9
-rw-r--r--bottleneck/tests/data/test_257_A9
-rw-r--r--bottleneck/tests/data/test_257_B9
-rw-r--r--bottleneck/tests/data/test_258_A9
-rw-r--r--bottleneck/tests/data/test_258_B9
-rw-r--r--bottleneck/tests/data/test_259_A9
-rw-r--r--bottleneck/tests/data/test_259_B9
-rw-r--r--bottleneck/tests/data/test_260_A10
-rw-r--r--bottleneck/tests/data/test_260_B10
-rw-r--r--bottleneck/tests/data/test_261_A10
-rw-r--r--bottleneck/tests/data/test_261_B10
-rw-r--r--bottleneck/tests/data/test_262_A10
-rw-r--r--bottleneck/tests/data/test_262_B10
-rw-r--r--bottleneck/tests/data/test_263_A10
-rw-r--r--bottleneck/tests/data/test_263_B10
-rw-r--r--bottleneck/tests/data/test_264_A10
-rw-r--r--bottleneck/tests/data/test_264_B10
-rw-r--r--bottleneck/tests/data/test_265_A10
-rw-r--r--bottleneck/tests/data/test_265_B10
-rw-r--r--bottleneck/tests/data/test_266_A10
-rw-r--r--bottleneck/tests/data/test_266_B10
-rw-r--r--bottleneck/tests/data/test_267_A10
-rw-r--r--bottleneck/tests/data/test_267_B10
-rw-r--r--bottleneck/tests/data/test_268_A10
-rw-r--r--bottleneck/tests/data/test_268_B10
-rw-r--r--bottleneck/tests/data/test_269_A10
-rw-r--r--bottleneck/tests/data/test_269_B10
-rw-r--r--bottleneck/tests/data/test_270_A10
-rw-r--r--bottleneck/tests/data/test_270_B10
-rw-r--r--bottleneck/tests/data/test_271_A10
-rw-r--r--bottleneck/tests/data/test_271_B10
-rw-r--r--bottleneck/tests/data/test_272_A10
-rw-r--r--bottleneck/tests/data/test_272_B10
-rw-r--r--bottleneck/tests/data/test_273_A10
-rw-r--r--bottleneck/tests/data/test_273_B10
-rw-r--r--bottleneck/tests/data/test_274_A10
-rw-r--r--bottleneck/tests/data/test_274_B10
-rw-r--r--bottleneck/tests/data/test_275_A10
-rw-r--r--bottleneck/tests/data/test_275_B10
-rw-r--r--bottleneck/tests/data/test_276_A10
-rw-r--r--bottleneck/tests/data/test_276_B10
-rw-r--r--bottleneck/tests/data/test_277_A10
-rw-r--r--bottleneck/tests/data/test_277_B10
-rw-r--r--bottleneck/tests/data/test_278_A10
-rw-r--r--bottleneck/tests/data/test_278_B10
-rw-r--r--bottleneck/tests/data/test_279_A10
-rw-r--r--bottleneck/tests/data/test_279_B10
-rw-r--r--bottleneck/tests/data/test_280_A20
-rw-r--r--bottleneck/tests/data/test_280_B20
-rw-r--r--bottleneck/tests/data/test_281_A20
-rw-r--r--bottleneck/tests/data/test_281_B20
-rw-r--r--bottleneck/tests/data/test_282_A20
-rw-r--r--bottleneck/tests/data/test_282_B20
-rw-r--r--bottleneck/tests/data/test_283_A20
-rw-r--r--bottleneck/tests/data/test_283_B20
-rw-r--r--bottleneck/tests/data/test_284_A20
-rw-r--r--bottleneck/tests/data/test_284_B20
-rw-r--r--bottleneck/tests/data/test_285_A20
-rw-r--r--bottleneck/tests/data/test_285_B20
-rw-r--r--bottleneck/tests/data/test_286_A20
-rw-r--r--bottleneck/tests/data/test_286_B20
-rw-r--r--bottleneck/tests/data/test_287_A20
-rw-r--r--bottleneck/tests/data/test_287_B20
-rw-r--r--bottleneck/tests/data/test_288_A20
-rw-r--r--bottleneck/tests/data/test_288_B20
-rw-r--r--bottleneck/tests/data/test_289_A20
-rw-r--r--bottleneck/tests/data/test_289_B20
-rw-r--r--bottleneck/tests/data/test_290_A20
-rw-r--r--bottleneck/tests/data/test_290_B20
-rw-r--r--bottleneck/tests/data/test_291_A20
-rw-r--r--bottleneck/tests/data/test_291_B20
-rw-r--r--bottleneck/tests/data/test_292_A20
-rw-r--r--bottleneck/tests/data/test_292_B20
-rw-r--r--bottleneck/tests/data/test_293_A20
-rw-r--r--bottleneck/tests/data/test_293_B20
-rw-r--r--bottleneck/tests/data/test_294_A20
-rw-r--r--bottleneck/tests/data/test_294_B20
-rw-r--r--bottleneck/tests/data/test_295_A20
-rw-r--r--bottleneck/tests/data/test_295_B20
-rw-r--r--bottleneck/tests/data/test_296_A20
-rw-r--r--bottleneck/tests/data/test_296_B20
-rw-r--r--bottleneck/tests/data/test_297_A20
-rw-r--r--bottleneck/tests/data/test_297_B20
-rw-r--r--bottleneck/tests/data/test_298_A20
-rw-r--r--bottleneck/tests/data/test_298_B20
-rw-r--r--bottleneck/tests/data/test_299_A20
-rw-r--r--bottleneck/tests/data/test_299_B20
-rw-r--r--bottleneck/tests/data/test_300_A30
-rw-r--r--bottleneck/tests/data/test_300_B30
-rw-r--r--bottleneck/tests/data/test_301_A30
-rw-r--r--bottleneck/tests/data/test_301_B30
-rw-r--r--bottleneck/tests/data/test_302_A30
-rw-r--r--bottleneck/tests/data/test_302_B30
-rw-r--r--bottleneck/tests/data/test_303_A30
-rw-r--r--bottleneck/tests/data/test_303_B30
-rw-r--r--bottleneck/tests/data/test_304_A30
-rw-r--r--bottleneck/tests/data/test_304_B30
-rw-r--r--bottleneck/tests/data/test_305_A30
-rw-r--r--bottleneck/tests/data/test_305_B30
-rw-r--r--bottleneck/tests/data/test_306_A30
-rw-r--r--bottleneck/tests/data/test_306_B30
-rw-r--r--bottleneck/tests/data/test_307_A30
-rw-r--r--bottleneck/tests/data/test_307_B30
-rw-r--r--bottleneck/tests/data/test_308_A30
-rw-r--r--bottleneck/tests/data/test_308_B30
-rw-r--r--bottleneck/tests/data/test_309_A30
-rw-r--r--bottleneck/tests/data/test_309_B30
-rw-r--r--bottleneck/tests/data/test_310_A30
-rw-r--r--bottleneck/tests/data/test_310_B30
-rw-r--r--bottleneck/tests/data/test_311_A30
-rw-r--r--bottleneck/tests/data/test_311_B30
-rw-r--r--bottleneck/tests/data/test_312_A30
-rw-r--r--bottleneck/tests/data/test_312_B30
-rw-r--r--bottleneck/tests/data/test_313_A30
-rw-r--r--bottleneck/tests/data/test_313_B30
-rw-r--r--bottleneck/tests/data/test_314_A30
-rw-r--r--bottleneck/tests/data/test_314_B30
-rw-r--r--bottleneck/tests/data/test_315_A30
-rw-r--r--bottleneck/tests/data/test_315_B30
-rw-r--r--bottleneck/tests/data/test_316_A30
-rw-r--r--bottleneck/tests/data/test_316_B30
-rw-r--r--bottleneck/tests/data/test_317_A30
-rw-r--r--bottleneck/tests/data/test_317_B30
-rw-r--r--bottleneck/tests/data/test_318_A30
-rw-r--r--bottleneck/tests/data/test_318_B30
-rw-r--r--bottleneck/tests/data/test_319_A30
-rw-r--r--bottleneck/tests/data/test_319_B30
-rw-r--r--bottleneck/tests/data/test_320_A50
-rw-r--r--bottleneck/tests/data/test_320_B50
-rw-r--r--bottleneck/tests/data/test_321_A50
-rw-r--r--bottleneck/tests/data/test_321_B50
-rw-r--r--bottleneck/tests/data/test_322_A50
-rw-r--r--bottleneck/tests/data/test_322_B50
-rw-r--r--bottleneck/tests/data/test_323_A50
-rw-r--r--bottleneck/tests/data/test_323_B50
-rw-r--r--bottleneck/tests/data/test_324_A50
-rw-r--r--bottleneck/tests/data/test_324_B50
-rw-r--r--bottleneck/tests/data/test_325_A50
-rw-r--r--bottleneck/tests/data/test_325_B50
-rw-r--r--bottleneck/tests/data/test_326_A50
-rw-r--r--bottleneck/tests/data/test_326_B50
-rw-r--r--bottleneck/tests/data/test_327_A50
-rw-r--r--bottleneck/tests/data/test_327_B50
-rw-r--r--bottleneck/tests/data/test_328_A50
-rw-r--r--bottleneck/tests/data/test_328_B50
-rw-r--r--bottleneck/tests/data/test_329_A50
-rw-r--r--bottleneck/tests/data/test_329_B50
-rw-r--r--bottleneck/tests/data/test_330_A50
-rw-r--r--bottleneck/tests/data/test_330_B50
-rw-r--r--bottleneck/tests/data/test_331_A50
-rw-r--r--bottleneck/tests/data/test_331_B50
-rw-r--r--bottleneck/tests/data/test_332_A50
-rw-r--r--bottleneck/tests/data/test_332_B50
-rw-r--r--bottleneck/tests/data/test_333_A50
-rw-r--r--bottleneck/tests/data/test_333_B50
-rw-r--r--bottleneck/tests/data/test_334_A50
-rw-r--r--bottleneck/tests/data/test_334_B50
-rw-r--r--bottleneck/tests/data/test_335_A50
-rw-r--r--bottleneck/tests/data/test_335_B50
-rw-r--r--bottleneck/tests/data/test_336_A50
-rw-r--r--bottleneck/tests/data/test_336_B50
-rw-r--r--bottleneck/tests/data/test_337_A50
-rw-r--r--bottleneck/tests/data/test_337_B50
-rw-r--r--bottleneck/tests/data/test_338_A50
-rw-r--r--bottleneck/tests/data/test_338_B50
-rw-r--r--bottleneck/tests/data/test_339_A50
-rw-r--r--bottleneck/tests/data/test_339_B50
-rw-r--r--bottleneck/tests/data/test_340_A100
-rw-r--r--bottleneck/tests/data/test_340_B100
-rw-r--r--bottleneck/tests/data/test_341_A100
-rw-r--r--bottleneck/tests/data/test_341_B100
-rw-r--r--bottleneck/tests/data/test_342_A100
-rw-r--r--bottleneck/tests/data/test_342_B100
-rw-r--r--bottleneck/tests/data/test_343_A100
-rw-r--r--bottleneck/tests/data/test_343_B100
-rw-r--r--bottleneck/tests/data/test_344_A100
-rw-r--r--bottleneck/tests/data/test_344_B100
-rw-r--r--bottleneck/tests/data/test_345_A100
-rw-r--r--bottleneck/tests/data/test_345_B100
-rw-r--r--bottleneck/tests/data/test_346_A100
-rw-r--r--bottleneck/tests/data/test_346_B100
-rw-r--r--bottleneck/tests/data/test_347_A100
-rw-r--r--bottleneck/tests/data/test_347_B100
-rw-r--r--bottleneck/tests/data/test_348_A100
-rw-r--r--bottleneck/tests/data/test_348_B100
-rw-r--r--bottleneck/tests/data/test_349_A100
-rw-r--r--bottleneck/tests/data/test_349_B100
-rw-r--r--bottleneck/tests/data/test_350_A100
-rw-r--r--bottleneck/tests/data/test_350_B100
-rw-r--r--bottleneck/tests/data/test_351_A100
-rw-r--r--bottleneck/tests/data/test_351_B100
-rw-r--r--bottleneck/tests/data/test_352_A100
-rw-r--r--bottleneck/tests/data/test_352_B100
-rw-r--r--bottleneck/tests/data/test_353_A100
-rw-r--r--bottleneck/tests/data/test_353_B100
-rw-r--r--bottleneck/tests/data/test_354_A100
-rw-r--r--bottleneck/tests/data/test_354_B100
-rw-r--r--bottleneck/tests/data/test_355_A100
-rw-r--r--bottleneck/tests/data/test_355_B100
-rw-r--r--bottleneck/tests/data/test_356_A100
-rw-r--r--bottleneck/tests/data/test_356_B100
-rw-r--r--bottleneck/tests/data/test_357_A100
-rw-r--r--bottleneck/tests/data/test_357_B100
-rw-r--r--bottleneck/tests/data/test_358_A100
-rw-r--r--bottleneck/tests/data/test_358_B100
-rw-r--r--bottleneck/tests/data/test_359_A100
-rw-r--r--bottleneck/tests/data/test_359_B100
-rw-r--r--bottleneck/tests/data/test_360_A2
-rw-r--r--bottleneck/tests/data/test_360_B2
-rw-r--r--bottleneck/tests/data/test_361_A2
-rw-r--r--bottleneck/tests/data/test_361_B2
-rw-r--r--bottleneck/tests/data/test_362_A2
-rw-r--r--bottleneck/tests/data/test_362_B2
-rw-r--r--bottleneck/tests/data/test_363_A2
-rw-r--r--bottleneck/tests/data/test_363_B2
-rw-r--r--bottleneck/tests/data/test_364_A2
-rw-r--r--bottleneck/tests/data/test_364_B2
-rw-r--r--bottleneck/tests/data/test_365_A2
-rw-r--r--bottleneck/tests/data/test_365_B2
-rw-r--r--bottleneck/tests/data/test_366_A2
-rw-r--r--bottleneck/tests/data/test_366_B2
-rw-r--r--bottleneck/tests/data/test_367_A2
-rw-r--r--bottleneck/tests/data/test_367_B2
-rw-r--r--bottleneck/tests/data/test_368_A2
-rw-r--r--bottleneck/tests/data/test_368_B2
-rw-r--r--bottleneck/tests/data/test_369_A2
-rw-r--r--bottleneck/tests/data/test_369_B2
-rw-r--r--bottleneck/tests/data/test_370_A2
-rw-r--r--bottleneck/tests/data/test_370_B2
-rw-r--r--bottleneck/tests/data/test_371_A2
-rw-r--r--bottleneck/tests/data/test_371_B2
-rw-r--r--bottleneck/tests/data/test_372_A2
-rw-r--r--bottleneck/tests/data/test_372_B2
-rw-r--r--bottleneck/tests/data/test_373_A2
-rw-r--r--bottleneck/tests/data/test_373_B2
-rw-r--r--bottleneck/tests/data/test_374_A2
-rw-r--r--bottleneck/tests/data/test_374_B2
-rw-r--r--bottleneck/tests/data/test_375_A2
-rw-r--r--bottleneck/tests/data/test_375_B2
-rw-r--r--bottleneck/tests/data/test_376_A2
-rw-r--r--bottleneck/tests/data/test_376_B2
-rw-r--r--bottleneck/tests/data/test_377_A2
-rw-r--r--bottleneck/tests/data/test_377_B2
-rw-r--r--bottleneck/tests/data/test_378_A2
-rw-r--r--bottleneck/tests/data/test_378_B2
-rw-r--r--bottleneck/tests/data/test_379_A2
-rw-r--r--bottleneck/tests/data/test_379_B2
-rw-r--r--bottleneck/tests/data/test_380_A3
-rw-r--r--bottleneck/tests/data/test_380_B3
-rw-r--r--bottleneck/tests/data/test_381_A3
-rw-r--r--bottleneck/tests/data/test_381_B3
-rw-r--r--bottleneck/tests/data/test_382_A3
-rw-r--r--bottleneck/tests/data/test_382_B3
-rw-r--r--bottleneck/tests/data/test_383_A3
-rw-r--r--bottleneck/tests/data/test_383_B3
-rw-r--r--bottleneck/tests/data/test_384_A3
-rw-r--r--bottleneck/tests/data/test_384_B3
-rw-r--r--bottleneck/tests/data/test_385_A3
-rw-r--r--bottleneck/tests/data/test_385_B3
-rw-r--r--bottleneck/tests/data/test_386_A3
-rw-r--r--bottleneck/tests/data/test_386_B3
-rw-r--r--bottleneck/tests/data/test_387_A3
-rw-r--r--bottleneck/tests/data/test_387_B3
-rw-r--r--bottleneck/tests/data/test_388_A3
-rw-r--r--bottleneck/tests/data/test_388_B3
-rw-r--r--bottleneck/tests/data/test_389_A3
-rw-r--r--bottleneck/tests/data/test_389_B3
-rw-r--r--bottleneck/tests/data/test_390_A3
-rw-r--r--bottleneck/tests/data/test_390_B3
-rw-r--r--bottleneck/tests/data/test_391_A3
-rw-r--r--bottleneck/tests/data/test_391_B3
-rw-r--r--bottleneck/tests/data/test_392_A3
-rw-r--r--bottleneck/tests/data/test_392_B3
-rw-r--r--bottleneck/tests/data/test_393_A3
-rw-r--r--bottleneck/tests/data/test_393_B3
-rw-r--r--bottleneck/tests/data/test_394_A3
-rw-r--r--bottleneck/tests/data/test_394_B3
-rw-r--r--bottleneck/tests/data/test_395_A3
-rw-r--r--bottleneck/tests/data/test_395_B3
-rw-r--r--bottleneck/tests/data/test_396_A3
-rw-r--r--bottleneck/tests/data/test_396_B3
-rw-r--r--bottleneck/tests/data/test_397_A3
-rw-r--r--bottleneck/tests/data/test_397_B3
-rw-r--r--bottleneck/tests/data/test_398_A3
-rw-r--r--bottleneck/tests/data/test_398_B3
-rw-r--r--bottleneck/tests/data/test_399_A3
-rw-r--r--bottleneck/tests/data/test_399_B3
-rw-r--r--bottleneck/tests/data/test_400_A4
-rw-r--r--bottleneck/tests/data/test_400_B4
-rw-r--r--bottleneck/tests/data/test_401_A4
-rw-r--r--bottleneck/tests/data/test_401_B4
-rw-r--r--bottleneck/tests/data/test_402_A4
-rw-r--r--bottleneck/tests/data/test_402_B4
-rw-r--r--bottleneck/tests/data/test_403_A4
-rw-r--r--bottleneck/tests/data/test_403_B4
-rw-r--r--bottleneck/tests/data/test_404_A4
-rw-r--r--bottleneck/tests/data/test_404_B4
-rw-r--r--bottleneck/tests/data/test_405_A4
-rw-r--r--bottleneck/tests/data/test_405_B4
-rw-r--r--bottleneck/tests/data/test_406_A4
-rw-r--r--bottleneck/tests/data/test_406_B4
-rw-r--r--bottleneck/tests/data/test_407_A4
-rw-r--r--bottleneck/tests/data/test_407_B4
-rw-r--r--bottleneck/tests/data/test_408_A4
-rw-r--r--bottleneck/tests/data/test_408_B4
-rw-r--r--bottleneck/tests/data/test_409_A4
-rw-r--r--bottleneck/tests/data/test_409_B4
-rw-r--r--bottleneck/tests/data/test_410_A4
-rw-r--r--bottleneck/tests/data/test_410_B4
-rw-r--r--bottleneck/tests/data/test_411_A4
-rw-r--r--bottleneck/tests/data/test_411_B4
-rw-r--r--bottleneck/tests/data/test_412_A4
-rw-r--r--bottleneck/tests/data/test_412_B4
-rw-r--r--bottleneck/tests/data/test_413_A4
-rw-r--r--bottleneck/tests/data/test_413_B4
-rw-r--r--bottleneck/tests/data/test_414_A4
-rw-r--r--bottleneck/tests/data/test_414_B4
-rw-r--r--bottleneck/tests/data/test_415_A4
-rw-r--r--bottleneck/tests/data/test_415_B4
-rw-r--r--bottleneck/tests/data/test_416_A4
-rw-r--r--bottleneck/tests/data/test_416_B4
-rw-r--r--bottleneck/tests/data/test_417_A4
-rw-r--r--bottleneck/tests/data/test_417_B4
-rw-r--r--bottleneck/tests/data/test_418_A4
-rw-r--r--bottleneck/tests/data/test_418_B4
-rw-r--r--bottleneck/tests/data/test_419_A4
-rw-r--r--bottleneck/tests/data/test_419_B4
-rw-r--r--bottleneck/tests/data/test_420_A5
-rw-r--r--bottleneck/tests/data/test_420_B5
-rw-r--r--bottleneck/tests/data/test_421_A5
-rw-r--r--bottleneck/tests/data/test_421_B5
-rw-r--r--bottleneck/tests/data/test_422_A5
-rw-r--r--bottleneck/tests/data/test_422_B5
-rw-r--r--bottleneck/tests/data/test_423_A5
-rw-r--r--bottleneck/tests/data/test_423_B5
-rw-r--r--bottleneck/tests/data/test_424_A5
-rw-r--r--bottleneck/tests/data/test_424_B5
-rw-r--r--bottleneck/tests/data/test_425_A5
-rw-r--r--bottleneck/tests/data/test_425_B5
-rw-r--r--bottleneck/tests/data/test_426_A5
-rw-r--r--bottleneck/tests/data/test_426_B5
-rw-r--r--bottleneck/tests/data/test_427_A5
-rw-r--r--bottleneck/tests/data/test_427_B5
-rw-r--r--bottleneck/tests/data/test_428_A5
-rw-r--r--bottleneck/tests/data/test_428_B5
-rw-r--r--bottleneck/tests/data/test_429_A5
-rw-r--r--bottleneck/tests/data/test_429_B5
-rw-r--r--bottleneck/tests/data/test_430_A5
-rw-r--r--bottleneck/tests/data/test_430_B5
-rw-r--r--bottleneck/tests/data/test_431_A5
-rw-r--r--bottleneck/tests/data/test_431_B5
-rw-r--r--bottleneck/tests/data/test_432_A5
-rw-r--r--bottleneck/tests/data/test_432_B5
-rw-r--r--bottleneck/tests/data/test_433_A5
-rw-r--r--bottleneck/tests/data/test_433_B5
-rw-r--r--bottleneck/tests/data/test_434_A5
-rw-r--r--bottleneck/tests/data/test_434_B5
-rw-r--r--bottleneck/tests/data/test_435_A5
-rw-r--r--bottleneck/tests/data/test_435_B5
-rw-r--r--bottleneck/tests/data/test_436_A5
-rw-r--r--bottleneck/tests/data/test_436_B5
-rw-r--r--bottleneck/tests/data/test_437_A5
-rw-r--r--bottleneck/tests/data/test_437_B5
-rw-r--r--bottleneck/tests/data/test_438_A5
-rw-r--r--bottleneck/tests/data/test_438_B5
-rw-r--r--bottleneck/tests/data/test_439_A5
-rw-r--r--bottleneck/tests/data/test_439_B5
-rw-r--r--bottleneck/tests/data/test_440_A6
-rw-r--r--bottleneck/tests/data/test_440_B6
-rw-r--r--bottleneck/tests/data/test_441_A6
-rw-r--r--bottleneck/tests/data/test_441_B6
-rw-r--r--bottleneck/tests/data/test_442_A6
-rw-r--r--bottleneck/tests/data/test_442_B6
-rw-r--r--bottleneck/tests/data/test_443_A6
-rw-r--r--bottleneck/tests/data/test_443_B6
-rw-r--r--bottleneck/tests/data/test_444_A6
-rw-r--r--bottleneck/tests/data/test_444_B6
-rw-r--r--bottleneck/tests/data/test_445_A6
-rw-r--r--bottleneck/tests/data/test_445_B6
-rw-r--r--bottleneck/tests/data/test_446_A6
-rw-r--r--bottleneck/tests/data/test_446_B6
-rw-r--r--bottleneck/tests/data/test_447_A6
-rw-r--r--bottleneck/tests/data/test_447_B6
-rw-r--r--bottleneck/tests/data/test_448_A6
-rw-r--r--bottleneck/tests/data/test_448_B6
-rw-r--r--bottleneck/tests/data/test_449_A6
-rw-r--r--bottleneck/tests/data/test_449_B6
-rw-r--r--bottleneck/tests/data/test_450_A6
-rw-r--r--bottleneck/tests/data/test_450_B6
-rw-r--r--bottleneck/tests/data/test_451_A6
-rw-r--r--bottleneck/tests/data/test_451_B6
-rw-r--r--bottleneck/tests/data/test_452_A6
-rw-r--r--bottleneck/tests/data/test_452_B6
-rw-r--r--bottleneck/tests/data/test_453_A6
-rw-r--r--bottleneck/tests/data/test_453_B6
-rw-r--r--bottleneck/tests/data/test_454_A6
-rw-r--r--bottleneck/tests/data/test_454_B6
-rw-r--r--bottleneck/tests/data/test_455_A6
-rw-r--r--bottleneck/tests/data/test_455_B6
-rw-r--r--bottleneck/tests/data/test_456_A6
-rw-r--r--bottleneck/tests/data/test_456_B6
-rw-r--r--bottleneck/tests/data/test_457_A6
-rw-r--r--bottleneck/tests/data/test_457_B6
-rw-r--r--bottleneck/tests/data/test_458_A6
-rw-r--r--bottleneck/tests/data/test_458_B6
-rw-r--r--bottleneck/tests/data/test_459_A6
-rw-r--r--bottleneck/tests/data/test_459_B6
-rw-r--r--bottleneck/tests/data/test_460_A7
-rw-r--r--bottleneck/tests/data/test_460_B7
-rw-r--r--bottleneck/tests/data/test_461_A7
-rw-r--r--bottleneck/tests/data/test_461_B7
-rw-r--r--bottleneck/tests/data/test_462_A7
-rw-r--r--bottleneck/tests/data/test_462_B7
-rw-r--r--bottleneck/tests/data/test_463_A7
-rw-r--r--bottleneck/tests/data/test_463_B7
-rw-r--r--bottleneck/tests/data/test_464_A7
-rw-r--r--bottleneck/tests/data/test_464_B7
-rw-r--r--bottleneck/tests/data/test_465_A7
-rw-r--r--bottleneck/tests/data/test_465_B7
-rw-r--r--bottleneck/tests/data/test_466_A7
-rw-r--r--bottleneck/tests/data/test_466_B7
-rw-r--r--bottleneck/tests/data/test_467_A7
-rw-r--r--bottleneck/tests/data/test_467_B7
-rw-r--r--bottleneck/tests/data/test_468_A7
-rw-r--r--bottleneck/tests/data/test_468_B7
-rw-r--r--bottleneck/tests/data/test_469_A7
-rw-r--r--bottleneck/tests/data/test_469_B7
-rw-r--r--bottleneck/tests/data/test_470_A7
-rw-r--r--bottleneck/tests/data/test_470_B7
-rw-r--r--bottleneck/tests/data/test_471_A7
-rw-r--r--bottleneck/tests/data/test_471_B7
-rw-r--r--bottleneck/tests/data/test_472_A7
-rw-r--r--bottleneck/tests/data/test_472_B7
-rw-r--r--bottleneck/tests/data/test_473_A7
-rw-r--r--bottleneck/tests/data/test_473_B7
-rw-r--r--bottleneck/tests/data/test_474_A7
-rw-r--r--bottleneck/tests/data/test_474_B7
-rw-r--r--bottleneck/tests/data/test_475_A7
-rw-r--r--bottleneck/tests/data/test_475_B7
-rw-r--r--bottleneck/tests/data/test_476_A7
-rw-r--r--bottleneck/tests/data/test_476_B7
-rw-r--r--bottleneck/tests/data/test_477_A7
-rw-r--r--bottleneck/tests/data/test_477_B7
-rw-r--r--bottleneck/tests/data/test_478_A7
-rw-r--r--bottleneck/tests/data/test_478_B7
-rw-r--r--bottleneck/tests/data/test_479_A7
-rw-r--r--bottleneck/tests/data/test_479_B7
-rw-r--r--bottleneck/tests/data/test_480_A8
-rw-r--r--bottleneck/tests/data/test_480_B8
-rw-r--r--bottleneck/tests/data/test_481_A8
-rw-r--r--bottleneck/tests/data/test_481_B8
-rw-r--r--bottleneck/tests/data/test_482_A8
-rw-r--r--bottleneck/tests/data/test_482_B8
-rw-r--r--bottleneck/tests/data/test_483_A8
-rw-r--r--bottleneck/tests/data/test_483_B8
-rw-r--r--bottleneck/tests/data/test_484_A8
-rw-r--r--bottleneck/tests/data/test_484_B8
-rw-r--r--bottleneck/tests/data/test_485_A8
-rw-r--r--bottleneck/tests/data/test_485_B8
-rw-r--r--bottleneck/tests/data/test_486_A8
-rw-r--r--bottleneck/tests/data/test_486_B8
-rw-r--r--bottleneck/tests/data/test_487_A8
-rw-r--r--bottleneck/tests/data/test_487_B8
-rw-r--r--bottleneck/tests/data/test_488_A8
-rw-r--r--bottleneck/tests/data/test_488_B8
-rw-r--r--bottleneck/tests/data/test_489_A8
-rw-r--r--bottleneck/tests/data/test_489_B8
-rw-r--r--bottleneck/tests/data/test_490_A8
-rw-r--r--bottleneck/tests/data/test_490_B8
-rw-r--r--bottleneck/tests/data/test_491_A8
-rw-r--r--bottleneck/tests/data/test_491_B8
-rw-r--r--bottleneck/tests/data/test_492_A8
-rw-r--r--bottleneck/tests/data/test_492_B8
-rw-r--r--bottleneck/tests/data/test_493_A8
-rw-r--r--bottleneck/tests/data/test_493_B8
-rw-r--r--bottleneck/tests/data/test_494_A8
-rw-r--r--bottleneck/tests/data/test_494_B8
-rw-r--r--bottleneck/tests/data/test_495_A8
-rw-r--r--bottleneck/tests/data/test_495_B8
-rw-r--r--bottleneck/tests/data/test_496_A8
-rw-r--r--bottleneck/tests/data/test_496_B8
-rw-r--r--bottleneck/tests/data/test_497_A8
-rw-r--r--bottleneck/tests/data/test_497_B8
-rw-r--r--bottleneck/tests/data/test_498_A8
-rw-r--r--bottleneck/tests/data/test_498_B8
-rw-r--r--bottleneck/tests/data/test_499_A8
-rw-r--r--bottleneck/tests/data/test_499_B8
-rw-r--r--bottleneck/tests/data/test_500_A9
-rw-r--r--bottleneck/tests/data/test_500_B9
-rw-r--r--bottleneck/tests/data/test_501_A9
-rw-r--r--bottleneck/tests/data/test_501_B9
-rw-r--r--bottleneck/tests/data/test_502_A9
-rw-r--r--bottleneck/tests/data/test_502_B9
-rw-r--r--bottleneck/tests/data/test_503_A9
-rw-r--r--bottleneck/tests/data/test_503_B9
-rw-r--r--bottleneck/tests/data/test_504_A9
-rw-r--r--bottleneck/tests/data/test_504_B9
-rw-r--r--bottleneck/tests/data/test_505_A9
-rw-r--r--bottleneck/tests/data/test_505_B9
-rw-r--r--bottleneck/tests/data/test_506_A9
-rw-r--r--bottleneck/tests/data/test_506_B9
-rw-r--r--bottleneck/tests/data/test_507_A9
-rw-r--r--bottleneck/tests/data/test_507_B9
-rw-r--r--bottleneck/tests/data/test_508_A9
-rw-r--r--bottleneck/tests/data/test_508_B9
-rw-r--r--bottleneck/tests/data/test_509_A9
-rw-r--r--bottleneck/tests/data/test_509_B9
-rw-r--r--bottleneck/tests/data/test_510_A9
-rw-r--r--bottleneck/tests/data/test_510_B9
-rw-r--r--bottleneck/tests/data/test_511_A9
-rw-r--r--bottleneck/tests/data/test_511_B9
-rw-r--r--bottleneck/tests/data/test_512_A9
-rw-r--r--bottleneck/tests/data/test_512_B9
-rw-r--r--bottleneck/tests/data/test_513_A9
-rw-r--r--bottleneck/tests/data/test_513_B9
-rw-r--r--bottleneck/tests/data/test_514_A9
-rw-r--r--bottleneck/tests/data/test_514_B9
-rw-r--r--bottleneck/tests/data/test_515_A9
-rw-r--r--bottleneck/tests/data/test_515_B9
-rw-r--r--bottleneck/tests/data/test_516_A9
-rw-r--r--bottleneck/tests/data/test_516_B9
-rw-r--r--bottleneck/tests/data/test_517_A9
-rw-r--r--bottleneck/tests/data/test_517_B9
-rw-r--r--bottleneck/tests/data/test_518_A9
-rw-r--r--bottleneck/tests/data/test_518_B9
-rw-r--r--bottleneck/tests/data/test_519_A9
-rw-r--r--bottleneck/tests/data/test_519_B9
-rw-r--r--bottleneck/tests/data/test_520_A10
-rw-r--r--bottleneck/tests/data/test_520_B10
-rw-r--r--bottleneck/tests/data/test_521_A10
-rw-r--r--bottleneck/tests/data/test_521_B10
-rw-r--r--bottleneck/tests/data/test_522_A10
-rw-r--r--bottleneck/tests/data/test_522_B10
-rw-r--r--bottleneck/tests/data/test_523_A10
-rw-r--r--bottleneck/tests/data/test_523_B10
-rw-r--r--bottleneck/tests/data/test_524_A10
-rw-r--r--bottleneck/tests/data/test_524_B10
-rw-r--r--bottleneck/tests/data/test_525_A10
-rw-r--r--bottleneck/tests/data/test_525_B10
-rw-r--r--bottleneck/tests/data/test_526_A10
-rw-r--r--bottleneck/tests/data/test_526_B10
-rw-r--r--bottleneck/tests/data/test_527_A10
-rw-r--r--bottleneck/tests/data/test_527_B10
-rw-r--r--bottleneck/tests/data/test_528_A10
-rw-r--r--bottleneck/tests/data/test_528_B10
-rw-r--r--bottleneck/tests/data/test_529_A10
-rw-r--r--bottleneck/tests/data/test_529_B10
-rw-r--r--bottleneck/tests/data/test_530_A10
-rw-r--r--bottleneck/tests/data/test_530_B10
-rw-r--r--bottleneck/tests/data/test_531_A10
-rw-r--r--bottleneck/tests/data/test_531_B10
-rw-r--r--bottleneck/tests/data/test_532_A10
-rw-r--r--bottleneck/tests/data/test_532_B10
-rw-r--r--bottleneck/tests/data/test_533_A10
-rw-r--r--bottleneck/tests/data/test_533_B10
-rw-r--r--bottleneck/tests/data/test_534_A10
-rw-r--r--bottleneck/tests/data/test_534_B10
-rw-r--r--bottleneck/tests/data/test_535_A10
-rw-r--r--bottleneck/tests/data/test_535_B10
-rw-r--r--bottleneck/tests/data/test_536_A10
-rw-r--r--bottleneck/tests/data/test_536_B10
-rw-r--r--bottleneck/tests/data/test_537_A10
-rw-r--r--bottleneck/tests/data/test_537_B10
-rw-r--r--bottleneck/tests/data/test_538_A10
-rw-r--r--bottleneck/tests/data/test_538_B10
-rw-r--r--bottleneck/tests/data/test_539_A10
-rw-r--r--bottleneck/tests/data/test_539_B10
-rw-r--r--bottleneck/tests/data/test_540_A20
-rw-r--r--bottleneck/tests/data/test_540_B20
-rw-r--r--bottleneck/tests/data/test_541_A20
-rw-r--r--bottleneck/tests/data/test_541_B20
-rw-r--r--bottleneck/tests/data/test_542_A20
-rw-r--r--bottleneck/tests/data/test_542_B20
-rw-r--r--bottleneck/tests/data/test_543_A20
-rw-r--r--bottleneck/tests/data/test_543_B20
-rw-r--r--bottleneck/tests/data/test_544_A20
-rw-r--r--bottleneck/tests/data/test_544_B20
-rw-r--r--bottleneck/tests/data/test_545_A20
-rw-r--r--bottleneck/tests/data/test_545_B20
-rw-r--r--bottleneck/tests/data/test_546_A20
-rw-r--r--bottleneck/tests/data/test_546_B20
-rw-r--r--bottleneck/tests/data/test_547_A20
-rw-r--r--bottleneck/tests/data/test_547_B20
-rw-r--r--bottleneck/tests/data/test_548_A20
-rw-r--r--bottleneck/tests/data/test_548_B20
-rw-r--r--bottleneck/tests/data/test_549_A20
-rw-r--r--bottleneck/tests/data/test_549_B20
-rw-r--r--bottleneck/tests/data/test_550_A20
-rw-r--r--bottleneck/tests/data/test_550_B20
-rw-r--r--bottleneck/tests/data/test_551_A20
-rw-r--r--bottleneck/tests/data/test_551_B20
-rw-r--r--bottleneck/tests/data/test_552_A20
-rw-r--r--bottleneck/tests/data/test_552_B20
-rw-r--r--bottleneck/tests/data/test_553_A20
-rw-r--r--bottleneck/tests/data/test_553_B20
-rw-r--r--bottleneck/tests/data/test_554_A20
-rw-r--r--bottleneck/tests/data/test_554_B20
-rw-r--r--bottleneck/tests/data/test_555_A20
-rw-r--r--bottleneck/tests/data/test_555_B20
-rw-r--r--bottleneck/tests/data/test_556_A20
-rw-r--r--bottleneck/tests/data/test_556_B20
-rw-r--r--bottleneck/tests/data/test_557_A20
-rw-r--r--bottleneck/tests/data/test_557_B20
-rw-r--r--bottleneck/tests/data/test_558_A20
-rw-r--r--bottleneck/tests/data/test_558_B20
-rw-r--r--bottleneck/tests/data/test_559_A20
-rw-r--r--bottleneck/tests/data/test_559_B20
-rw-r--r--bottleneck/tests/data/test_560_A30
-rw-r--r--bottleneck/tests/data/test_560_B30
-rw-r--r--bottleneck/tests/data/test_561_A30
-rw-r--r--bottleneck/tests/data/test_561_B30
-rw-r--r--bottleneck/tests/data/test_562_A30
-rw-r--r--bottleneck/tests/data/test_562_B30
-rw-r--r--bottleneck/tests/data/test_563_A30
-rw-r--r--bottleneck/tests/data/test_563_B30
-rw-r--r--bottleneck/tests/data/test_564_A30
-rw-r--r--bottleneck/tests/data/test_564_B30
-rw-r--r--bottleneck/tests/data/test_565_A30
-rw-r--r--bottleneck/tests/data/test_565_B30
-rw-r--r--bottleneck/tests/data/test_566_A30
-rw-r--r--bottleneck/tests/data/test_566_B30
-rw-r--r--bottleneck/tests/data/test_567_A30
-rw-r--r--bottleneck/tests/data/test_567_B30
-rw-r--r--bottleneck/tests/data/test_568_A30
-rw-r--r--bottleneck/tests/data/test_568_B30
-rw-r--r--bottleneck/tests/data/test_569_A30
-rw-r--r--bottleneck/tests/data/test_569_B30
-rw-r--r--bottleneck/tests/data/test_570_A30
-rw-r--r--bottleneck/tests/data/test_570_B30
-rw-r--r--bottleneck/tests/data/test_571_A30
-rw-r--r--bottleneck/tests/data/test_571_B30
-rw-r--r--bottleneck/tests/data/test_572_A30
-rw-r--r--bottleneck/tests/data/test_572_B30
-rw-r--r--bottleneck/tests/data/test_573_A30
-rw-r--r--bottleneck/tests/data/test_573_B30
-rw-r--r--bottleneck/tests/data/test_574_A30
-rw-r--r--bottleneck/tests/data/test_574_B30
-rw-r--r--bottleneck/tests/data/test_575_A30
-rw-r--r--bottleneck/tests/data/test_575_B30
-rw-r--r--bottleneck/tests/data/test_576_A30
-rw-r--r--bottleneck/tests/data/test_576_B30
-rw-r--r--bottleneck/tests/data/test_577_A30
-rw-r--r--bottleneck/tests/data/test_577_B30
-rw-r--r--bottleneck/tests/data/test_578_A30
-rw-r--r--bottleneck/tests/data/test_578_B30
-rw-r--r--bottleneck/tests/data/test_579_A30
-rw-r--r--bottleneck/tests/data/test_579_B30
-rw-r--r--bottleneck/tests/data/test_580_A50
-rw-r--r--bottleneck/tests/data/test_580_B50
-rw-r--r--bottleneck/tests/data/test_581_A50
-rw-r--r--bottleneck/tests/data/test_581_B50
-rw-r--r--bottleneck/tests/data/test_582_A50
-rw-r--r--bottleneck/tests/data/test_582_B50
-rw-r--r--bottleneck/tests/data/test_583_A50
-rw-r--r--bottleneck/tests/data/test_583_B50
-rw-r--r--bottleneck/tests/data/test_584_A50
-rw-r--r--bottleneck/tests/data/test_584_B50
-rw-r--r--bottleneck/tests/data/test_585_A50
-rw-r--r--bottleneck/tests/data/test_585_B50
-rw-r--r--bottleneck/tests/data/test_586_A50
-rw-r--r--bottleneck/tests/data/test_586_B50
-rw-r--r--bottleneck/tests/data/test_587_A50
-rw-r--r--bottleneck/tests/data/test_587_B50
-rw-r--r--bottleneck/tests/data/test_588_A50
-rw-r--r--bottleneck/tests/data/test_588_B50
-rw-r--r--bottleneck/tests/data/test_589_A50
-rw-r--r--bottleneck/tests/data/test_589_B50
-rw-r--r--bottleneck/tests/data/test_590_A50
-rw-r--r--bottleneck/tests/data/test_590_B50
-rw-r--r--bottleneck/tests/data/test_591_A50
-rw-r--r--bottleneck/tests/data/test_591_B50
-rw-r--r--bottleneck/tests/data/test_592_A50
-rw-r--r--bottleneck/tests/data/test_592_B50
-rw-r--r--bottleneck/tests/data/test_593_A50
-rw-r--r--bottleneck/tests/data/test_593_B50
-rw-r--r--bottleneck/tests/data/test_594_A50
-rw-r--r--bottleneck/tests/data/test_594_B50
-rw-r--r--bottleneck/tests/data/test_595_A50
-rw-r--r--bottleneck/tests/data/test_595_B50
-rw-r--r--bottleneck/tests/data/test_596_A50
-rw-r--r--bottleneck/tests/data/test_596_B50
-rw-r--r--bottleneck/tests/data/test_597_A50
-rw-r--r--bottleneck/tests/data/test_597_B50
-rw-r--r--bottleneck/tests/data/test_598_A50
-rw-r--r--bottleneck/tests/data/test_598_B50
-rw-r--r--bottleneck/tests/data/test_599_A50
-rw-r--r--bottleneck/tests/data/test_599_B50
-rw-r--r--bottleneck/tests/data/test_600_A100
-rw-r--r--bottleneck/tests/data/test_600_B100
-rw-r--r--bottleneck/tests/data/test_601_A100
-rw-r--r--bottleneck/tests/data/test_601_B100
-rw-r--r--bottleneck/tests/data/test_602_A100
-rw-r--r--bottleneck/tests/data/test_602_B100
-rw-r--r--bottleneck/tests/data/test_603_A100
-rw-r--r--bottleneck/tests/data/test_603_B100
-rw-r--r--bottleneck/tests/data/test_604_A100
-rw-r--r--bottleneck/tests/data/test_604_B100
-rw-r--r--bottleneck/tests/data/test_605_A100
-rw-r--r--bottleneck/tests/data/test_605_B100
-rw-r--r--bottleneck/tests/data/test_606_A100
-rw-r--r--bottleneck/tests/data/test_606_B100
-rw-r--r--bottleneck/tests/data/test_607_A100
-rw-r--r--bottleneck/tests/data/test_607_B100
-rw-r--r--bottleneck/tests/data/test_608_A100
-rw-r--r--bottleneck/tests/data/test_608_B100
-rw-r--r--bottleneck/tests/data/test_609_A100
-rw-r--r--bottleneck/tests/data/test_609_B100
-rw-r--r--bottleneck/tests/data/test_610_A100
-rw-r--r--bottleneck/tests/data/test_610_B100
-rw-r--r--bottleneck/tests/data/test_611_A100
-rw-r--r--bottleneck/tests/data/test_611_B100
-rw-r--r--bottleneck/tests/data/test_612_A100
-rw-r--r--bottleneck/tests/data/test_612_B100
-rw-r--r--bottleneck/tests/data/test_613_A100
-rw-r--r--bottleneck/tests/data/test_613_B100
-rw-r--r--bottleneck/tests/data/test_614_A100
-rw-r--r--bottleneck/tests/data/test_614_B100
-rw-r--r--bottleneck/tests/data/test_615_A100
-rw-r--r--bottleneck/tests/data/test_615_B100
-rw-r--r--bottleneck/tests/data/test_616_A100
-rw-r--r--bottleneck/tests/data/test_616_B100
-rw-r--r--bottleneck/tests/data/test_617_A100
-rw-r--r--bottleneck/tests/data/test_617_B100
-rw-r--r--bottleneck/tests/data/test_618_A100
-rw-r--r--bottleneck/tests/data/test_618_B100
-rw-r--r--bottleneck/tests/data/test_619_A100
-rw-r--r--bottleneck/tests/data/test_619_B100
-rw-r--r--bottleneck/tests/data/test_620_A2
-rw-r--r--bottleneck/tests/data/test_620_B2
-rw-r--r--bottleneck/tests/data/test_621_A2
-rw-r--r--bottleneck/tests/data/test_621_B2
-rw-r--r--bottleneck/tests/data/test_622_A2
-rw-r--r--bottleneck/tests/data/test_622_B2
-rw-r--r--bottleneck/tests/data/test_623_A2
-rw-r--r--bottleneck/tests/data/test_623_B2
-rw-r--r--bottleneck/tests/data/test_624_A2
-rw-r--r--bottleneck/tests/data/test_624_B2
-rw-r--r--bottleneck/tests/data/test_625_A2
-rw-r--r--bottleneck/tests/data/test_625_B2
-rw-r--r--bottleneck/tests/data/test_626_A2
-rw-r--r--bottleneck/tests/data/test_626_B2
-rw-r--r--bottleneck/tests/data/test_627_A2
-rw-r--r--bottleneck/tests/data/test_627_B2
-rw-r--r--bottleneck/tests/data/test_628_A2
-rw-r--r--bottleneck/tests/data/test_628_B2
-rw-r--r--bottleneck/tests/data/test_629_A2
-rw-r--r--bottleneck/tests/data/test_629_B2
-rw-r--r--bottleneck/tests/data/test_630_A2
-rw-r--r--bottleneck/tests/data/test_630_B2
-rw-r--r--bottleneck/tests/data/test_631_A2
-rw-r--r--bottleneck/tests/data/test_631_B2
-rw-r--r--bottleneck/tests/data/test_632_A2
-rw-r--r--bottleneck/tests/data/test_632_B2
-rw-r--r--bottleneck/tests/data/test_633_A2
-rw-r--r--bottleneck/tests/data/test_633_B2
-rw-r--r--bottleneck/tests/data/test_634_A2
-rw-r--r--bottleneck/tests/data/test_634_B2
-rw-r--r--bottleneck/tests/data/test_635_A2
-rw-r--r--bottleneck/tests/data/test_635_B2
-rw-r--r--bottleneck/tests/data/test_636_A2
-rw-r--r--bottleneck/tests/data/test_636_B2
-rw-r--r--bottleneck/tests/data/test_637_A2
-rw-r--r--bottleneck/tests/data/test_637_B2
-rw-r--r--bottleneck/tests/data/test_638_A2
-rw-r--r--bottleneck/tests/data/test_638_B2
-rw-r--r--bottleneck/tests/data/test_639_A2
-rw-r--r--bottleneck/tests/data/test_639_B2
-rw-r--r--bottleneck/tests/data/test_640_A3
-rw-r--r--bottleneck/tests/data/test_640_B3
-rw-r--r--bottleneck/tests/data/test_641_A3
-rw-r--r--bottleneck/tests/data/test_641_B3
-rw-r--r--bottleneck/tests/data/test_642_A3
-rw-r--r--bottleneck/tests/data/test_642_B3
-rw-r--r--bottleneck/tests/data/test_643_A3
-rw-r--r--bottleneck/tests/data/test_643_B3
-rw-r--r--bottleneck/tests/data/test_644_A3
-rw-r--r--bottleneck/tests/data/test_644_B3
-rw-r--r--bottleneck/tests/data/test_645_A3
-rw-r--r--bottleneck/tests/data/test_645_B3
-rw-r--r--bottleneck/tests/data/test_646_A3
-rw-r--r--bottleneck/tests/data/test_646_B3
-rw-r--r--bottleneck/tests/data/test_647_A3
-rw-r--r--bottleneck/tests/data/test_647_B3
-rw-r--r--bottleneck/tests/data/test_648_A3
-rw-r--r--bottleneck/tests/data/test_648_B3
-rw-r--r--bottleneck/tests/data/test_649_A3
-rw-r--r--bottleneck/tests/data/test_649_B3
-rw-r--r--bottleneck/tests/data/test_650_A3
-rw-r--r--bottleneck/tests/data/test_650_B3
-rw-r--r--bottleneck/tests/data/test_651_A3
-rw-r--r--bottleneck/tests/data/test_651_B3
-rw-r--r--bottleneck/tests/data/test_652_A3
-rw-r--r--bottleneck/tests/data/test_652_B3
-rw-r--r--bottleneck/tests/data/test_653_A3
-rw-r--r--bottleneck/tests/data/test_653_B3
-rw-r--r--bottleneck/tests/data/test_654_A3
-rw-r--r--bottleneck/tests/data/test_654_B3
-rw-r--r--bottleneck/tests/data/test_655_A3
-rw-r--r--bottleneck/tests/data/test_655_B3
-rw-r--r--bottleneck/tests/data/test_656_A3
-rw-r--r--bottleneck/tests/data/test_656_B3
-rw-r--r--bottleneck/tests/data/test_657_A3
-rw-r--r--bottleneck/tests/data/test_657_B3
-rw-r--r--bottleneck/tests/data/test_658_A3
-rw-r--r--bottleneck/tests/data/test_658_B3
-rw-r--r--bottleneck/tests/data/test_659_A3
-rw-r--r--bottleneck/tests/data/test_659_B3
-rw-r--r--bottleneck/tests/data/test_660_A4
-rw-r--r--bottleneck/tests/data/test_660_B4
-rw-r--r--bottleneck/tests/data/test_661_A4
-rw-r--r--bottleneck/tests/data/test_661_B4
-rw-r--r--bottleneck/tests/data/test_662_A4
-rw-r--r--bottleneck/tests/data/test_662_B4
-rw-r--r--bottleneck/tests/data/test_663_A4
-rw-r--r--bottleneck/tests/data/test_663_B4
-rw-r--r--bottleneck/tests/data/test_664_A4
-rw-r--r--bottleneck/tests/data/test_664_B4
-rw-r--r--bottleneck/tests/data/test_665_A4
-rw-r--r--bottleneck/tests/data/test_665_B4
-rw-r--r--bottleneck/tests/data/test_666_A4
-rw-r--r--bottleneck/tests/data/test_666_B4
-rw-r--r--bottleneck/tests/data/test_667_A4
-rw-r--r--bottleneck/tests/data/test_667_B4
-rw-r--r--bottleneck/tests/data/test_668_A4
-rw-r--r--bottleneck/tests/data/test_668_B4
-rw-r--r--bottleneck/tests/data/test_669_A4
-rw-r--r--bottleneck/tests/data/test_669_B4
-rw-r--r--bottleneck/tests/data/test_670_A4
-rw-r--r--bottleneck/tests/data/test_670_B4
-rw-r--r--bottleneck/tests/data/test_671_A4
-rw-r--r--bottleneck/tests/data/test_671_B4
-rw-r--r--bottleneck/tests/data/test_672_A4
-rw-r--r--bottleneck/tests/data/test_672_B4
-rw-r--r--bottleneck/tests/data/test_673_A4
-rw-r--r--bottleneck/tests/data/test_673_B4
-rw-r--r--bottleneck/tests/data/test_674_A4
-rw-r--r--bottleneck/tests/data/test_674_B4
-rw-r--r--bottleneck/tests/data/test_675_A4
-rw-r--r--bottleneck/tests/data/test_675_B4
-rw-r--r--bottleneck/tests/data/test_676_A4
-rw-r--r--bottleneck/tests/data/test_676_B4
-rw-r--r--bottleneck/tests/data/test_677_A4
-rw-r--r--bottleneck/tests/data/test_677_B4
-rw-r--r--bottleneck/tests/data/test_678_A4
-rw-r--r--bottleneck/tests/data/test_678_B4
-rw-r--r--bottleneck/tests/data/test_679_A4
-rw-r--r--bottleneck/tests/data/test_679_B4
-rw-r--r--bottleneck/tests/data/test_680_A5
-rw-r--r--bottleneck/tests/data/test_680_B5
-rw-r--r--bottleneck/tests/data/test_681_A5
-rw-r--r--bottleneck/tests/data/test_681_B5
-rw-r--r--bottleneck/tests/data/test_682_A5
-rw-r--r--bottleneck/tests/data/test_682_B5
-rw-r--r--bottleneck/tests/data/test_683_A5
-rw-r--r--bottleneck/tests/data/test_683_B5
-rw-r--r--bottleneck/tests/data/test_684_A5
-rw-r--r--bottleneck/tests/data/test_684_B5
-rw-r--r--bottleneck/tests/data/test_685_A5
-rw-r--r--bottleneck/tests/data/test_685_B5
-rw-r--r--bottleneck/tests/data/test_686_A5
-rw-r--r--bottleneck/tests/data/test_686_B5
-rw-r--r--bottleneck/tests/data/test_687_A5
-rw-r--r--bottleneck/tests/data/test_687_B5
-rw-r--r--bottleneck/tests/data/test_688_A5
-rw-r--r--bottleneck/tests/data/test_688_B5
-rw-r--r--bottleneck/tests/data/test_689_A5
-rw-r--r--bottleneck/tests/data/test_689_B5
-rw-r--r--bottleneck/tests/data/test_690_A5
-rw-r--r--bottleneck/tests/data/test_690_B5
-rw-r--r--bottleneck/tests/data/test_691_A5
-rw-r--r--bottleneck/tests/data/test_691_B5
-rw-r--r--bottleneck/tests/data/test_692_A5
-rw-r--r--bottleneck/tests/data/test_692_B5
-rw-r--r--bottleneck/tests/data/test_693_A5
-rw-r--r--bottleneck/tests/data/test_693_B5
-rw-r--r--bottleneck/tests/data/test_694_A5
-rw-r--r--bottleneck/tests/data/test_694_B5
-rw-r--r--bottleneck/tests/data/test_695_A5
-rw-r--r--bottleneck/tests/data/test_695_B5
-rw-r--r--bottleneck/tests/data/test_696_A5
-rw-r--r--bottleneck/tests/data/test_696_B5
-rw-r--r--bottleneck/tests/data/test_697_A5
-rw-r--r--bottleneck/tests/data/test_697_B5
-rw-r--r--bottleneck/tests/data/test_698_A5
-rw-r--r--bottleneck/tests/data/test_698_B5
-rw-r--r--bottleneck/tests/data/test_699_A5
-rw-r--r--bottleneck/tests/data/test_699_B5
-rw-r--r--bottleneck/tests/data/test_700_A6
-rw-r--r--bottleneck/tests/data/test_700_B6
-rw-r--r--bottleneck/tests/data/test_701_A6
-rw-r--r--bottleneck/tests/data/test_701_B6
-rw-r--r--bottleneck/tests/data/test_702_A6
-rw-r--r--bottleneck/tests/data/test_702_B6
-rw-r--r--bottleneck/tests/data/test_703_A6
-rw-r--r--bottleneck/tests/data/test_703_B6
-rw-r--r--bottleneck/tests/data/test_704_A6
-rw-r--r--bottleneck/tests/data/test_704_B6
-rw-r--r--bottleneck/tests/data/test_705_A6
-rw-r--r--bottleneck/tests/data/test_705_B6
-rw-r--r--bottleneck/tests/data/test_706_A6
-rw-r--r--bottleneck/tests/data/test_706_B6
-rw-r--r--bottleneck/tests/data/test_707_A6
-rw-r--r--bottleneck/tests/data/test_707_B6
-rw-r--r--bottleneck/tests/data/test_708_A6
-rw-r--r--bottleneck/tests/data/test_708_B6
-rw-r--r--bottleneck/tests/data/test_709_A6
-rw-r--r--bottleneck/tests/data/test_709_B6
-rw-r--r--bottleneck/tests/data/test_710_A6
-rw-r--r--bottleneck/tests/data/test_710_B6
-rw-r--r--bottleneck/tests/data/test_711_A6
-rw-r--r--bottleneck/tests/data/test_711_B6
-rw-r--r--bottleneck/tests/data/test_712_A6
-rw-r--r--bottleneck/tests/data/test_712_B6
-rw-r--r--bottleneck/tests/data/test_713_A6
-rw-r--r--bottleneck/tests/data/test_713_B6
-rw-r--r--bottleneck/tests/data/test_714_A6
-rw-r--r--bottleneck/tests/data/test_714_B6
-rw-r--r--bottleneck/tests/data/test_715_A6
-rw-r--r--bottleneck/tests/data/test_715_B6
-rw-r--r--bottleneck/tests/data/test_716_A6
-rw-r--r--bottleneck/tests/data/test_716_B6
-rw-r--r--bottleneck/tests/data/test_717_A6
-rw-r--r--bottleneck/tests/data/test_717_B6
-rw-r--r--bottleneck/tests/data/test_718_A6
-rw-r--r--bottleneck/tests/data/test_718_B6
-rw-r--r--bottleneck/tests/data/test_719_A6
-rw-r--r--bottleneck/tests/data/test_719_B6
-rw-r--r--bottleneck/tests/data/test_720_A7
-rw-r--r--bottleneck/tests/data/test_720_B7
-rw-r--r--bottleneck/tests/data/test_721_A7
-rw-r--r--bottleneck/tests/data/test_721_B7
-rw-r--r--bottleneck/tests/data/test_722_A7
-rw-r--r--bottleneck/tests/data/test_722_B7
-rw-r--r--bottleneck/tests/data/test_723_A7
-rw-r--r--bottleneck/tests/data/test_723_B7
-rw-r--r--bottleneck/tests/data/test_724_A7
-rw-r--r--bottleneck/tests/data/test_724_B7
-rw-r--r--bottleneck/tests/data/test_725_A7
-rw-r--r--bottleneck/tests/data/test_725_B7
-rw-r--r--bottleneck/tests/data/test_726_A7
-rw-r--r--bottleneck/tests/data/test_726_B7
-rw-r--r--bottleneck/tests/data/test_727_A7
-rw-r--r--bottleneck/tests/data/test_727_B7
-rw-r--r--bottleneck/tests/data/test_728_A7
-rw-r--r--bottleneck/tests/data/test_728_B7
-rw-r--r--bottleneck/tests/data/test_729_A7
-rw-r--r--bottleneck/tests/data/test_729_B7
-rw-r--r--bottleneck/tests/data/test_730_A7
-rw-r--r--bottleneck/tests/data/test_730_B7
-rw-r--r--bottleneck/tests/data/test_731_A7
-rw-r--r--bottleneck/tests/data/test_731_B7
-rw-r--r--bottleneck/tests/data/test_732_A7
-rw-r--r--bottleneck/tests/data/test_732_B7
-rw-r--r--bottleneck/tests/data/test_733_A7
-rw-r--r--bottleneck/tests/data/test_733_B7
-rw-r--r--bottleneck/tests/data/test_734_A7
-rw-r--r--bottleneck/tests/data/test_734_B7
-rw-r--r--bottleneck/tests/data/test_735_A7
-rw-r--r--bottleneck/tests/data/test_735_B7
-rw-r--r--bottleneck/tests/data/test_736_A7
-rw-r--r--bottleneck/tests/data/test_736_B7
-rw-r--r--bottleneck/tests/data/test_737_A7
-rw-r--r--bottleneck/tests/data/test_737_B7
-rw-r--r--bottleneck/tests/data/test_738_A7
-rw-r--r--bottleneck/tests/data/test_738_B7
-rw-r--r--bottleneck/tests/data/test_739_A7
-rw-r--r--bottleneck/tests/data/test_739_B7
-rw-r--r--bottleneck/tests/data/test_740_A8
-rw-r--r--bottleneck/tests/data/test_740_B8
-rw-r--r--bottleneck/tests/data/test_741_A8
-rw-r--r--bottleneck/tests/data/test_741_B8
-rw-r--r--bottleneck/tests/data/test_742_A8
-rw-r--r--bottleneck/tests/data/test_742_B8
-rw-r--r--bottleneck/tests/data/test_743_A8
-rw-r--r--bottleneck/tests/data/test_743_B8
-rw-r--r--bottleneck/tests/data/test_744_A8
-rw-r--r--bottleneck/tests/data/test_744_B8
-rw-r--r--bottleneck/tests/data/test_745_A8
-rw-r--r--bottleneck/tests/data/test_745_B8
-rw-r--r--bottleneck/tests/data/test_746_A8
-rw-r--r--bottleneck/tests/data/test_746_B8
-rw-r--r--bottleneck/tests/data/test_747_A8
-rw-r--r--bottleneck/tests/data/test_747_B8
-rw-r--r--bottleneck/tests/data/test_748_A8
-rw-r--r--bottleneck/tests/data/test_748_B8
-rw-r--r--bottleneck/tests/data/test_749_A8
-rw-r--r--bottleneck/tests/data/test_749_B8
-rw-r--r--bottleneck/tests/data/test_750_A8
-rw-r--r--bottleneck/tests/data/test_750_B8
-rw-r--r--bottleneck/tests/data/test_751_A8
-rw-r--r--bottleneck/tests/data/test_751_B8
-rw-r--r--bottleneck/tests/data/test_752_A8
-rw-r--r--bottleneck/tests/data/test_752_B8
-rw-r--r--bottleneck/tests/data/test_753_A8
-rw-r--r--bottleneck/tests/data/test_753_B8
-rw-r--r--bottleneck/tests/data/test_754_A8
-rw-r--r--bottleneck/tests/data/test_754_B8
-rw-r--r--bottleneck/tests/data/test_755_A8
-rw-r--r--bottleneck/tests/data/test_755_B8
-rw-r--r--bottleneck/tests/data/test_756_A8
-rw-r--r--bottleneck/tests/data/test_756_B8
-rw-r--r--bottleneck/tests/data/test_757_A8
-rw-r--r--bottleneck/tests/data/test_757_B8
-rw-r--r--bottleneck/tests/data/test_758_A8
-rw-r--r--bottleneck/tests/data/test_758_B8
-rw-r--r--bottleneck/tests/data/test_759_A8
-rw-r--r--bottleneck/tests/data/test_759_B8
-rw-r--r--bottleneck/tests/data/test_760_A9
-rw-r--r--bottleneck/tests/data/test_760_B9
-rw-r--r--bottleneck/tests/data/test_761_A9
-rw-r--r--bottleneck/tests/data/test_761_B9
-rw-r--r--bottleneck/tests/data/test_762_A9
-rw-r--r--bottleneck/tests/data/test_762_B9
-rw-r--r--bottleneck/tests/data/test_763_A9
-rw-r--r--bottleneck/tests/data/test_763_B9
-rw-r--r--bottleneck/tests/data/test_764_A9
-rw-r--r--bottleneck/tests/data/test_764_B9
-rw-r--r--bottleneck/tests/data/test_765_A9
-rw-r--r--bottleneck/tests/data/test_765_B9
-rw-r--r--bottleneck/tests/data/test_766_A9
-rw-r--r--bottleneck/tests/data/test_766_B9
-rw-r--r--bottleneck/tests/data/test_767_A9
-rw-r--r--bottleneck/tests/data/test_767_B9
-rw-r--r--bottleneck/tests/data/test_768_A9
-rw-r--r--bottleneck/tests/data/test_768_B9
-rw-r--r--bottleneck/tests/data/test_769_A9
-rw-r--r--bottleneck/tests/data/test_769_B9
-rw-r--r--bottleneck/tests/data/test_770_A9
-rw-r--r--bottleneck/tests/data/test_770_B9
-rw-r--r--bottleneck/tests/data/test_771_A9
-rw-r--r--bottleneck/tests/data/test_771_B9
-rw-r--r--bottleneck/tests/data/test_772_A9
-rw-r--r--bottleneck/tests/data/test_772_B9
-rw-r--r--bottleneck/tests/data/test_773_A9
-rw-r--r--bottleneck/tests/data/test_773_B9
-rw-r--r--bottleneck/tests/data/test_774_A9
-rw-r--r--bottleneck/tests/data/test_774_B9
-rw-r--r--bottleneck/tests/data/test_775_A9
-rw-r--r--bottleneck/tests/data/test_775_B9
-rw-r--r--bottleneck/tests/data/test_776_A9
-rw-r--r--bottleneck/tests/data/test_776_B9
-rw-r--r--bottleneck/tests/data/test_777_A9
-rw-r--r--bottleneck/tests/data/test_777_B9
-rw-r--r--bottleneck/tests/data/test_778_A9
-rw-r--r--bottleneck/tests/data/test_778_B9
-rw-r--r--bottleneck/tests/data/test_779_A9
-rw-r--r--bottleneck/tests/data/test_779_B9
-rw-r--r--bottleneck/tests/data/test_780_A10
-rw-r--r--bottleneck/tests/data/test_780_B10
-rw-r--r--bottleneck/tests/data/test_781_A10
-rw-r--r--bottleneck/tests/data/test_781_B10
-rw-r--r--bottleneck/tests/data/test_782_A10
-rw-r--r--bottleneck/tests/data/test_782_B10
-rw-r--r--bottleneck/tests/data/test_783_A10
-rw-r--r--bottleneck/tests/data/test_783_B10
-rw-r--r--bottleneck/tests/data/test_784_A10
-rw-r--r--bottleneck/tests/data/test_784_B10
-rw-r--r--bottleneck/tests/data/test_785_A10
-rw-r--r--bottleneck/tests/data/test_785_B10
-rw-r--r--bottleneck/tests/data/test_786_A10
-rw-r--r--bottleneck/tests/data/test_786_B10
-rw-r--r--bottleneck/tests/data/test_787_A10
-rw-r--r--bottleneck/tests/data/test_787_B10
-rw-r--r--bottleneck/tests/data/test_788_A10
-rw-r--r--bottleneck/tests/data/test_788_B10
-rw-r--r--bottleneck/tests/data/test_789_A10
-rw-r--r--bottleneck/tests/data/test_789_B10
-rw-r--r--bottleneck/tests/data/test_790_A10
-rw-r--r--bottleneck/tests/data/test_790_B10
-rw-r--r--bottleneck/tests/data/test_791_A10
-rw-r--r--bottleneck/tests/data/test_791_B10
-rw-r--r--bottleneck/tests/data/test_792_A10
-rw-r--r--bottleneck/tests/data/test_792_B10
-rw-r--r--bottleneck/tests/data/test_793_A10
-rw-r--r--bottleneck/tests/data/test_793_B10
-rw-r--r--bottleneck/tests/data/test_794_A10
-rw-r--r--bottleneck/tests/data/test_794_B10
-rw-r--r--bottleneck/tests/data/test_795_A10
-rw-r--r--bottleneck/tests/data/test_795_B10
-rw-r--r--bottleneck/tests/data/test_796_A10
-rw-r--r--bottleneck/tests/data/test_796_B10
-rw-r--r--bottleneck/tests/data/test_797_A10
-rw-r--r--bottleneck/tests/data/test_797_B10
-rw-r--r--bottleneck/tests/data/test_798_A10
-rw-r--r--bottleneck/tests/data/test_798_B10
-rw-r--r--bottleneck/tests/data/test_799_A10
-rw-r--r--bottleneck/tests/data/test_799_B10
-rw-r--r--bottleneck/tests/data/test_800_A20
-rw-r--r--bottleneck/tests/data/test_800_B20
-rw-r--r--bottleneck/tests/data/test_801_A20
-rw-r--r--bottleneck/tests/data/test_801_B20
-rw-r--r--bottleneck/tests/data/test_802_A20
-rw-r--r--bottleneck/tests/data/test_802_B20
-rw-r--r--bottleneck/tests/data/test_803_A20
-rw-r--r--bottleneck/tests/data/test_803_B20
-rw-r--r--bottleneck/tests/data/test_804_A20
-rw-r--r--bottleneck/tests/data/test_804_B20
-rw-r--r--bottleneck/tests/data/test_805_A20
-rw-r--r--bottleneck/tests/data/test_805_B20
-rw-r--r--bottleneck/tests/data/test_806_A20
-rw-r--r--bottleneck/tests/data/test_806_B20
-rw-r--r--bottleneck/tests/data/test_807_A20
-rw-r--r--bottleneck/tests/data/test_807_B20
-rw-r--r--bottleneck/tests/data/test_808_A20
-rw-r--r--bottleneck/tests/data/test_808_B20
-rw-r--r--bottleneck/tests/data/test_809_A20
-rw-r--r--bottleneck/tests/data/test_809_B20
-rw-r--r--bottleneck/tests/data/test_810_A20
-rw-r--r--bottleneck/tests/data/test_810_B20
-rw-r--r--bottleneck/tests/data/test_811_A20
-rw-r--r--bottleneck/tests/data/test_811_B20
-rw-r--r--bottleneck/tests/data/test_812_A20
-rw-r--r--bottleneck/tests/data/test_812_B20
-rw-r--r--bottleneck/tests/data/test_813_A20
-rw-r--r--bottleneck/tests/data/test_813_B20
-rw-r--r--bottleneck/tests/data/test_814_A20
-rw-r--r--bottleneck/tests/data/test_814_B20
-rw-r--r--bottleneck/tests/data/test_815_A20
-rw-r--r--bottleneck/tests/data/test_815_B20
-rw-r--r--bottleneck/tests/data/test_816_A20
-rw-r--r--bottleneck/tests/data/test_816_B20
-rw-r--r--bottleneck/tests/data/test_817_A20
-rw-r--r--bottleneck/tests/data/test_817_B20
-rw-r--r--bottleneck/tests/data/test_818_A20
-rw-r--r--bottleneck/tests/data/test_818_B20
-rw-r--r--bottleneck/tests/data/test_819_A20
-rw-r--r--bottleneck/tests/data/test_819_B20
-rw-r--r--bottleneck/tests/data/test_820_A30
-rw-r--r--bottleneck/tests/data/test_820_B30
-rw-r--r--bottleneck/tests/data/test_821_A30
-rw-r--r--bottleneck/tests/data/test_821_B30
-rw-r--r--bottleneck/tests/data/test_822_A30
-rw-r--r--bottleneck/tests/data/test_822_B30
-rw-r--r--bottleneck/tests/data/test_823_A30
-rw-r--r--bottleneck/tests/data/test_823_B30
-rw-r--r--bottleneck/tests/data/test_824_A30
-rw-r--r--bottleneck/tests/data/test_824_B30
-rw-r--r--bottleneck/tests/data/test_825_A30
-rw-r--r--bottleneck/tests/data/test_825_B30
-rw-r--r--bottleneck/tests/data/test_826_A30
-rw-r--r--bottleneck/tests/data/test_826_B30
-rw-r--r--bottleneck/tests/data/test_827_A30
-rw-r--r--bottleneck/tests/data/test_827_B30
-rw-r--r--bottleneck/tests/data/test_828_A30
-rw-r--r--bottleneck/tests/data/test_828_B30
-rw-r--r--bottleneck/tests/data/test_829_A30
-rw-r--r--bottleneck/tests/data/test_829_B30
-rw-r--r--bottleneck/tests/data/test_830_A30
-rw-r--r--bottleneck/tests/data/test_830_B30
-rw-r--r--bottleneck/tests/data/test_831_A30
-rw-r--r--bottleneck/tests/data/test_831_B30
-rw-r--r--bottleneck/tests/data/test_832_A30
-rw-r--r--bottleneck/tests/data/test_832_B30
-rw-r--r--bottleneck/tests/data/test_833_A30
-rw-r--r--bottleneck/tests/data/test_833_B30
-rw-r--r--bottleneck/tests/data/test_834_A30
-rw-r--r--bottleneck/tests/data/test_834_B30
-rw-r--r--bottleneck/tests/data/test_835_A30
-rw-r--r--bottleneck/tests/data/test_835_B30
-rw-r--r--bottleneck/tests/data/test_836_A30
-rw-r--r--bottleneck/tests/data/test_836_B30
-rw-r--r--bottleneck/tests/data/test_837_A30
-rw-r--r--bottleneck/tests/data/test_837_B30
-rw-r--r--bottleneck/tests/data/test_838_A30
-rw-r--r--bottleneck/tests/data/test_838_B30
-rw-r--r--bottleneck/tests/data/test_839_A30
-rw-r--r--bottleneck/tests/data/test_839_B30
-rw-r--r--bottleneck/tests/data/test_840_A50
-rw-r--r--bottleneck/tests/data/test_840_B50
-rw-r--r--bottleneck/tests/data/test_841_A50
-rw-r--r--bottleneck/tests/data/test_841_B50
-rw-r--r--bottleneck/tests/data/test_842_A50
-rw-r--r--bottleneck/tests/data/test_842_B50
-rw-r--r--bottleneck/tests/data/test_843_A50
-rw-r--r--bottleneck/tests/data/test_843_B50
-rw-r--r--bottleneck/tests/data/test_844_A50
-rw-r--r--bottleneck/tests/data/test_844_B50
-rw-r--r--bottleneck/tests/data/test_845_A50
-rw-r--r--bottleneck/tests/data/test_845_B50
-rw-r--r--bottleneck/tests/data/test_846_A50
-rw-r--r--bottleneck/tests/data/test_846_B50
-rw-r--r--bottleneck/tests/data/test_847_A50
-rw-r--r--bottleneck/tests/data/test_847_B50
-rw-r--r--bottleneck/tests/data/test_848_A50
-rw-r--r--bottleneck/tests/data/test_848_B50
-rw-r--r--bottleneck/tests/data/test_849_A50
-rw-r--r--bottleneck/tests/data/test_849_B50
-rw-r--r--bottleneck/tests/data/test_850_A50
-rw-r--r--bottleneck/tests/data/test_850_B50
-rw-r--r--bottleneck/tests/data/test_851_A50
-rw-r--r--bottleneck/tests/data/test_851_B50
-rw-r--r--bottleneck/tests/data/test_852_A50
-rw-r--r--bottleneck/tests/data/test_852_B50
-rw-r--r--bottleneck/tests/data/test_853_A50
-rw-r--r--bottleneck/tests/data/test_853_B50
-rw-r--r--bottleneck/tests/data/test_854_A50
-rw-r--r--bottleneck/tests/data/test_854_B50
-rw-r--r--bottleneck/tests/data/test_855_A50
-rw-r--r--bottleneck/tests/data/test_855_B50
-rw-r--r--bottleneck/tests/data/test_856_A50
-rw-r--r--bottleneck/tests/data/test_856_B50
-rw-r--r--bottleneck/tests/data/test_857_A50
-rw-r--r--bottleneck/tests/data/test_857_B50
-rw-r--r--bottleneck/tests/data/test_858_A50
-rw-r--r--bottleneck/tests/data/test_858_B50
-rw-r--r--bottleneck/tests/data/test_859_A50
-rw-r--r--bottleneck/tests/data/test_859_B50
-rw-r--r--bottleneck/tests/data/test_860_A100
-rw-r--r--bottleneck/tests/data/test_860_B100
-rw-r--r--bottleneck/tests/data/test_861_A100
-rw-r--r--bottleneck/tests/data/test_861_B100
-rw-r--r--bottleneck/tests/data/test_862_A100
-rw-r--r--bottleneck/tests/data/test_862_B100
-rw-r--r--bottleneck/tests/data/test_863_A100
-rw-r--r--bottleneck/tests/data/test_863_B100
-rw-r--r--bottleneck/tests/data/test_864_A100
-rw-r--r--bottleneck/tests/data/test_864_B100
-rw-r--r--bottleneck/tests/data/test_865_A100
-rw-r--r--bottleneck/tests/data/test_865_B100
-rw-r--r--bottleneck/tests/data/test_866_A100
-rw-r--r--bottleneck/tests/data/test_866_B100
-rw-r--r--bottleneck/tests/data/test_867_A100
-rw-r--r--bottleneck/tests/data/test_867_B100
-rw-r--r--bottleneck/tests/data/test_868_A100
-rw-r--r--bottleneck/tests/data/test_868_B100
-rw-r--r--bottleneck/tests/data/test_869_A100
-rw-r--r--bottleneck/tests/data/test_869_B100
-rw-r--r--bottleneck/tests/data/test_870_A100
-rw-r--r--bottleneck/tests/data/test_870_B100
-rw-r--r--bottleneck/tests/data/test_871_A100
-rw-r--r--bottleneck/tests/data/test_871_B100
-rw-r--r--bottleneck/tests/data/test_872_A100
-rw-r--r--bottleneck/tests/data/test_872_B100
-rw-r--r--bottleneck/tests/data/test_873_A100
-rw-r--r--bottleneck/tests/data/test_873_B100
-rw-r--r--bottleneck/tests/data/test_874_A100
-rw-r--r--bottleneck/tests/data/test_874_B100
-rw-r--r--bottleneck/tests/data/test_875_A100
-rw-r--r--bottleneck/tests/data/test_875_B100
-rw-r--r--bottleneck/tests/data/test_876_A100
-rw-r--r--bottleneck/tests/data/test_876_B100
-rw-r--r--bottleneck/tests/data/test_877_A100
-rw-r--r--bottleneck/tests/data/test_877_B100
-rw-r--r--bottleneck/tests/data/test_878_A100
-rw-r--r--bottleneck/tests/data/test_878_B100
-rw-r--r--bottleneck/tests/data/test_879_A100
-rw-r--r--bottleneck/tests/data/test_879_B100
-rw-r--r--bottleneck/tests/data/test_list.txt792
-rw-r--r--bottleneck/tests/data/test_list.txt.bak792
-rw-r--r--bottleneck/tests/data/ws_tests/test_100_A100
-rw-r--r--bottleneck/tests/data/ws_tests/test_100_A.pd.diphabin0 -> 2424 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_100_B100
-rw-r--r--bottleneck/tests/data/ws_tests/test_100_B.pd.diphabin0 -> 2424 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_200_A200
-rw-r--r--bottleneck/tests/data/ws_tests/test_200_B200
-rw-r--r--bottleneck/tests/data/ws_tests/test_5000_A5000
-rw-r--r--bottleneck/tests/data/ws_tests/test_5000_B5000
-rw-r--r--bottleneck/tests/data/ws_tests/test_5_A5
-rw-r--r--bottleneck/tests/data/ws_tests/test_5_A.pd.diphabin0 -> 144 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_5_B5
-rw-r--r--bottleneck/tests/data/ws_tests/test_5_B.pd.diphabin0 -> 144 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag1_A1
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag1_A.pd.diphabin0 -> 48 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag1_B1
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag1_B.pd.diphabin0 -> 48 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag2_A1
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag2_A.pd.diphabin0 -> 48 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag2_B1
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag2_B.pd.diphabin0 -> 48 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag3_A220
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag3_A.pd.diphabin0 -> 5304 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag3_B193
-rw-r--r--bottleneck/tests/data/ws_tests/test_diag3_B.pd.diphabin0 -> 4656 bytes
-rw-r--r--bottleneck/tests/data/ws_tests/test_list.txt21
-rw-r--r--bottleneck/tests/test_hera_bottleneck.cpp611
-rw-r--r--bottleneck/tests/tests_main.cpp3
-rw-r--r--license.txt22
-rw-r--r--matching/CMakeLists.txt56
-rw-r--r--matching/README.md69
-rw-r--r--matching/example/matching_dist.cpp366
-rw-r--r--matching/example/module_example.cpp68
-rw-r--r--matching/include/bifiltration.h136
-rw-r--r--matching/include/bifiltration.hpp412
-rw-r--r--matching/include/box.h59
-rw-r--r--matching/include/box.hpp52
-rw-r--r--matching/include/cell_with_value.h141
-rw-r--r--matching/include/cell_with_value.hpp225
-rw-r--r--matching/include/common_defs.h10
-rw-r--r--matching/include/common_util.h183
-rw-r--r--matching/include/common_util.hpp93
-rw-r--r--matching/include/dual_box.h79
-rw-r--r--matching/include/dual_box.hpp188
-rw-r--r--matching/include/dual_point.h107
-rw-r--r--matching/include/dual_point.hpp299
-rw-r--r--matching/include/matching_distance.h290
-rw-r--r--matching/include/matching_distance.hpp722
-rw-r--r--matching/include/opts/opts.h499
-rw-r--r--matching/include/persistence_module.h111
-rw-r--r--matching/include/persistence_module.hpp192
-rw-r--r--matching/include/phat/algorithms/chunk_reduction.h223
-rw-r--r--matching/include/phat/algorithms/row_reduction.h56
-rw-r--r--matching/include/phat/algorithms/spectral_sequence_reduction.h80
-rw-r--r--matching/include/phat/algorithms/standard_reduction.h47
-rw-r--r--matching/include/phat/algorithms/twist_reduction.h51
-rw-r--r--matching/include/phat/boundary_matrix.h343
-rw-r--r--matching/include/phat/compute_persistence_pairs.h137
-rw-r--r--matching/include/phat/helpers/dualize.h74
-rw-r--r--matching/include/phat/helpers/misc.h78
-rw-r--r--matching/include/phat/helpers/thread_local_storage.h52
-rw-r--r--matching/include/phat/persistence_pairs.h155
-rw-r--r--matching/include/phat/representations/abstract_pivot_column.h102
-rw-r--r--matching/include/phat/representations/bit_tree_pivot_column.h165
-rw-r--r--matching/include/phat/representations/full_pivot_column.h100
-rw-r--r--matching/include/phat/representations/heap_pivot_column.h126
-rw-r--r--matching/include/phat/representations/sparse_pivot_column.h79
-rw-r--r--matching/include/phat/representations/vector_heap.h170
-rw-r--r--matching/include/phat/representations/vector_list.h101
-rw-r--r--matching/include/phat/representations/vector_set.h99
-rw-r--r--matching/include/phat/representations/vector_vector.h107
-rw-r--r--matching/include/simplex.h163
-rw-r--r--matching/include/simplex.hpp79
-rw-r--r--matching/tests/prism_1.bif28
-rw-r--r--matching/tests/prism_2.bif29
-rw-r--r--matching/tests/test_bifiltration.cpp36
-rw-r--r--matching/tests/test_common.cpp156
-rw-r--r--matching/tests/test_list.txt1
-rw-r--r--matching/tests/test_matching_distance.cpp159
-rw-r--r--matching/tests/test_module.cpp109
-rw-r--r--matching/tests/tests_main.cpp2
-rw-r--r--wasserstein/CMakeLists.txt62
-rw-r--r--wasserstein/README100
-rw-r--r--wasserstein/example/wasserstein_dist.cpp156
-rw-r--r--wasserstein/example/wasserstein_dist_dipha.cpp133
-rw-r--r--wasserstein/example/wasserstein_dist_point_cloud.cpp175
-rw-r--r--wasserstein/include/auction_oracle.h40
-rw-r--r--wasserstein/include/auction_oracle_base.h85
-rw-r--r--wasserstein/include/auction_oracle_base.hpp97
-rw-r--r--wasserstein/include/auction_oracle_kdtree_pure_geom.h94
-rw-r--r--wasserstein/include/auction_oracle_kdtree_pure_geom.hpp225
-rw-r--r--wasserstein/include/auction_oracle_kdtree_restricted.h119
-rw-r--r--wasserstein/include/auction_oracle_kdtree_restricted.hpp538
-rw-r--r--wasserstein/include/auction_oracle_kdtree_single_diag.h219
-rw-r--r--wasserstein/include/auction_oracle_kdtree_single_diag.hpp717
-rw-r--r--wasserstein/include/auction_oracle_lazy_heap.h191
-rw-r--r--wasserstein/include/auction_oracle_lazy_heap.hpp465
-rw-r--r--wasserstein/include/auction_oracle_stupid_sparse_restricted.h112
-rw-r--r--wasserstein/include/auction_oracle_stupid_sparse_restricted.hpp521
-rw-r--r--wasserstein/include/auction_runner_fr.h272
-rw-r--r--wasserstein/include/auction_runner_fr.hpp1208
-rw-r--r--wasserstein/include/auction_runner_gs.h122
-rw-r--r--wasserstein/include/auction_runner_gs.hpp494
-rw-r--r--wasserstein/include/auction_runner_gs_single_diag.h149
-rw-r--r--wasserstein/include/auction_runner_gs_single_diag.hpp738
-rw-r--r--wasserstein/include/auction_runner_jac.h230
-rw-r--r--wasserstein/include/auction_runner_jac.hpp879
-rw-r--r--wasserstein/include/basic_defs_ws.h321
-rw-r--r--wasserstein/include/basic_defs_ws.hpp220
-rw-r--r--wasserstein/include/def_debug_ws.h44
-rw-r--r--wasserstein/include/diagonal_heap.h149
-rw-r--r--wasserstein/include/diagram_reader.h447
-rw-r--r--wasserstein/include/dnn/geometry/euclidean-dynamic.h270
-rw-r--r--wasserstein/include/dnn/geometry/euclidean-fixed.h196
-rw-r--r--wasserstein/include/dnn/local/kd-tree.h97
-rw-r--r--wasserstein/include/dnn/local/kd-tree.hpp330
-rw-r--r--wasserstein/include/dnn/local/search-functors.h95
-rw-r--r--wasserstein/include/dnn/parallel/tbb.h235
-rw-r--r--wasserstein/include/dnn/parallel/utils.h100
-rw-r--r--wasserstein/include/dnn/utils.h47
-rw-r--r--wasserstein/include/hera_infinity.h22
-rwxr-xr-xwasserstein/include/opts/opts.h353
-rw-r--r--wasserstein/include/wasserstein.h346
-rw-r--r--wasserstein/include/wasserstein_pure_geom.hpp86
-rw-r--r--wasserstein/tests/data/test_100_A100
-rw-r--r--wasserstein/tests/data/test_100_A.pd.diphabin0 -> 2424 bytes
-rw-r--r--wasserstein/tests/data/test_100_B100
-rw-r--r--wasserstein/tests/data/test_100_B.pd.diphabin0 -> 2424 bytes
-rw-r--r--wasserstein/tests/data/test_200_A200
-rw-r--r--wasserstein/tests/data/test_200_B200
-rw-r--r--wasserstein/tests/data/test_5000_A5000
-rw-r--r--wasserstein/tests/data/test_5000_B5000
-rw-r--r--wasserstein/tests/data/test_5_A5
-rw-r--r--wasserstein/tests/data/test_5_A.pd.diphabin0 -> 144 bytes
-rw-r--r--wasserstein/tests/data/test_5_B5
-rw-r--r--wasserstein/tests/data/test_5_B.pd.diphabin0 -> 144 bytes
-rw-r--r--wasserstein/tests/data/test_diag1_A1
-rw-r--r--wasserstein/tests/data/test_diag1_A.pd.diphabin0 -> 48 bytes
-rw-r--r--wasserstein/tests/data/test_diag1_B1
-rw-r--r--wasserstein/tests/data/test_diag1_B.pd.diphabin0 -> 48 bytes
-rw-r--r--wasserstein/tests/data/test_diag2_A1
-rw-r--r--wasserstein/tests/data/test_diag2_A.pd.diphabin0 -> 48 bytes
-rw-r--r--wasserstein/tests/data/test_diag2_B1
-rw-r--r--wasserstein/tests/data/test_diag2_B.pd.diphabin0 -> 48 bytes
-rw-r--r--wasserstein/tests/data/test_diag3_A220
-rw-r--r--wasserstein/tests/data/test_diag3_A.pd.diphabin0 -> 5304 bytes
-rw-r--r--wasserstein/tests/data/test_diag3_B193
-rw-r--r--wasserstein/tests/data/test_diag3_B.pd.diphabin0 -> 4656 bytes
-rw-r--r--wasserstein/tests/data/test_list.txt21
-rw-r--r--wasserstein/tests/test_hera_wasserstein.cpp532
-rw-r--r--wasserstein/tests/test_hera_wasserstein_pure_geom.cpp111
-rw-r--r--wasserstein/tests/tests_main.cpp3
-rw-r--r--wasserstein/tests/tests_reader.h67
1769 files changed, 89588 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8d53708
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,37 @@
+/*.cfg
+/build
+build/
+*.gitattributes
+*.opensdf
+*.sdf
+*.suo
+*.vcxproj
+*.filters
+*.log
+*.tlog
+*.lastbuildstate
+*.obj
+*.idb
+*.pdb
+*.exe
+*.ilk
+*.user
+*.out
+*.output
+*.pyc
+*.*~*
+*.swp
+*.nfs*
+*.pdf
+*.o
+*.d
+*.dll
+*.lib
+*.exe
+makeout
+/MS_Win32
+/bin
+bottleneck/build/
+ann/lib
+ann/bin
+ann/lib/dummy
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..29945f3
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,41 @@
+This repository contains software to compute bottleneck and Wasserstein
+distances between persistence diagrams, and matching distance
+between 2-parameter persistence modules and (1-critical) bi-filtrations.
+
+The software is licensed under
+BSD license, see license.txt file.
+If you are going to use this software for research purposes,
+you probably do not need to worry about that.
+
+See README files in subdirectories for usage and building.
+
+If you use Hera in your project, we would appreciate if you
+cite the corresponding paper.
+
+Bottleneck or Wasserstein distance:
+
+Michael Kerber, Dmitriy Morozov, and Arnur Nigmetov,
+"Geometry Helps to Compare Persistence Diagrams.",
+Journal of Experimental Algorithmics, vol. 22, 2017, pp. 1--20.
+(conference version: ALENEX 2016).
+
+@article{jea_hera,
+ title={Geometry helps to compare persistence diagrams},
+ author={Kerber, Michael and Morozov, Dmitriy and Nigmetov, Arnur},
+ journal={Journal of Experimental Algorithmics (JEA)},
+ volume={22},
+ pages={1--20},
+ year={2017},
+ publisher={ACM New York, NY, USA}
+}
+
+Matching distance:
+
+Michael Kerber, Arnur Nigmetov, "Efficient Approximation of the Matching
+Distance for 2-parameter persistence.", SoCG 2020
+
+Changes:
+
+09.03.2020. Add matching distance, change directory names.
+WARNING: geom_bottleneck -> bottleneck
+ geom_matching/wasserstein -> wasserstein
diff --git a/bottleneck/CMakeLists.txt b/bottleneck/CMakeLists.txt
new file mode 100644
index 0000000..7a820ac
--- /dev/null
+++ b/bottleneck/CMakeLists.txt
@@ -0,0 +1,38 @@
+project (geom_bottleneck)
+cmake_minimum_required (VERSION 3.5.1)
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+# C++ 11 required
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+# Default to Release
+
+if (NOT CMAKE_BUILD_TYPE)
+ set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
+endif (NOT CMAKE_BUILD_TYPE)
+
+if(NOT WIN32)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -D_GLIBCXX_DEBUG")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 ")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -O2 -g -ggdb")
+endif(NOT WIN32)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+file(GLOB WS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
+
+
+
+find_package (Threads)
+set (libraries ${libraries} ${CMAKE_THREAD_LIBS_INIT})
+
+add_executable(bottleneck_dist ${CMAKE_CURRENT_SOURCE_DIR}/example/bottleneck_dist.cpp ${WS_HEADERS})
+target_link_libraries(bottleneck_dist PUBLIC ${libraries})
+
+add_executable(bottleneck_test ${CMAKE_CURRENT_SOURCE_DIR}/tests/tests_main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_hera_bottleneck.cpp)
+target_link_libraries(bottleneck_test PUBLIC ${libraries})
diff --git a/bottleneck/README b/bottleneck/README
new file mode 100644
index 0000000..c04390b
--- /dev/null
+++ b/bottleneck/README
@@ -0,0 +1,98 @@
+Accompanying paper: M. Kerber, D. Morozov, A. Nigmetov. Geometry Helps To Compare Persistence Diagrams (ALENEX 2016, http://www.geometrie.tugraz.at/nigmetov/geom_dist.pdf)
+
+Bug reports can be sent to "anigmetov EMAIL SIGN lbl DOT gov".
+
+# Dependencies
+
+Your compiler must support C++11.
+
+# Usage:
+
+1. To use a standalone command-line utility bottleneck_dist:
+
+bottleneck_dist file1 file2 [relative_error].
+
+If relative error is not supplied, the exact distance is computed and printed.
+If two diagrams are equal, then the exact distance 0.0 is printed (the order
+of points in file1 and file2 need not be the same).
+Otherwise the output is an approximation of the exact distance. Precisely:
+if d_exact is the true distance and d_approx is the output, then
+
+ | d_exact - d_approx | / d_exact < relative_error.
+
+file1 and file2 must contain persistence diagrams in plain text format
+(one point per line, empty lines are ignored, comments can be made with #):
+
+# this is how your input can look like
+x_1 y_1 # two real numbers per line
+...
+# empty lines or comments are ignored
+x_n y_n
+
+2. To use from your code:
+
+#include "bottleneck.h"
+
+// the functions hera::bottleneckDistExact, hera::bottleneckDistApprox
+// return the exact and approximate bottleneck distance.
+
+// function hera::readDiagramPointSet reads diagram from a plain-text file.
+
+std::vector<std::pair<double, double>> diagram1, diagram2;
+// any container class that supports range-for loops will do.
+// A pair represents a single point,
+// first component = x-coordinate,
+// second component = y-coordinate.
+// ...
+// load your diagrams into diagram1, diagram2 (off-diagonal points).
+// If you data is in plain text format, you can use readDiagramPointSet function:
+
+if (!hera::readDiagramPointSet("diagram1.txt", diagram1)) {
+ // something went wrong: function returns true if it successfully read the file
+ }
+
+// OK: diagram1.txt was read.
+// ...
+// to get exact distance:
+double btDist = hera::bottleneckDistExact(diagram1, diagram2);
+// to get 1% approximation
+double btDistApprox = hera::bottleneckDistApprox(diagram1, diagram2, 0.01);
+// ..............................................................................
+// if diagrams will be used many times, you may want to avoid copying them
+// to hera::bt::DiagramPointSet (which is done internally in each call to
+bottleneckDistExact/bottleneckDistApprox) and do it yourself once.
+// Constructor takes two iterators:
+hera::bt::DiagramPointSet ds1(diagram1.begin(), diagram1.end());
+hera::bt::DiagramPointSet ds2(diagram2.begin(), diagram2.end());
+btDist = hera::bt::bottleneckDistExact(ds1, ds2);
+btDistApprox = hera::bt::bottleneckDistApprox(ds1, ds2, 0.01);
+
+Necessary projections (diagonal points) will be added in the bottleneckDistApprox
+function.
+
+See also code in example/bottleneck_dist.cpp.
+
+# Remarks:
+
+1) If bottleneckDistApprox is called with epsilon = 0.0, it will never return.
+2) Empty diagrams are not considered as error.
+
+# License
+
+See licence.txt
+
+# Building
+
+CMakeLists.txt in the root directory can be used to build
+the command-line utility (in example/ directory).
+The library itself is header-only and does not require separate compilation.
+
+On Linux/Mac:
+
+mkdir build
+cd build
+cmake ..
+make
+
+On Windows:
+use cmake-gui to create the solution in build directory and build it with VS.
diff --git a/bottleneck/example/CMakeLists.txt b/bottleneck/example/CMakeLists.txt
new file mode 100644
index 0000000..3ae8536
--- /dev/null
+++ b/bottleneck/example/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 2.8.9)
+
+# Default to Release
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif(NOT CMAKE_BUILD_TYPE)
+
+# Add path to ANN header files
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../bottleneck/include")
+
+set(CXX_FLAGS ${CMAKE_CXX_FLAGS_RELEASE})
+
+if(NOT WIN32)
+ set(CMAKE_CXX_FLAGS "-O3 -DNDEBUG -DBOOST_DISABLE_ASSERTS")
+ add_definitions(-std=c++11)
+endif(NOT WIN32)
+
+
+if(UNIX)
+ # specify full path to ANN
+ set_property(TARGET bottleneck PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../bottleneck/build/libbottleneck.a")
+endif(UNIX)
+
+add_executable (bottleneck_dist bottleneck_dist.cpp)
+
+target_link_libraries(bottleneck_dist PUBLIC bottleneck)
+
diff --git a/bottleneck/example/bottleneck_dist.cpp b/bottleneck/example/bottleneck_dist.cpp
new file mode 100644
index 0000000..8966789
--- /dev/null
+++ b/bottleneck/example/bottleneck_dist.cpp
@@ -0,0 +1,96 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#include <iomanip>
+#include "bottleneck.h"
+
+// any container of pairs of doubles can be used,
+// we use vector in this example.
+
+typedef std::vector<std::pair<double, double>> PairVector;
+
+// estimate initial guess on sampled diagram?
+constexpr bool useSamplingHeur = false;
+// if diagrams contain fewer points, don't use heuristic
+constexpr int heurThreshold = 30000;
+
+int main(int argc, char* argv[])
+{
+ if (argc < 3 ) {
+ std::cerr << "Usage: " << argv[0] << " file1 file2 [relative_error]. Without relative_error calculate the exact distance." << std::endl;
+ return 1;
+ }
+
+ PairVector diagramA, diagramB;
+ int decPrecision { 0 };
+ if (!hera::readDiagramPointSet(argv[1], diagramA, decPrecision)) {
+ std::exit(1);
+ }
+
+ if (!hera::readDiagramPointSet(argv[2], diagramB, decPrecision)) {
+ std::exit(1);
+ }
+
+ double res;
+ hera::bt::MatchingEdge<double> e;
+ if (argc >= 4) {
+ // the third parameter is epsilon,
+ // return approximate distance (faster)
+ double delta = atof(argv[3]);
+ if (delta > 0.0) {
+ if (useSamplingHeur && diagramA.size() > heurThreshold && diagramB.size() > heurThreshold) {
+ res = hera::bottleneckDistApproxHeur(diagramA, diagramB, delta);
+ } else {
+ res = hera::bottleneckDistApprox(diagramA, diagramB, delta, e, true);
+ }
+ } else if (delta == 0.0) {
+ res = hera::bottleneckDistExact(diagramA, diagramB, decPrecision);
+ } else {
+ std::cerr << "The third parameter (relative error) must be positive!" << std::endl;
+ std::exit(1);
+ }
+ } else {
+ // only filenames have been supplied, return exact distance
+ res = hera::bottleneckDistExact(diagramA, diagramB, decPrecision, e, true);
+
+ }
+ std::cout << std::setprecision(15) << res << std::endl;
+ //std::cout << "Longest edge " << e.first.get_user_id() << " <-> " << e.second.get_user_id() << std::endl;
+ //std::cout << "Longest edge " << e.first << " <-> " << e.second << std::endl;
+ // Alternative could be to construct DiagramPointSet
+ // using the constructor with iterators.
+ // May be useful if the same diagram is used multiple times
+ // to avoid copying data from user's container each time.
+
+ //hera::bt::DiagramPointSet dA(diagramA);
+ //hera::bt::DiagramPointSet dB(diagramB);
+ //double result1 = hera::bt::bottleneckDistExact(dA, dB);
+ //std::cout << std::setprecision(15) << result1 << std::endl;
+
+ return 0;
+}
diff --git a/bottleneck/include/basic_defs_bt.h b/bottleneck/include/basic_defs_bt.h
new file mode 100644
index 0000000..172e0f7
--- /dev/null
+++ b/bottleneck/include/basic_defs_bt.h
@@ -0,0 +1,569 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_BASIC_DEFS_BT_H
+#define HERA_BASIC_DEFS_BT_H
+
+#ifdef _WIN32
+#include <ciso646>
+#endif
+
+#include <utility>
+#include <vector>
+#include <stdexcept>
+#include <math.h>
+#include <cstddef>
+#include <unordered_map>
+#include <unordered_set>
+#include <string>
+#include <assert.h>
+
+#include "def_debug_bt.h"
+
+#ifndef FOR_R_TDA
+
+#include <iostream>
+
+#endif
+
+namespace hera {
+
+ template<class Real = double>
+ Real get_infinity()
+ {
+ return Real(-1.0);
+ }
+
+ namespace bt {
+
+
+ typedef int IdType;
+ constexpr IdType MinValidId = 10;
+
+ template<class Real = double>
+ struct Point
+ {
+ Real x, y;
+
+ bool operator==(const Point<Real>& other) const
+ {
+ return ((this->x == other.x) and (this->y == other.y));
+ }
+
+ bool operator!=(const Point<Real>& other) const
+ {
+ return !(*this == other);
+ }
+
+ Point(Real ax, Real ay) :
+ x(ax), y(ay)
+ {}
+
+ Point() :
+ x(0.0), y(0.0)
+ {}
+
+#ifndef FOR_R_TDA
+
+ template<class R>
+ friend std::ostream& operator<<(std::ostream& output, const Point<R>& p)
+ {
+ output << "(" << p.x << ", " << p.y << ")";
+ return output;
+ }
+
+#endif
+ };
+
+ template<class Real = double>
+ struct DiagramPoint
+ {
+ // Points above the diagonal have type NORMAL
+ // Projections onto the diagonal have type DIAG
+ // for DIAG points only x-coordinate is relevant
+ // to-do: add getters/setters, checks in constructors, etc
+ enum Type
+ {
+ NORMAL, DIAG
+ };
+ // data members
+ private:
+ Real x, y;
+ public:
+ Type type;
+ IdType id;
+ IdType user_id;
+
+ // operators, constructors
+ bool operator==(const DiagramPoint<Real>& other) const
+ {
+ // compare by id only
+ assert(this->id >= MinValidId);
+ assert(other.id >= MinValidId);
+ bool areEqual { this->id == other.id };
+ assert(!areEqual or ((this->x == other.x) and (this->y == other.y) and (this->type == other.type)));
+ return areEqual;
+ }
+
+ bool operator!=(const DiagramPoint& other) const
+ {
+ return !(*this == other);
+ }
+
+ DiagramPoint() :
+ x(0.0),
+ y(0.0),
+ type(DiagramPoint::DIAG),
+ id(MinValidId - 1),
+ user_id(-1)
+ {
+ }
+
+ DiagramPoint(Real _x, Real _y, Type _type, IdType _id, IdType _user_id) :
+ x(_x),
+ y(_y),
+ type(_type),
+ id(_id),
+ user_id(_user_id)
+ {
+ if (_y == _x and _type != DIAG) {
+ throw std::runtime_error("Point on the main diagonal must have DIAG type");
+ }
+
+ }
+
+
+ bool isDiagonal() const
+ { return type == DIAG; }
+
+ bool isNormal() const
+ { return type == NORMAL; }
+
+ bool isInfinity() const
+ {
+ return x == std::numeric_limits<Real>::infinity() or
+ x == -std::numeric_limits<Real>::infinity() or
+ y == std::numeric_limits<Real>::infinity() or
+ y == -std::numeric_limits<Real>::infinity();
+ }
+
+ Real inline getRealX() const // return the x-coord
+ {
+ return x;
+ }
+
+ Real inline getRealY() const // return the y-coord
+ {
+ return y;
+ }
+
+ IdType inline get_user_id() const
+ {
+ if (isNormal())
+ return user_id;
+ else
+ return -1;
+ }
+
+ Real inline get_persistence(const Real internal_p = get_infinity()) const
+ {
+ if (isDiagonal())
+ return 0.0;
+ Real pers = fabs(y - x) / 2;
+ if (internal_p == get_infinity()) {
+ return pers;
+ } else if (internal_p == 1.0) {
+ return 2 * pers;
+ } else {
+ return std::pow(static_cast<Real>(2), static_cast<Real>(1) / internal_p);
+ }
+ }
+
+#ifndef FOR_R_TDA
+
+ friend std::ostream& operator<<(std::ostream& output, const DiagramPoint& p)
+ {
+ if (p.isDiagonal()) {
+ output << "(" << p.x << ", " << p.y << ", " << 0.5 * (p.x + p.y) << ", " << p.id << " DIAG )";
+ } else {
+ output << "(" << p.x << ", " << p.y << ", " << p.id << " NORMAL)";
+ }
+ return output;
+ }
+#endif
+ };
+
+ template<class Real>
+ using MatchingEdge = std::pair<DiagramPoint<Real>, DiagramPoint<Real>>;
+
+ // compute l-inf distance between two diagram points
+ template<class Real>
+ inline Real distLInf(const DiagramPoint<Real>& a, const DiagramPoint<Real>& b)
+ {
+ if (a.isDiagonal() and b.isDiagonal()) {
+ // distance between points on the diagonal is 0
+ return 0.0;
+ }
+ // otherwise distance is a usual l-inf distance
+ return std::max(fabs(a.getRealX() - b.getRealX()), fabs(a.getRealY() - b.getRealY()));
+ }
+
+ // this function works with points at infinity as well
+ // not needed in actual computation, since these points are processed
+ // separately, but is useful in tests
+ template<class Real>
+ inline Real dist_l_inf_slow(const DiagramPoint<Real>& a, const DiagramPoint<Real>& b)
+ {
+ if (a.isDiagonal() and b.isDiagonal()) {
+ // distance between points on the diagonal is 0
+ return 0.0;
+ }
+ // otherwise distance is a usual l-inf distance
+ //
+ Real dx = (a.getRealX() == b.getRealX()) ? 0.0 : fabs(a.getRealX() - b.getRealX());
+ Real dy = (a.getRealY() == b.getRealY()) ? 0.0 : fabs(a.getRealY() - b.getRealY());
+ Real result = std::max(dx, dy);
+ if (std::isnan(result))
+ result = std::numeric_limits<Real>::infinity();
+ return result;
+ }
+
+
+
+ template<class Real = double>
+ inline Real get_infinity()
+ {
+ return Real(-1.0);
+ }
+
+ template<class T>
+ inline void hash_combine(std::size_t& seed, const T& v)
+ {
+ std::hash<T> hasher;
+ seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+
+ template<class Real = double>
+ struct DiagramPointHash
+ {
+ size_t operator()(const DiagramPoint<Real>& p) const
+ {
+ assert(p.id >= MinValidId);
+ return std::hash<int>()(p.id);
+ }
+ };
+
+ template<class Real = double>
+ Real distLInf(const DiagramPoint<Real>& a, const DiagramPoint<Real>& b);
+
+ //template<class Real = double>
+ //typedef std::unordered_set<Point, PointHash> PointSet;
+ template<class Real_ = double>
+ class DiagramPointSet;
+
+ template<class Real>
+ void addProjections(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B);
+
+ template<class Real_>
+ class DiagramPointSet
+ {
+ public:
+
+ using Real = Real_;
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointHash = DiagramPointHash<Real>;
+ using const_iterator = typename std::unordered_set<DgmPoint, DgmPointHash>::const_iterator;
+ using iterator = typename std::unordered_set<DgmPoint, DgmPointHash>::iterator;
+
+ private:
+
+ bool isLinked { false };
+ IdType maxId { MinValidId + 1 };
+ std::unordered_set<DgmPoint, DgmPointHash> points;
+
+ public:
+
+ void insert(const DgmPoint& p)
+ {
+ points.insert(p);
+ if (p.id > maxId) {
+ maxId = p.id + 1;
+ }
+ }
+
+ void erase(const DgmPoint& p, bool doCheck = true)
+ {
+ // if doCheck, erasing non-existing elements causes assert
+ auto it = points.find(p);
+ if (it != points.end()) {
+ points.erase(it);
+ } else {
+ assert(!doCheck);
+ }
+ }
+
+
+ void erase(const const_iterator it)
+ {
+ points.erase(it);
+ }
+
+ void removeDiagonalPoints()
+ {
+ if (isLinked) {
+ auto ptIter = points.begin();
+ while (ptIter != points.end()) {
+ if (ptIter->isDiagonal()) {
+ ptIter = points.erase(ptIter);
+ } else {
+ ptIter++;
+ }
+ }
+ isLinked = false;
+ }
+ }
+
+ size_t size() const
+ {
+ return points.size();
+ }
+
+ void reserve(const size_t newSize)
+ {
+ points.reserve(newSize);
+ }
+
+ void clear()
+ {
+ points.clear();
+ }
+
+ bool empty() const
+ {
+ return points.empty();
+ }
+
+ bool hasElement(const DgmPoint& p) const
+ {
+ return points.find(p) != points.end();
+ }
+
+ iterator find(const DgmPoint& p)
+ {
+ return points.find(p);
+ }
+
+ iterator begin()
+ {
+ return points.begin();
+ }
+
+ iterator end()
+ {
+ return points.end();
+ }
+
+ const_iterator cbegin() const
+ {
+ return points.cbegin();
+ }
+
+ const_iterator cend() const
+ {
+ return points.cend();
+ }
+
+
+ const_iterator find(const DgmPoint& p) const
+ {
+ return points.find(p);
+ }
+
+#ifndef FOR_R_TDA
+
+ friend std::ostream& operator<<(std::ostream& output, const DiagramPointSet& ps)
+ {
+ output << "{ ";
+ for (auto pit = ps.cbegin(); pit != ps.cend(); ++pit) {
+ output << *pit << ", ";
+ }
+ output << "\b\b }";
+ return output;
+ }
+
+#endif
+
+ friend void addProjections<Real_>(DiagramPointSet<Real_>& A, DiagramPointSet<Real_>& B);
+
+ template<class PairIterator>
+ void fillIn(PairIterator begin_iter, PairIterator end_iter)
+ {
+ isLinked = false;
+ clear();
+ IdType uniqueId = MinValidId + 1;
+ IdType user_id = 0;
+ for (auto iter = begin_iter; iter != end_iter; ++iter) {
+ insert(DgmPoint(iter->first, iter->second, DgmPoint::NORMAL, uniqueId++, user_id++));
+ }
+ }
+
+ template<class PointContainer>
+ void fillIn(const PointContainer& dgm_cont)
+ {
+ using Traits = DiagramTraits<PointContainer>;
+ isLinked = false;
+ clear();
+ IdType uniqueId = MinValidId + 1;
+ IdType user_id = 0;
+ for (const auto& pt : dgm_cont) {
+ Real x = Traits::get_x(pt);
+ Real y = Traits::get_y(pt);
+ insert(DgmPoint(x, y, DgmPoint::NORMAL, uniqueId++, user_id++));
+ }
+ }
+
+
+ // ctor from range
+ template<class PairIterator>
+ DiagramPointSet(PairIterator begin_iter, PairIterator end_iter)
+ {
+ fillIn(begin_iter, end_iter);
+ }
+
+ // ctor from container, uses DiagramTraits
+ template<class PointContainer>
+ DiagramPointSet(const PointContainer& dgm)
+ {
+ fillIn(dgm);
+ }
+
+
+ // default ctor, empty diagram
+ DiagramPointSet(IdType minId = MinValidId + 1) :
+ maxId(minId + 1)
+ {};
+
+ IdType nextId()
+ { return maxId + 1; }
+
+ }; // DiagramPointSet
+
+
+ template<class Real, class DiagPointContainer>
+ Real getFurthestDistance3Approx(DiagPointContainer& A, DiagPointContainer& B)
+ {
+ Real result { 0.0 };
+ DiagramPoint<Real> begA = *(A.begin());
+ DiagramPoint<Real> optB = *(B.begin());
+ for (const auto& pointB : B) {
+ if (distLInf(begA, pointB) > result) {
+ result = distLInf(begA, pointB);
+ optB = pointB;
+ }
+ }
+ for (const auto& pointA : A) {
+ if (distLInf(pointA, optB) > result) {
+ result = distLInf(pointA, optB);
+ }
+ }
+ return result;
+ }
+
+ // preprocess diagrams A and B by adding projections onto diagonal of points of
+ // A to B and vice versa. Also removes points at infinity!
+ // NB: ids of points will be changed!
+ template<class Real_>
+ void addProjections(DiagramPointSet<Real_>& A, DiagramPointSet<Real_>& B)
+ {
+
+ using Real = Real_;
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointSet = DiagramPointSet<Real>;
+
+ IdType uniqueId { MinValidId + 1 };
+ DgmPointSet newA, newB;
+
+ // copy normal points from A to newA
+ // add projections to newB
+ for (auto& pA : A) {
+ if (pA.isNormal() and not pA.isInfinity()) {
+ // add pA's projection to B
+ DgmPoint dpA { pA.getRealX(), pA.getRealY(), DgmPoint::NORMAL, uniqueId++, pA.get_user_id() };
+ DgmPoint dpB { (pA.getRealX() + pA.getRealY()) / 2, (pA.getRealX() + pA.getRealY()) / 2,
+ DgmPoint::DIAG, uniqueId++, -1 };
+ newA.insert(dpA);
+ newB.insert(dpB);
+ }
+ }
+
+ for (auto& pB : B) {
+ if (pB.isNormal() and not pB.isInfinity()) {
+ // add pB's projection to A
+ DgmPoint dpB { pB.getRealX(), pB.getRealY(), DgmPoint::NORMAL, uniqueId++, pB.get_user_id() };
+ DgmPoint dpA { (pB.getRealX() + pB.getRealY()) / 2, (pB.getRealX() + pB.getRealY()) / 2,
+ DgmPoint::DIAG, uniqueId++, -1 };
+ newB.insert(dpB);
+ newA.insert(dpA);
+ }
+ }
+
+ A = newA;
+ B = newB;
+ A.isLinked = true;
+ B.isLinked = true;
+ }
+
+ //#ifndef FOR_R_TDA
+
+ //template<class Real>
+ //std::ostream& operator<<(std::ostream& output, const DiagramPoint<Real>& p)
+ //{
+ // if ( p.isDiagonal() ) {
+ // output << "(" << p.x << ", " << p.y << ", " << 0.5 * (p.x + p.y) << ", " << p.id << " DIAG )";
+ // } else {
+ // output << "(" << p.x << ", " << p.y << ", " << p.id << " NORMAL)";
+ // }
+ // return output;
+ //}
+
+ //template<class Real>
+ //std::ostream& operator<<(std::ostream& output, const DiagramPointSet<Real>& ps)
+ //{
+ // output << "{ ";
+ // for(auto pit = ps.cbegin(); pit != ps.cend(); ++pit) {
+ // output << *pit << ", ";
+ // }
+ // output << "\b\b }";
+ // return output;
+ //}
+ //#endif // FOR_R_TDA
+
+
+ } // end namespace bt
+} // end namespace hera
+#endif // HERA_BASIC_DEFS_BT_H
diff --git a/bottleneck/include/bottleneck.h b/bottleneck/include/bottleneck.h
new file mode 100644
index 0000000..64da2c8
--- /dev/null
+++ b/bottleneck/include/bottleneck.h
@@ -0,0 +1,153 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_BOTTLENECK_H
+#define HERA_BOTTLENECK_H
+
+
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <limits>
+#include <random>
+
+#include "diagram_traits.h"
+#include "diagram_reader.h"
+#include "bottleneck_detail.h"
+#include "basic_defs_bt.h"
+#include "bound_match.h"
+
+namespace hera {
+ // internal_p defines cost function on edges (use hera::get_infinity(),
+ // if you want to explicitly refer to l_inf, but that's default value
+ // delta is relative error, default is 1 percent
+ template<class Real = double>
+ struct BottleneckParams
+ {
+ Real internal_p { hera::get_infinity() };
+ Real delta { 0.01 };
+ };
+
+ // functions taking containers as input
+ // template parameter PairContainer must be a container of pairs of real
+ // numbers (pair.first = x-coordinate, pair.second = y-coordinate)
+ // PairContainer class must support iteration of the form
+ // for(it = pairContainer.begin(); it != pairContainer.end(); ++it)
+
+ // all functions in this header are wrappers around
+ // functions from hera::bt namespace
+
+ // get exact bottleneck distance,
+ template<class PairContainer>
+ typename DiagramTraits<PairContainer>::RealType
+ bottleneckDistExact(PairContainer& dgm_A, PairContainer& dgm_B, const int decPrecision,
+ hera::bt::MatchingEdge<typename DiagramTraits<PairContainer>::RealType>& longest_edge,
+ bool compute_longest_edge = true)
+ {
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ hera::bt::DiagramPointSet<Real> a(dgm_A);
+ hera::bt::DiagramPointSet<Real> b(dgm_B);
+ return hera::bt::bottleneckDistExact(a, b, decPrecision, longest_edge, compute_longest_edge);
+ }
+
+ template<class PairContainer>
+ typename DiagramTraits<PairContainer>::RealType
+ bottleneckDistExact(PairContainer& dgm_A, PairContainer& dgm_B, const int decPrecision)
+ {
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ hera::bt::MatchingEdge<Real> longest_edge;
+ return bottleneckDistExact(dgm_A, dgm_B, decPrecision, longest_edge, false);
+ }
+
+
+ template<class PairContainer>
+ typename DiagramTraits<PairContainer>::RealType
+ bottleneckDistExact(PairContainer& dgm_A, PairContainer& dgm_B)
+ {
+ int dec_precision = 14;
+ return bottleneckDistExact(dgm_A, dgm_B, dec_precision);
+ }
+
+
+// return the interval (distMin, distMax) such that:
+// a) actual bottleneck distance between A and B is contained in the interval
+// b) if the interval is not (0,0), then (distMax - distMin) / distMin < delta
+ template<class PairContainer>
+ std::pair<typename DiagramTraits<PairContainer>::RealType, typename DiagramTraits<PairContainer>::RealType>
+ bottleneckDistApproxInterval(PairContainer& dgm_A, PairContainer& dgm_B,
+ const typename DiagramTraits<PairContainer>::RealType delta)
+ {
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ hera::bt::DiagramPointSet<Real> a(dgm_A);
+ hera::bt::DiagramPointSet<Real> b(dgm_B);
+ return hera::bt::bottleneckDistApproxInterval(a, b, delta);
+ }
+
+// use sampling heuristic: discard most of the points with small persistency
+// to get a good initial approximation of the bottleneck distance
+ template<class PairContainer>
+ typename DiagramTraits<PairContainer>::RealType
+ bottleneckDistApproxHeur(PairContainer& dgm_A, PairContainer& dgm_B,
+ const typename DiagramTraits<PairContainer>::RealType delta)
+ {
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ hera::bt::DiagramPointSet<Real> a(dgm_A);
+ hera::bt::DiagramPointSet<Real> b(dgm_B);
+ std::pair<Real, Real> resPair = hera::bt::bottleneckDistApproxIntervalHeur(a, b, delta);
+ return resPair.second;
+ }
+
+// get approximate distance,
+// see bottleneckDistApproxInterval
+ template<class PairContainer>
+ typename DiagramTraits<PairContainer>::RealType
+ bottleneckDistApprox(PairContainer& A, PairContainer& B,
+ const typename DiagramTraits<PairContainer>::RealType delta,
+ hera::bt::MatchingEdge<typename DiagramTraits<PairContainer>::RealType>& longest_edge,
+ bool compute_longest_edge = true)
+ {
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ hera::bt::DiagramPointSet<Real> a(A.begin(), A.end());
+ hera::bt::DiagramPointSet<Real> b(B.begin(), B.end());
+ return hera::bt::bottleneckDistApprox(a, b, delta, longest_edge, compute_longest_edge);
+ }
+
+ template<class PairContainer>
+ typename DiagramTraits<PairContainer>::RealType
+ bottleneckDistApprox(PairContainer& A, PairContainer& B,
+ const typename DiagramTraits<PairContainer>::RealType delta)
+ {
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ hera::bt::MatchingEdge<Real> longest_edge;
+ return hera::bottleneckDistApprox(A, B, delta, longest_edge, false);
+ }
+
+
+} // end namespace hera
+
+#endif
diff --git a/bottleneck/include/bottleneck_detail.h b/bottleneck/include/bottleneck_detail.h
new file mode 100644
index 0000000..7241c9a
--- /dev/null
+++ b/bottleneck/include/bottleneck_detail.h
@@ -0,0 +1,90 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_BOTTLENECK_DETAIL_H
+#define HERA_BOTTLENECK_DETAIL_H
+
+
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <limits>
+#include <random>
+
+#include "diagram_traits.h"
+#include "basic_defs_bt.h"
+#include "bound_match.h"
+
+namespace hera {
+
+
+ namespace bt {
+
+ // functions taking DiagramPointSet as input.
+ // ATTENTION: parameters A and B (diagrams) will be changed after the call
+ // (projections added).
+
+ // return the interval (distMin, distMax) such that:
+ // a) actual bottleneck distance between A and B is contained in the interval
+ // b) if the interval is not (0,0), then (distMax - distMin) / distMin < epsilon
+ template<class Real>
+ std::pair<Real, Real> bottleneckDistApproxInterval(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B,
+ const Real epsilon, MatchingEdge<Real>& longest_edge,
+ bool compute_longest_edge = false);
+
+
+ // heuristic (sample diagram to estimate the distance)
+ template<class Real>
+ std::pair<Real, Real>
+ bottleneckDistApproxIntervalHeur(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B, const Real epsilon,
+ bool compute_longest_edge = false);
+
+ // get approximate distance,
+ // see bottleneckDistApproxInterval
+ template<class Real>
+ Real bottleneckDistApprox(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B, const Real epsilon,
+ MatchingEdge<Real>& longest_edge, bool compute_longest_edge = false);
+
+ // get exact bottleneck distance,
+ template<class Real>
+ Real bottleneckDistExact(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B, const int decPrecision,
+ MatchingEdge<Real>& longest_edge, bool compute_longest_edge = false);
+
+ // get exact bottleneck distance,
+ template<class Real>
+ Real bottleneckDistExact(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B, MatchingEdge<Real>& longest_edge,
+ bool compute_longest_edge = false);
+
+ } // end namespace bt
+
+
+} // end namespace hera
+
+#include "bottleneck_detail.hpp"
+
+#endif // HERA_BOTTLENECK_DETAIL_H
diff --git a/bottleneck/include/bottleneck_detail.hpp b/bottleneck/include/bottleneck_detail.hpp
new file mode 100644
index 0000000..8f51d07
--- /dev/null
+++ b/bottleneck/include/bottleneck_detail.hpp
@@ -0,0 +1,636 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_BOTTLENECK_HPP
+#define HERA_BOTTLENECK_HPP
+
+#ifdef FOR_R_TDA
+#undef DEBUG_BOUND_MATCH
+#undef DEBUG_MATCHING
+#undef VERBOSE_BOTTLENECK
+#endif
+
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <cctype>
+#include <set>
+
+#include "bottleneck_detail.h"
+
+namespace hera {
+ namespace bt {
+
+ template<class Real>
+ void binarySearch(const Real epsilon,
+ std::pair<Real, Real>& result,
+ BoundMatchOracle <Real>& oracle,
+ const Real infinityCost,
+ bool isResultInitializedCorrectly,
+ const Real distProbeInit)
+ {
+ // aliases for result components
+ Real& distMin = result.first;
+ Real& distMax = result.second;
+
+ distMin = std::max(distMin, infinityCost);
+ distMax = std::max(distMax, infinityCost);
+
+ Real distProbe;
+
+ if (not isResultInitializedCorrectly) {
+ distProbe = distProbeInit;
+ if (oracle.isMatchLess(distProbe)) {
+ // distProbe is an upper bound,
+ // find lower bound with binary search
+ do {
+ distMax = distProbe;
+ distProbe /= 2.0;
+ } while (oracle.isMatchLess(distProbe));
+ distMin = distProbe;
+ } else {
+ // distProbe is a lower bound,
+ // find upper bound with exponential search
+ do {
+ distMin = distProbe;
+ distProbe *= 2.0;
+ } while (!oracle.isMatchLess(distProbe));
+ distMax = distProbe;
+ }
+ }
+ // bounds are correct , perform binary search
+ distProbe = (distMin + distMax) / 2.0;
+ while ((distMax - distMin) / distMin >= epsilon) {
+
+ if (distMax < infinityCost) {
+ distMin = infinityCost;
+ distMax = infinityCost;
+ break;
+ }
+
+ if (oracle.isMatchLess(distProbe)) {
+ distMax = distProbe;
+ } else {
+ distMin = distProbe;
+ }
+
+ distProbe = (distMin + distMax) / 2.0;
+ }
+
+ distMin = std::max(distMin, infinityCost);
+ distMax = std::max(distMax, infinityCost);
+ }
+
+ // template<class Real>
+ // inline Real getOneDimensionalCost(std::vector<Real>& set_A, std::vector<Real>& set_B)
+ // {
+ // if (set_A.size() != set_B.size()) {
+ // return std::numeric_limits<Real>::infinity();
+ // }
+ //
+ // if (set_A.empty()) {
+ // return Real(0.0);
+ // }
+ //
+ // std::sort(set_A.begin(), set_A.end());
+ // std::sort(set_B.begin(), set_B.end());
+ //
+ // Real result = 0.0;
+ // for (size_t i = 0; i < set_A.size(); ++i) {
+ // result = std::max(result, (std::fabs(set_A[i] - set_B[i])));
+ // }
+ //
+ // return result;
+ // }
+
+
+ template<class Real>
+ struct CostEdgePair
+ {
+ Real cost;
+ typename hera::bt::MatchingEdge<Real> edge;
+ };
+
+ template<class Real>
+ using CoordPointPair = std::pair<Real, typename hera::bt::DiagramPoint<Real>>;
+
+ template<class Real>
+ using CoordPointVector = std::vector<typename hera::bt::CoordPointPair<Real>>;
+
+ template<class Real>
+ struct CoordPointPairComparator
+ {
+ bool operator()(const CoordPointPair<Real>& a, const CoordPointPair<Real>& b) const
+ {
+ return a.first < b.first or (a.first == b.first and a.second.id < b.second.id);
+ };
+ };
+
+ template<class Real>
+ inline typename hera::bt::CostEdgePair<Real>
+ getOneDimensionalCost(typename hera::bt::CoordPointVector<Real>& set_A,
+ typename hera::bt::CoordPointVector<Real>& set_B)
+ {
+ using MatchingEdgeR = hera::bt::MatchingEdge<Real>;
+ using CostEdgePairR = CostEdgePair<Real>;
+
+ if (set_A.size() != set_B.size()) {
+ return CostEdgePairR { std::numeric_limits<Real>::infinity(), MatchingEdgeR() };
+ }
+
+ if (set_A.empty()) {
+ return CostEdgePairR { Real(0.0), MatchingEdgeR() };
+ }
+
+ std::sort(set_A.begin(), set_A.end(), CoordPointPairComparator<Real>());
+ std::sort(set_B.begin(), set_B.end(), CoordPointPairComparator<Real>());
+
+ CostEdgePairR result { -1.0, MatchingEdgeR() };
+
+ for (size_t i = 0; i < set_A.size(); ++i) {
+ Real curr_cost = std::fabs(set_A[i].first - set_B[i].first);
+ if (curr_cost > result.cost) {
+ result.cost = curr_cost;
+ result.edge = MatchingEdgeR(set_A[i].second, set_B[i].second);
+ }
+ }
+ return result;
+ }
+
+
+ template<class Real>
+ inline CostEdgePair<Real> getInfinityCost(const DiagramPointSet <Real>& A, const DiagramPointSet <Real>& B,
+ bool compute_longest_edge = false)
+ {
+ using CostEdgePairR = CostEdgePair<Real>;
+ using CoordPointVectorR = CoordPointVector<Real>;
+
+ CoordPointVectorR x_plus_A, x_minus_A, y_plus_A, y_minus_A;
+ CoordPointVectorR x_plus_B, x_minus_B, y_plus_B, y_minus_B;
+
+ for (auto iter_A = A.cbegin(); iter_A != A.cend(); ++iter_A) {
+ Real x = iter_A->getRealX();
+ Real y = iter_A->getRealY();
+ if (x == std::numeric_limits<Real>::infinity()) {
+ y_plus_A.emplace_back(y, *iter_A);
+ } else if (x == -std::numeric_limits<Real>::infinity()) {
+ y_minus_A.emplace_back(y, *iter_A);
+ } else if (y == std::numeric_limits<Real>::infinity()) {
+ x_plus_A.emplace_back(x, *iter_A);
+ } else if (y == -std::numeric_limits<Real>::infinity()) {
+ x_minus_A.emplace_back(x, *iter_A);
+ }
+ }
+
+ for (auto iter_B = B.cbegin(); iter_B != B.cend(); ++iter_B) {
+ Real x = iter_B->getRealX();
+ Real y = iter_B->getRealY();
+ if (x == std::numeric_limits<Real>::infinity()) {
+ y_plus_B.emplace_back(y, *iter_B);
+ } else if (x == -std::numeric_limits<Real>::infinity()) {
+ y_minus_B.emplace_back(y, *iter_B);
+ } else if (y == std::numeric_limits<Real>::infinity()) {
+ x_plus_B.emplace_back(x, *iter_B);
+ } else if (y == -std::numeric_limits<Real>::infinity()) {
+ x_minus_B.emplace_back(x, *iter_B);
+ }
+ }
+
+ CostEdgePairR result = getOneDimensionalCost(x_plus_A, x_plus_B);
+
+ CostEdgePairR next_cost_edge = getOneDimensionalCost(x_minus_A, x_minus_B);
+ if (next_cost_edge.cost > result.cost) {
+ result = next_cost_edge;
+ }
+
+ next_cost_edge = getOneDimensionalCost(y_plus_A, y_plus_B);
+ if (next_cost_edge.cost > result.cost) {
+ result = next_cost_edge;
+ }
+
+ next_cost_edge = getOneDimensionalCost(y_minus_A, y_minus_B);
+ if (next_cost_edge.cost > result.cost) {
+ result = next_cost_edge;
+ }
+
+ return result;
+ }
+
+ // return the interval (distMin, distMax) such that:
+ // a) actual bottleneck distance between A and B is contained in the interval
+ // b) if the interval is not (0,0), then (distMax - distMin) / distMin < epsilon
+ template<class Real>
+ inline std::pair<Real, Real>
+ bottleneckDistApproxInterval(DiagramPointSet<Real>& A, DiagramPointSet<Real>& B, const Real epsilon,
+ MatchingEdge<Real>& edge, bool compute_longest_edge)
+ {
+ using MatchingEdgeR = MatchingEdge<Real>;
+ using CostEdgePairR = CostEdgePair<Real>;
+
+ edge = MatchingEdgeR();
+ // empty diagrams are not considered as error
+ if (A.empty() and B.empty()) {
+ return std::make_pair(0.0, 0.0);
+ }
+
+ CostEdgePairR inf_cost_edge = getInfinityCost(A, B, true);
+
+ Real infinity_cost = inf_cost_edge.cost;
+ if (infinity_cost == std::numeric_limits<Real>::infinity()) {
+ return std::make_pair(infinity_cost, infinity_cost);
+ } else {
+ edge = inf_cost_edge.edge;
+ }
+
+ // link diagrams A and B by adding projections
+ addProjections(A, B);
+
+ // TODO: think about that!
+ // we need one threshold for checking if the distance is 0,
+ // another one for the oracle!
+ constexpr Real epsThreshold { 1.0e-10 };
+ std::pair<Real, Real> result { 0.0, 0.0 };
+ bool useRangeSearch { true };
+ // construct an oracle
+ BoundMatchOracle<Real> oracle(A, B, epsThreshold, useRangeSearch);
+ // check for distance = 0
+ if (oracle.isMatchLess(2 * epsThreshold)) {
+ if (infinity_cost > epsThreshold) {
+ result.first = infinity_cost;
+ result.second = infinity_cost;
+ edge = inf_cost_edge.edge;
+ }
+ return result;
+ }
+ // get a 3-approximation of maximal distance between A and B
+ // as a starting value for probe distance
+ Real distProbe { getFurthestDistance3Approx<Real, DiagramPointSet<Real>>(A, B) };
+ binarySearch(epsilon, result, oracle, infinity_cost, false, distProbe);
+ // to compute longest edge a perfect matching is needed
+ if (compute_longest_edge and result.first > infinity_cost) {
+ oracle.isMatchLess(result.second);
+ edge = oracle.get_longest_edge();
+ }
+ return result;
+ }
+
+ template<class Real>
+ void sampleDiagramForHeur(const DiagramPointSet <Real>& dgmIn, DiagramPointSet <Real>& dgmOut)
+ {
+ struct pair_hash
+ {
+ std::size_t operator()(const std::pair<Real, Real> p) const
+ {
+ return std::hash<Real>()(p.first) ^ std::hash<Real>()(p.second);
+ }
+ };
+ std::unordered_map<std::pair<Real, Real>, int, pair_hash> m;
+ for (auto ptIter = dgmIn.cbegin(); ptIter != dgmIn.cend(); ++ptIter) {
+ if (ptIter->isNormal() and not ptIter->isInfinity()) {
+ m[std::make_pair(ptIter->getRealX(), ptIter->getRealY())]++;
+ }
+ }
+ if (m.size() < 2) {
+ dgmOut = dgmIn;
+ return;
+ }
+ std::vector<int> v;
+ for (const auto& ptQtyPair : m) {
+ v.push_back(ptQtyPair.second);
+ }
+ std::sort(v.begin(), v.end());
+ int maxLeap = v[1] - v[0];
+ int cutVal = v[0];
+ for (int i = 1; i < static_cast<int>(v.size()) - 1; ++i) {
+ int currLeap = v[i + 1] - v[i];
+ if (currLeap > maxLeap) {
+ maxLeap = currLeap;
+ cutVal = v[i];
+ }
+ }
+ std::vector<std::pair<Real, Real>> vv;
+ // keep points whose multiplicites are at most cutVal
+ // quick-and-dirty: fill in vv with copies of each point
+ // to construct DiagramPointSet from it later
+ for (const auto& ptQty : m) {
+ if (ptQty.second < cutVal) {
+ for (int i = 0; i < ptQty.second; ++i) {
+ vv.push_back(std::make_pair(ptQty.first.first, ptQty.first.second));
+ }
+ }
+ }
+ dgmOut.clear();
+ dgmOut = DiagramPointSet<Real>(vv.begin(), vv.end());
+ }
+
+
+ // return the interval (distMin, distMax) such that:
+ // a) actual bottleneck distance between A and B is contained in the interval
+ // b) if the interval is not (0,0), then (distMax - distMin) / distMin < epsilon
+ template<class Real>
+ std::pair<Real, Real>
+ bottleneckDistApproxIntervalWithInitial(DiagramPointSet <Real>& A, DiagramPointSet <Real>& B,
+ const Real epsilon,
+ const std::pair<Real, Real> initialGuess,
+ const Real infinity_cost,
+ MatchingEdge <Real>& longest_edge,
+ bool compute_longest_edge = false)
+ {
+ // empty diagrams are not considered as error
+ if (A.empty() and B.empty()) {
+ return std::make_pair(0.0, 0.0);
+ }
+
+ // link diagrams A and B by adding projections
+ addProjections(A, B);
+
+ constexpr Real epsThreshold { 1.0e-10 };
+ std::pair<Real, Real> result { 0.0, 0.0 };
+ bool useRangeSearch { true };
+ // construct an oracle
+ BoundMatchOracle<Real> oracle(A, B, epsThreshold, useRangeSearch);
+
+ Real& distMin { result.first };
+ Real& distMax { result.second };
+
+ // initialize search interval from initialGuess
+ distMin = initialGuess.first;
+ distMax = initialGuess.second;
+
+ assert(distMin <= distMax);
+
+ // make sure that distMin is a lower bound
+ while (oracle.isMatchLess(distMin)) {
+ // distMin is in fact an upper bound, so assign it to distMax
+ distMax = distMin;
+ // and decrease distMin by 5 %
+ distMin = 0.95 * distMin;
+ }
+
+ // make sure that distMax is an upper bound
+ while (not oracle.isMatchLess(distMax)) {
+ // distMax is in fact a lower bound, so assign it to distMin
+ distMin = distMax;
+ // and increase distMax by 5 %
+ distMax = 1.05 * distMax;
+ }
+
+ // bounds are found, perform binary search
+ Real distProbe = (distMin + distMax) / 2.0;
+ binarySearch(epsilon, result, oracle, infinity_cost, true, distProbe);
+ if (compute_longest_edge) {
+ longest_edge = oracle.get_longest_edge();
+ }
+ return result;
+ }
+
+ // return the interval (distMin, distMax) such that:
+ // a) actual bottleneck distance between A and B is contained in the interval
+ // b) if the interval is not (0,0), then (distMax - distMin) / distMin < epsilon
+ // use heuristic: initial estimate on sampled diagrams
+ template<class Real>
+ std::pair<Real, Real>
+ bottleneckDistApproxIntervalHeur(DiagramPointSet <Real>& A, DiagramPointSet <Real>& B, const Real epsilon,
+ MatchingEdge <Real>& longest_edge)
+ {
+ // empty diagrams are not considered as error
+ if (A.empty() and B.empty()) {
+ return std::make_pair(0.0, 0.0);
+ }
+
+ Real infinity_cost = getInfinityCost(A, B);
+ if (infinity_cost == std::numeric_limits<Real>::infinity()) {
+ return std::make_pair(infinity_cost, infinity_cost);
+ }
+
+ DiagramPointSet<Real> sampledA, sampledB;
+ sampleDiagramForHeur(A, sampledA);
+ sampleDiagramForHeur(B, sampledB);
+
+ std::pair<Real, Real> initGuess = bottleneckDistApproxInterval(sampledA, sampledB, epsilon);
+
+ initGuess.first = std::max(initGuess.first, infinity_cost);
+ initGuess.second = std::max(initGuess.second, infinity_cost);
+
+ return bottleneckDistApproxIntervalWithInitial<Real>(A, B, epsilon, initGuess, infinity_cost, longest_edge);
+ }
+
+
+ // get approximate distance,
+ // see bottleneckDistApproxInterval
+ template<class Real>
+ Real bottleneckDistApprox(DiagramPointSet <Real>& A, DiagramPointSet <Real>& B, const Real epsilon,
+ MatchingEdge <Real>& longest_edge, bool compute_longest_edge)
+ {
+ auto interval = bottleneckDistApproxInterval<Real>(A, B, epsilon, longest_edge, compute_longest_edge);
+ return interval.second;
+ }
+
+
+ template<class Real>
+ Real bottleneckDistExactFromSortedPwDist(DiagramPointSet <Real>& A, DiagramPointSet <Real>& B,
+ const std::vector<Real>& pairwiseDist,
+ const int decPrecision, MatchingEdge <Real>& longest_edge,
+ bool compute_longest_edge = false)
+ {
+ // trivial case: we have only one candidate
+ if (pairwiseDist.size() == 1) {
+ return pairwiseDist[0];
+ }
+
+ bool useRangeSearch = true;
+ Real distEpsilon = std::numeric_limits<Real>::max();
+ Real diffThreshold = 0.1;
+ for (int k = 0; k < decPrecision; ++k) {
+ diffThreshold /= 10;
+ }
+ for (size_t k = 0; k < pairwiseDist.size() - 2; ++k) {
+ auto diff = pairwiseDist[k + 1] - pairwiseDist[k];
+ if (diff > diffThreshold and diff < distEpsilon) {
+ distEpsilon = diff;
+ }
+ }
+ distEpsilon = std::min(diffThreshold, distEpsilon / 3);
+
+ BoundMatchOracle<Real> oracle(A, B, distEpsilon, useRangeSearch);
+ // binary search
+ size_t iterNum { 0 };
+ size_t idxMin { 0 }, idxMax { pairwiseDist.size() - 1 };
+ size_t idxMid;
+ while (idxMax > idxMin) {
+ idxMid = static_cast<size_t>(floor(idxMin + idxMax) / 2);
+ iterNum++;
+ // not A[imid] < dist <=> A[imid] >= dist <=> A[imid[ >= dist + eps
+ if (oracle.isMatchLess(pairwiseDist[idxMid] + distEpsilon / 2)) {
+ idxMax = idxMid;
+ } else {
+ idxMin = idxMid + 1;
+ }
+ }
+ idxMid = static_cast<size_t>(floor(idxMin + idxMax) / 2);
+ Real result = pairwiseDist[idxMid];
+ if (compute_longest_edge) {
+ oracle.isMatchLess(result + distEpsilon / 2);
+ longest_edge = oracle.get_longest_edge();
+ }
+ return result;
+ }
+
+
+ template<class Real>
+ Real
+ bottleneckDistExact(DiagramPointSet <Real>& A, DiagramPointSet <Real>& B, MatchingEdge <Real>& longest_edge,
+ bool compute_longest_edge)
+ {
+ return bottleneckDistExact(A, B, 14, longest_edge, compute_longest_edge);
+ }
+
+ template<class Real>
+ Real bottleneckDistExact(DiagramPointSet <Real>& A, DiagramPointSet <Real>& B, const int decPrecision,
+ MatchingEdge <Real>& longest_edge, bool compute_longest_edge)
+ {
+ using DgmPoint = DiagramPoint<Real>;
+
+ constexpr Real epsilon = 0.001;
+ auto interval = bottleneckDistApproxInterval(A, B, epsilon, longest_edge, true);
+ // if the longest edge is on infinity, the answer is already exact
+ // this will be detected here and all the code after if
+ // may assume that the longest edge is on finite points
+ if (interval.first == interval.second) {
+ return interval.first;
+ }
+ const Real delta = 0.50001 * (interval.second - interval.first);
+ const Real approxDist = 0.5 * (interval.first + interval.second);
+ const Real minDist = interval.first;
+ const Real maxDist = interval.second;
+ if (delta == 0) {
+ return interval.first;
+ }
+ // copy points from A to a vector
+ // todo: get rid of this?
+ std::vector<DgmPoint> pointsA;
+ pointsA.reserve(A.size());
+ for (const auto& ptA : A) {
+ pointsA.push_back(ptA);
+ }
+
+ // in this vector we store the distances between the points
+ // that are candidates to realize
+ std::set<Real> pairwiseDist;
+ {
+ // vector to store centers of vertical stripes
+ // two for each point in A and the id of the corresponding point
+ std::vector<std::pair<Real, DgmPoint>> xCentersVec;
+ xCentersVec.reserve(2 * pointsA.size());
+ for (auto ptA : pointsA) {
+ xCentersVec.push_back(std::make_pair(ptA.getRealX() - approxDist, ptA));
+ xCentersVec.push_back(std::make_pair(ptA.getRealX() + approxDist, ptA));
+ }
+ // lambda to compare pairs <coordinate, id> w.r.t coordinate
+ auto compLambda = [](std::pair<Real, DgmPoint> a, std::pair<Real, DgmPoint> b) {
+ return a.first < b.first;
+ };
+
+ std::sort(xCentersVec.begin(), xCentersVec.end(), compLambda);
+ // todo: sort points in B, reduce search range in lower and upper bounds
+ for (auto ptB : B) {
+ // iterator to the first stripe such that ptB lies to the left
+ // from its right boundary (x_B <= x_j + \delta iff x_j >= x_B - \delta
+ auto itStart = std::lower_bound(xCentersVec.begin(),
+ xCentersVec.end(),
+ std::make_pair(ptB.getRealX() - delta, ptB),
+ compLambda);
+
+ for (auto iterA = itStart; iterA < xCentersVec.end(); ++iterA) {
+ if (ptB.getRealX() < iterA->first - delta) {
+ // from that moment x_B >= x_j - delta
+ // is violated: x_B no longer lies to right from the left
+ // boundary of current stripe
+ break;
+ }
+ // we're here => ptB lies in vertical stripe,
+ // check if distance fits into the interval we've found
+ Real pwDist = distLInf(iterA->second, ptB);
+ if (pwDist >= minDist and pwDist <= maxDist) {
+ pairwiseDist.insert(pwDist);
+ }
+ }
+ }
+ }
+
+ {
+ // for y
+ // vector to store centers of vertical stripes
+ // two for each point in A and the id of the corresponding point
+ std::vector<std::pair<Real, DgmPoint>> yCentersVec;
+ yCentersVec.reserve(2 * pointsA.size());
+ for (auto ptA : pointsA) {
+ yCentersVec.push_back(std::make_pair(ptA.getRealY() - approxDist, ptA));
+ yCentersVec.push_back(std::make_pair(ptA.getRealY() + approxDist, ptA));
+ }
+ // lambda to compare pairs <coordinate, id> w.r.t coordinate
+ auto compLambda = [](std::pair<Real, DgmPoint> a, std::pair<Real, DgmPoint> b) {
+ return a.first < b.first;
+ };
+
+ std::sort(yCentersVec.begin(), yCentersVec.end(), compLambda);
+
+ // todo: sort points in B, reduce search range in lower and upper bounds
+ for (auto ptB : B) {
+ auto itStart = std::lower_bound(yCentersVec.begin(),
+ yCentersVec.end(),
+ std::make_pair(ptB.getRealY() - delta, ptB),
+ compLambda);
+
+
+ for (auto iterA = itStart; iterA < yCentersVec.end(); ++iterA) {
+ if (ptB.getRealY() < iterA->first - delta) {
+ break;
+ }
+ Real pwDist = distLInf(iterA->second, ptB);
+ if (pwDist >= minDist and pwDist <= maxDist) {
+ pairwiseDist.insert(pwDist);
+ }
+ }
+ }
+ }
+
+ std::vector<Real> pw_dists;
+ pw_dists.reserve(pairwiseDist.size());
+ for(Real d : pairwiseDist) {
+ pw_dists.push_back(d);
+ }
+
+ return bottleneckDistExactFromSortedPwDist(A, B, pw_dists, decPrecision, longest_edge,
+ compute_longest_edge);
+ }
+
+ } // end namespace bt
+} // end namespace hera
+#endif // HERA_BOTTLENECK_HPP
diff --git a/bottleneck/include/bound_match.h b/bottleneck/include/bound_match.h
new file mode 100644
index 0000000..99543f9
--- /dev/null
+++ b/bottleneck/include/bound_match.h
@@ -0,0 +1,109 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_BOUND_MATCH_H
+#define HERA_BOUND_MATCH_H
+
+#include <unordered_map>
+#include <memory>
+
+#include "basic_defs_bt.h"
+#include "neighb_oracle.h"
+
+
+namespace hera {
+namespace bt {
+
+template<class Real = double>
+class Matching {
+public:
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointSet = DiagramPointSet<Real>;
+ using DgmPointHash = DiagramPointHash<Real>;
+ using Path = std::vector<DgmPoint>;
+
+ Matching(const DgmPointSet& AA, const DgmPointSet& BB) : A(AA), B(BB) {};
+ DgmPointSet getExposedVertices(bool forA = true) const ;
+ bool isExposed(const DgmPoint& p) const;
+ void getAllAdjacentVertices(const DgmPointSet& setIn, DgmPointSet& setOut, bool forA = true) const;
+ void increase(const Path& augmentingPath);
+ void checkAugPath(const Path& augPath) const;
+ bool getMatchedVertex(const DgmPoint& p, DgmPoint& result) const;
+ bool isPerfect() const;
+ void trimMatching(const Real newThreshold);
+ MatchingEdge<Real> get_longest_edge() const;
+#ifndef FOR_R_TDA
+ template<class R>
+ friend std::ostream& operator<<(std::ostream& output, const Matching<R>& m);
+#endif
+private:
+ DgmPointSet A;
+ DgmPointSet B;
+ std::unordered_map<DgmPoint, DgmPoint, DgmPointHash> AToB, BToA;
+ void matchVertices(const DgmPoint& pA, const DgmPoint& pB);
+ void sanityCheck() const;
+};
+
+
+
+template<class Real_ = double, class NeighbOracle_ = NeighbOracleDnn<Real_>>
+class BoundMatchOracle {
+public:
+ using Real = Real_;
+ using NeighbOracle = NeighbOracle_;
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointSet = DiagramPointSet<Real>;
+ using Path = std::vector<DgmPoint>;
+
+ BoundMatchOracle(DgmPointSet psA, DgmPointSet psB, Real dEps, bool useRS = true);
+ bool isMatchLess(Real r);
+ bool buildMatchingForThreshold(const Real r);
+ MatchingEdge<Real> get_longest_edge() const { return M.get_longest_edge(); }
+private:
+ DgmPointSet A, B;
+ Matching<Real> M;
+ void printLayerGraph();
+ void buildLayerGraph(Real r);
+ void buildLayerOracles(Real r);
+ bool buildAugmentingPath(const DgmPoint startVertex, Path& result);
+ void removeFromLayer(const DgmPoint& p, const int layerIdx);
+ std::unique_ptr<NeighbOracle> neighbOracle;
+ bool augPathExist;
+ std::vector<DgmPointSet> layerGraph;
+ std::vector<std::unique_ptr<NeighbOracle>> layerOracles;
+ Real distEpsilon;
+ bool useRangeSearch;
+ Real prevQueryValue;
+};
+
+} // end namespace bt
+} // end namespace hera
+
+#include "bound_match.hpp"
+
+#endif // HERA_BOUND_MATCH_H
diff --git a/bottleneck/include/bound_match.hpp b/bottleneck/include/bound_match.hpp
new file mode 100644
index 0000000..b95628f
--- /dev/null
+++ b/bottleneck/include/bound_match.hpp
@@ -0,0 +1,511 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_BOUND_MATCH_HPP
+#define HERA_BOUND_MATCH_HPP
+
+
+#ifdef FOR_R_TDA
+#undef DEBUG_BOUND_MATCH
+#undef DEBUG_MATCHING
+#undef VERBOSE_BOTTLENECK
+#endif
+
+#include <assert.h>
+#include "def_debug_bt.h"
+#include "bound_match.h"
+
+#ifdef VERBOSE_BOTTLENECK
+#include <chrono>
+#endif
+
+#ifndef FOR_R_TDA
+
+#include <iostream>
+
+#endif
+
+namespace hera {
+ namespace bt {
+
+#ifndef FOR_R_TDA
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& output, const Matching <Real>& m)
+ {
+ output << "Matching: " << m.AToB.size() << " pairs (";
+ if (!m.isPerfect()) {
+ output << "not";
+ }
+ output << " perfect)" << std::endl;
+ for (auto atob : m.AToB) {
+ output << atob.first << " <-> " << atob.second << " distance: " << distLInf(atob.first, atob.second)
+ << std::endl;
+ }
+ return output;
+ }
+
+#endif
+
+ template<class R>
+ void Matching<R>::sanityCheck() const
+ {
+#ifdef DEBUG_MATCHING
+ assert( AToB.size() == BToA.size() );
+ for(auto aToBPair : AToB) {
+ auto bToAPair = BToA.find(aToBPair.second);
+ assert(bToAPair != BToA.end());
+ assert( aToBPair.first == bToAPair->second);
+ }
+#endif
+ }
+
+ template<class R>
+ bool Matching<R>::isPerfect() const
+ {
+ return AToB.size() == A.size();
+ }
+
+ template<class R>
+ void Matching<R>::matchVertices(const DgmPoint& pA, const DgmPoint& pB)
+ {
+ assert(A.hasElement(pA));
+ assert(B.hasElement(pB));
+ AToB.erase(pA);
+ AToB.insert({{ pA, pB }});
+ BToA.erase(pB);
+ BToA.insert({{ pB, pA }});
+ }
+
+ template<class R>
+ bool Matching<R>::getMatchedVertex(const DgmPoint& p, DgmPoint& result) const
+ {
+ sanityCheck();
+ auto inA = AToB.find(p);
+ if (inA != AToB.end()) {
+ result = inA->second;
+ return true;
+ } else {
+ auto inB = BToA.find(p);
+ if (inB != BToA.end()) {
+ result = inB->second;
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ template<class R>
+ void Matching<R>::checkAugPath(const Path& augPath) const
+ {
+ assert(augPath.size() % 2 == 0);
+ for (size_t idx = 0; idx < augPath.size(); ++idx) {
+ bool mustBeExposed { idx == 0 or idx == augPath.size() - 1 };
+ if (isExposed(augPath[idx]) != mustBeExposed) {
+#ifndef FOR_R_TDA
+ std::cerr << "mustBeExposed = " << mustBeExposed << ", idx = " << idx << ", point " << augPath[idx]
+ << std::endl;
+#endif
+ }
+ assert(isExposed(augPath[idx]) == mustBeExposed);
+ DgmPoint matchedVertex;
+ if (idx % 2 == 0) {
+ assert(A.hasElement(augPath[idx]));
+ if (not mustBeExposed) {
+ getMatchedVertex(augPath[idx], matchedVertex);
+ assert(matchedVertex == augPath[idx - 1]);
+ }
+ } else {
+ assert(B.hasElement(augPath[idx]));
+ if (not mustBeExposed) {
+ getMatchedVertex(augPath[idx], matchedVertex);
+ assert(matchedVertex == augPath[idx + 1]);
+ }
+ }
+ }
+ }
+
+ // use augmenting path to increase
+ // the size of the matching
+ template<class R>
+ void Matching<R>::increase(const Path& augPath)
+ {
+ sanityCheck();
+ // check that augPath is an augmenting path
+ checkAugPath(augPath);
+ for (size_t idx = 0; idx < augPath.size() - 1; idx += 2) {
+ matchVertices(augPath[idx], augPath[idx + 1]);
+ }
+ sanityCheck();
+ }
+
+ template<class R>
+ DiagramPointSet <R> Matching<R>::getExposedVertices(bool forA) const
+ {
+ sanityCheck();
+ DgmPointSet result;
+ const DgmPointSet* setToSearch { forA ? &A : &B };
+ const std::unordered_map<DgmPoint, DgmPoint, DgmPointHash>* mapToSearch { forA ? &AToB : &BToA };
+ for (auto it = setToSearch->cbegin(); it != setToSearch->cend(); ++it) {
+ if (mapToSearch->find((*it)) == mapToSearch->cend()) {
+ result.insert((*it));
+ }
+ }
+ return result;
+ }
+
+ template<class R>
+ void Matching<R>::getAllAdjacentVertices(const DgmPointSet& setIn,
+ DgmPointSet& setOut,
+ bool forA) const
+ {
+ sanityCheck();
+ //bool isDebug {false};
+ setOut.clear();
+ const std::unordered_map<DgmPoint, DgmPoint, DgmPointHash>* m;
+ m = (forA) ? &BToA : &AToB;
+ for (auto pit = setIn.cbegin(); pit != setIn.cend(); ++pit) {
+ auto findRes = m->find(*pit);
+ if (findRes != m->cend()) {
+ setOut.insert((*findRes).second);
+ }
+ }
+ sanityCheck();
+ }
+
+ template<class R>
+ bool Matching<R>::isExposed(const DgmPoint& p) const
+ {
+ return (AToB.find(p) == AToB.end()) && (BToA.find(p) == BToA.end());
+ }
+
+ // remove all edges whose length is > newThreshold
+ template<class R>
+ void Matching<R>::trimMatching(const R newThreshold)
+ {
+ //bool isDebug { false };
+ sanityCheck();
+ for (auto aToBIter = AToB.begin(); aToBIter != AToB.end();) {
+ if (distLInf(aToBIter->first, aToBIter->second) > newThreshold) {
+ // remove edge from AToB and BToA
+ BToA.erase(aToBIter->second);
+ aToBIter = AToB.erase(aToBIter);
+ } else {
+ aToBIter++;
+ }
+ }
+ sanityCheck();
+ }
+
+ template<class R>
+ MatchingEdge <R> Matching<R>::get_longest_edge() const
+ {
+ R max_dist = -1.0;
+ MatchingEdge<R> edge;
+ for (const auto& x : AToB) {
+ //std::cout << "max_dist = " << max_dist << std::endl;
+ //std::cout << "distance = " << distLInf(x.first, x.second) << std::endl;
+
+ // for now skew edges may appear in the matching
+ // but they should not be returned to user
+ // if currrent edge is a skew edge, there must another edge
+ // with the same cost
+ R curr_dist;
+ if (x.first.isDiagonal() and x.second.isNormal()) {
+ curr_dist = x.second.get_persistence(hera::get_infinity());
+ } else if (x.first.isNormal() and x.second.isDiagonal()) {
+ curr_dist = x.first.get_persistence(hera::get_infinity());
+ } else {
+ curr_dist = distLInf(x.first, x.second);
+ }
+ if (max_dist < curr_dist) {
+ max_dist = curr_dist;
+ edge = x;
+ //std::cout << "updated max_dist = " << max_dist << std::endl;
+ //std::cout << "updated edge = " << x.first << " <-> " << x.second << std::endl;
+ }
+ }
+ return edge;
+ }
+
+ // ------- BoundMatchOracle --------------
+
+ template<class R, class NO>
+ BoundMatchOracle<R, NO>::BoundMatchOracle(DgmPointSet psA, DgmPointSet psB,
+ Real dEps, bool useRS) :
+ A(psA), B(psB), M(A, B), distEpsilon(dEps), useRangeSearch(useRS), prevQueryValue(0.0)
+ {
+ neighbOracle = std::unique_ptr<NeighbOracle>(new NeighbOracle(psB, 0, distEpsilon));
+ }
+
+ template<class R, class NO>
+ bool BoundMatchOracle<R, NO>::isMatchLess(Real r)
+ {
+#ifdef VERBOSE_BOTTLENECK
+ std::chrono::high_resolution_clock hrClock;
+ std::chrono::time_point<std::chrono::high_resolution_clock> startMoment;
+ startMoment = hrClock.now();
+#endif
+ bool result = buildMatchingForThreshold(r);
+#ifdef VERBOSE_BOTTLENECK
+ auto endMoment = hrClock.now();
+ std::chrono::duration<double, std::milli> iterTime = endMoment - startMoment;
+ std::cout << "isMatchLess for r = " << r << " finished in " << std::chrono::duration<double, std::milli>(iterTime).count() << " ms." << std::endl;
+#endif
+ return result;
+
+ }
+
+
+ template<class R, class NO>
+ void BoundMatchOracle<R, NO>::removeFromLayer(const DgmPoint& p, const int layerIdx)
+ {
+ //bool isDebug {false};
+ layerGraph[layerIdx].erase(p);
+ if (layerOracles[layerIdx]) {
+ layerOracles[layerIdx]->deletePoint(p);
+ }
+ }
+
+ // return true, if there exists an augmenting path from startVertex
+ // in this case the path is returned in result.
+ // startVertex must be an exposed vertex from L_1 (layer[0])
+ template<class R, class NO>
+ bool BoundMatchOracle<R, NO>::buildAugmentingPath(const DgmPoint startVertex, Path& result)
+ {
+ //bool isDebug {false};
+ DgmPoint prevVertexA = startVertex;
+ result.clear();
+ result.push_back(startVertex);
+ size_t evenLayerIdx { 1 };
+ while (evenLayerIdx < layerGraph.size()) {
+ //for(size_t evenLayerIdx = 1; evenLayerIdx < layerGraph.size(); evenLayerIdx += 2) {
+ DgmPoint nextVertexB; // next vertex from even layer
+ bool neighbFound = layerOracles[evenLayerIdx]->getNeighbour(prevVertexA, nextVertexB);
+ if (neighbFound) {
+ result.push_back(nextVertexB);
+ if (layerGraph.size() == evenLayerIdx + 1) {
+ break;
+ } else {
+ // nextVertexB must be matched with some vertex from the next odd
+ // layer
+ DgmPoint nextVertexA;
+ if (!M.getMatchedVertex(nextVertexB, nextVertexA)) {
+#ifndef FOR_R_TDA
+ std::cerr << "Vertices in even layers must be matched! Unmatched: ";
+ std::cerr << nextVertexB << std::endl;
+ std::cerr << evenLayerIdx << "; " << layerGraph.size() << std::endl;
+#endif
+ throw std::runtime_error("Unmatched vertex in even layer");
+ } else {
+ assert(!(nextVertexA.getRealX() == 0 and nextVertexA.getRealY() == 0));
+ result.push_back(nextVertexA);
+ prevVertexA = nextVertexA;
+ evenLayerIdx += 2;
+ continue;
+ }
+ }
+ } else {
+ // prevVertexA has no neighbours in the next layer,
+ // backtrack
+ if (evenLayerIdx == 1) {
+ // startVertex is not connected to any vertices
+ // in the next layer, augm. path doesn't exist
+ removeFromLayer(startVertex, 0);
+ return false;
+ } else {
+ assert(evenLayerIdx >= 3);
+ assert(result.size() % 2 == 1);
+ result.pop_back();
+ DgmPoint prevVertexB = result.back();
+ result.pop_back();
+ removeFromLayer(prevVertexA, evenLayerIdx - 1);
+ removeFromLayer(prevVertexB, evenLayerIdx - 2);
+ // we should proceed from the previous odd layer
+ assert(result.size() >= 1);
+ prevVertexA = result.back();
+ evenLayerIdx -= 2;
+ continue;
+ }
+ }
+ } // finished iterating over all layers
+ // remove all vertices in the augmenting paths
+ // the corresponding layers
+ for (size_t layerIdx = 0; layerIdx < result.size(); ++layerIdx) {
+ removeFromLayer(result[layerIdx], layerIdx);
+ }
+ return true;
+ }
+
+
+ template<class R, class NO>
+ bool BoundMatchOracle<R, NO>::buildMatchingForThreshold(const Real r)
+ {
+ //bool isDebug {false};
+ if (prevQueryValue > r) {
+ M.trimMatching(r);
+ }
+ prevQueryValue = r;
+ while (true) {
+ buildLayerGraph(r);
+ if (augPathExist) {
+ std::vector<Path> augmentingPaths;
+ DgmPointSet copyLG0;
+ for (DgmPoint p : layerGraph[0]) {
+ copyLG0.insert(p);
+ }
+ for (DgmPoint exposedVertex : copyLG0) {
+ Path augPath;
+ if (buildAugmentingPath(exposedVertex, augPath)) {
+ augmentingPaths.push_back(augPath);
+ }
+ }
+ if (augmentingPaths.empty()) {
+#ifndef FOR_R_TDA
+ std::cerr << "augmenting paths must exist, but were not found!" << std::endl;
+#endif
+ throw std::runtime_error("bad epsilon?");
+ }
+ // swap all augmenting paths with matching to increase it
+ for (auto& augPath : augmentingPaths) {
+ M.increase(augPath);
+ }
+ } else {
+ return M.isPerfect();
+ }
+ }
+ }
+
+ template<class R, class NO>
+ void BoundMatchOracle<R, NO>::printLayerGraph(void)
+ {
+#ifdef DEBUG_BOUND_MATCH
+ for(auto& layer : layerGraph) {
+ std::cout << "{ ";
+ for(auto& p : layer) {
+ std::cout << p << "; ";
+ }
+ std::cout << "\b\b }" << std::endl;
+ }
+#endif
+ }
+
+ template<class R, class NO>
+ void BoundMatchOracle<R, NO>::buildLayerGraph(Real r)
+ {
+#ifdef VERBOSE_BOTTLENECK
+ std::cout << "Entered buildLayerGraph, r = " << r << std::endl;
+#endif
+ layerGraph.clear();
+ DgmPointSet L1 = M.getExposedVertices();
+ layerGraph.push_back(L1);
+ neighbOracle->rebuild(B, r);
+ size_t k = 0;
+ DgmPointSet layerNextEven;
+ DgmPointSet layerNextOdd;
+ bool exposedVerticesFound { false };
+ while (true) {
+ layerNextEven.clear();
+ for (auto p : layerGraph[k]) {
+ bool neighbFound;
+ //DgmPoint neighbour {0.0, 0.0, DgmPoint::DIAG, 1};
+ DgmPoint neighbour;
+ if (useRangeSearch) {
+ std::vector<DgmPoint> neighbVec;
+ neighbOracle->getAllNeighbours(p, neighbVec);
+ neighbFound = !neighbVec.empty();
+ for (auto& neighbPt : neighbVec) {
+ layerNextEven.insert(neighbPt);
+ if (!exposedVerticesFound and M.isExposed(neighbPt)) {
+ exposedVerticesFound = true;
+ }
+ }
+ } else {
+ while (true) {
+ neighbFound = neighbOracle->getNeighbour(p, neighbour);
+ if (neighbFound) {
+ layerNextEven.insert(neighbour);
+ neighbOracle->deletePoint(neighbour);
+ if ((!exposedVerticesFound) && M.isExposed(neighbour)) {
+ exposedVerticesFound = true;
+ }
+ } else {
+ break;
+ }
+ }
+ } // without range search
+ } // all vertices from previous odd layer processed
+ if (layerNextEven.empty()) {
+ augPathExist = false;
+ break;
+ }
+ if (exposedVerticesFound) {
+ for (auto it = layerNextEven.cbegin(); it != layerNextEven.cend();) {
+ if (!M.isExposed(*it)) {
+ layerNextEven.erase(it++);
+ } else {
+ ++it;
+ }
+
+ }
+ layerGraph.push_back(layerNextEven);
+ augPathExist = true;
+ break;
+ }
+ layerGraph.push_back(layerNextEven);
+ M.getAllAdjacentVertices(layerNextEven, layerNextOdd);
+ layerGraph.push_back(layerNextOdd);
+ k += 2;
+ }
+ buildLayerOracles(r);
+ printLayerGraph();
+ }
+
+ // create geometric oracles for each even layer
+ // odd layers have NULL in layerOracles
+ template<class R, class NO>
+ void BoundMatchOracle<R, NO>::buildLayerOracles(Real r)
+ {
+ //bool isDebug {false};
+ // free previously constructed oracles
+ layerOracles.clear();
+ for (size_t layerIdx = 0; layerIdx < layerGraph.size(); ++layerIdx) {
+ if (layerIdx % 2 == 1) {
+ // even layer, build actual oracle
+ layerOracles.emplace_back(new NeighbOracle(layerGraph[layerIdx], r, distEpsilon));
+ } else {
+ // odd layer
+ layerOracles.emplace_back(nullptr);
+ }
+ }
+ }
+
+ } // end namespace bt
+} // end namespace hera
+#endif // HERA_BOUND_MATCH_HPP
diff --git a/bottleneck/include/def_debug_bt.h b/bottleneck/include/def_debug_bt.h
new file mode 100644
index 0000000..21557e7
--- /dev/null
+++ b/bottleneck/include/def_debug_bt.h
@@ -0,0 +1,42 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef DEF_DEBUG_BT_H
+#define DEF_DEBUG_BT_H
+
+//#define DEBUG_BOUND_MATCH
+//#define DEBUG_NEIGHBOUR_ORACLE
+//#define DEBUG_MATCHING
+//#define DEBUG_AUCTION
+// This symbol should be defined only in the version
+// for R package TDA, to comply with some CRAN rules
+// like no usage of cout, cerr, cin, exit, etc.
+//#define FOR_R_TDA
+//#define VERBOSE_BOTTLENECK
+
+#endif
diff --git a/bottleneck/include/diagram_reader.h b/bottleneck/include/diagram_reader.h
new file mode 100644
index 0000000..08d9e2b
--- /dev/null
+++ b/bottleneck/include/diagram_reader.h
@@ -0,0 +1,196 @@
+/*
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_DIAGRAM_READER_H
+#define HERA_DIAGRAM_READER_H
+
+#ifndef FOR_R_TDA
+#include <iostream>
+#endif
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <cctype>
+
+namespace hera {
+
+// cannot choose stod, stof or stold based on RealType,
+// lazy solution: partial specialization
+ template<class RealType = double>
+ inline RealType parse_real_from_str(const std::string& s);
+
+ template <>
+ inline double parse_real_from_str<double>(const std::string& s)
+ {
+ return std::stod(s);
+ }
+
+
+ template <>
+ inline long double parse_real_from_str<long double>(const std::string& s)
+ {
+ return std::stold(s);
+ }
+
+
+ template <>
+ inline float parse_real_from_str<float>(const std::string& s)
+ {
+ return std::stof(s);
+ }
+
+
+ template<class RealType>
+ inline RealType parse_real_from_str(const std::string& s)
+ {
+ static_assert(sizeof(RealType) != sizeof(RealType), "Must be specialized for each type you want to use, see above");
+ }
+
+// fill in result with points from file fname
+// return false if file can't be opened
+// or error occurred while reading
+// decPrecision is the maximal decimal precision in the input,
+// it is zero if all coordinates in the input are integers
+
+ template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>>
+ inline bool readDiagramPointSet(const char* fname, ContType_& result, int& decPrecision)
+ {
+ using RealType = RealType_;
+
+ size_t lineNumber { 0 };
+ result.clear();
+ std::ifstream f(fname);
+ if (!f.good()) {
+#ifndef FOR_R_TDA
+ std::cerr << "Cannot open file " << fname << std::endl;
+#endif
+ return false;
+ }
+ std::locale loc;
+ std::string line;
+ while(std::getline(f, line)) {
+ lineNumber++;
+ // process comments: remove everything after hash
+ auto hashPos = line.find_first_of("#", 0);
+ if( std::string::npos != hashPos) {
+ line = std::string(line.begin(), line.begin() + hashPos);
+ }
+ if (line.empty()) {
+ continue;
+ }
+ // trim whitespaces
+ auto whiteSpaceFront = std::find_if_not(line.begin(),line.end(),isspace);
+ auto whiteSpaceBack = std::find_if_not(line.rbegin(),line.rend(),isspace).base();
+ if (whiteSpaceBack <= whiteSpaceFront) {
+ // line consists of spaces only - move to the next line
+ continue;
+ }
+ line = std::string(whiteSpaceFront,whiteSpaceBack);
+
+ // transform line to lower case
+ // to parse Infinity
+ for(auto& c : line) {
+ c = std::tolower(c, loc);
+ }
+
+ bool fracPart = false;
+ int currDecPrecision = 0;
+ for(auto c : line) {
+ if (c == '.') {
+ fracPart = true;
+ } else if (fracPart) {
+ if (isdigit(c)) {
+ currDecPrecision++;
+ } else {
+ fracPart = false;
+ if (currDecPrecision > decPrecision)
+ decPrecision = currDecPrecision;
+ currDecPrecision = 0;
+ }
+ }
+ }
+
+ RealType x, y;
+ std::string str_x, str_y;
+ std::istringstream iss(line);
+ try {
+ iss >> str_x >> str_y;
+
+ x = parse_real_from_str<RealType>(str_x);
+ y = parse_real_from_str<RealType>(str_y);
+
+ if (x != y) {
+ result.push_back(std::make_pair(x, y));
+ } else {
+#ifndef FOR_R_TDA
+ std::cerr << "Warning: point with 0 persistence ignored in " << fname << ":" << lineNumber << "\n";
+#endif
+ }
+ }
+ catch (const std::invalid_argument& e) {
+#ifndef FOR_R_TDA
+ std::cerr << "Error in file " << fname << ", line number " << lineNumber << ": cannot parse \"" << line << "\"" << std::endl;
+#endif
+ return false;
+ }
+ catch (const std::out_of_range&) {
+#ifndef FOR_R_TDA
+ std::cerr << "Error while reading file " << fname << ", line number " << lineNumber << ": value too large in \"" << line << "\"" << std::endl;
+#endif
+ return false;
+ }
+ }
+ f.close();
+ return true;
+ }
+
+ // wrappers
+ template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>>
+ inline bool readDiagramPointSet(const std::string& fname, ContType_& result, int& decPrecision)
+ {
+ return readDiagramPointSet<RealType_, ContType_>(fname.c_str(), result, decPrecision);
+ }
+
+ // these two functions are now just wrappers for the previous ones,
+ // in case someone needs them; decPrecision is ignored
+ template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>>
+ inline bool readDiagramPointSet(const char* fname, ContType_& result)
+ {
+ int decPrecision;
+ return readDiagramPointSet<RealType_, ContType_>(fname, result, decPrecision);
+ }
+
+ template<class RealType_ = double, class ContType_ = std::vector<std::pair<RealType_, RealType_>>>
+ inline bool readDiagramPointSet(const std::string& fname, ContType_& result)
+ {
+ int decPrecision;
+ return readDiagramPointSet<RealType_, ContType_>(fname.c_str(), result, decPrecision);
+ }
+
+} // end namespace hera
+#endif // HERA_DIAGRAM_READER_H
diff --git a/bottleneck/include/diagram_traits.h b/bottleneck/include/diagram_traits.h
new file mode 100644
index 0000000..c8d4862
--- /dev/null
+++ b/bottleneck/include/diagram_traits.h
@@ -0,0 +1,45 @@
+#ifndef HERA_DIAGRAM_TRAITS_H
+#define HERA_DIAGRAM_TRAITS_H
+
+namespace hera {
+
+template<class PairContainer_, class PointType_ = typename std::remove_reference< decltype(*std::declval<PairContainer_>().begin())>::type >
+struct DiagramTraits
+{
+ using Container = PairContainer_;
+ using PointType = PointType_;
+ using RealType = typename std::remove_reference< decltype(std::declval<PointType>()[0]) >::type;
+
+ static RealType get_x(const PointType& p) { return p[0]; }
+ static RealType get_y(const PointType& p) { return p[1]; }
+};
+
+
+template<class PairContainer_>
+struct DiagramTraits<PairContainer_, std::pair<double, double>>
+{
+ using PointType = std::pair<double, double>;
+ using RealType = double;
+ using Container = std::vector<PointType>;
+
+ static RealType get_x(const PointType& p) { return p.first; }
+ static RealType get_y(const PointType& p) { return p.second; }
+};
+
+
+template<class PairContainer_>
+struct DiagramTraits<PairContainer_, std::pair<float, float>>
+{
+ using PointType = std::pair<float, float>;
+ using RealType = float;
+ using Container = std::vector<PointType>;
+
+ static RealType get_x(const PointType& p) { return p.first; }
+ static RealType get_y(const PointType& p) { return p.second; }
+};
+
+
+} // end namespace hera
+
+
+#endif // HERA_DIAGRAM_TRAITS_H
diff --git a/bottleneck/include/dnn/geometry/euclidean-fixed.h b/bottleneck/include/dnn/geometry/euclidean-fixed.h
new file mode 100644
index 0000000..f45b980
--- /dev/null
+++ b/bottleneck/include/dnn/geometry/euclidean-fixed.h
@@ -0,0 +1,162 @@
+#ifndef HERA_BT_DNN_GEOMETRY_EUCLIDEAN_FIXED_H
+#define HERA_BT_DNN_GEOMETRY_EUCLIDEAN_FIXED_H
+
+#include <boost/operators.hpp>
+#include <boost/array.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/base_object.hpp>
+
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <cmath>
+
+#include "../parallel/tbb.h" // for dnn::vector<...>
+
+namespace hera {
+namespace bt {
+namespace dnn
+{
+ // TODO: wrap in another namespace (e.g., euclidean)
+
+ template<size_t D, typename Real = double>
+ struct Point:
+ boost::addable< Point<D,Real>,
+ boost::subtractable< Point<D,Real>,
+ boost::dividable2< Point<D, Real>, Real,
+ boost::multipliable2< Point<D, Real>, Real > > > >,
+ public boost::array<Real, D>
+ {
+ public:
+ typedef Real Coordinate;
+ typedef Real DistanceType;
+
+
+ public:
+ Point(size_t id = 0): id_(id) {}
+ template<size_t DD>
+ Point(const Point<DD,Real>& p, size_t id = 0):
+ id_(id) { *this = p; }
+
+ static size_t dimension() { return D; }
+
+ // Assign a point of different dimension
+ template<size_t DD>
+ Point& operator=(const Point<DD,Real>& p) { for (size_t i = 0; i < (D < DD ? D : DD); ++i) (*this)[i] = p[i]; if (DD < D) for (size_t i = DD; i < D; ++i) (*this)[i] = 0; return *this; }
+
+ Point& operator+=(const Point& p) { for (size_t i = 0; i < D; ++i) (*this)[i] += p[i]; return *this; }
+ Point& operator-=(const Point& p) { for (size_t i = 0; i < D; ++i) (*this)[i] -= p[i]; return *this; }
+ Point& operator/=(Real r) { for (size_t i = 0; i < D; ++i) (*this)[i] /= r; return *this; }
+ Point& operator*=(Real r) { for (size_t i = 0; i < D; ++i) (*this)[i] *= r; return *this; }
+
+ Real norm2() const { Real n = 0; for (size_t i = 0; i < D; ++i) n += (*this)[i] * (*this)[i]; return n; }
+ Real max_norm() const
+ {
+ Real m = std::fabs((*this)[0]);
+ for (size_t i = 1; i < D; ++i)
+ if (std::fabs((*this)[i]) > m)
+ m = std::fabs((*this)[i]);
+ return m; }
+
+ // quick and dirty for now; make generic later
+ //DistanceType distance(const Point& other) const { return sqrt(sq_distance(other)); }
+ //DistanceType sq_distance(const Point& other) const { return (other - *this).norm2(); }
+
+ DistanceType distance(const Point& other) const { return (other - *this).max_norm(); }
+ DistanceType sq_distance(const Point& other) const { DistanceType d = distance(other); return d*d; }
+
+ size_t id() const { return id_; }
+ size_t& id() { return id_; }
+
+ private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object< boost::array<Real,D> >(*this) & id_; }
+
+ private:
+ size_t id_;
+ };
+
+ template<size_t D, typename Real>
+ std::ostream&
+ operator<<(std::ostream& out, const Point<D,Real>& p)
+ { out << p[0]; for (size_t i = 1; i < D; ++i) out << " " << p[i]; return out; }
+
+
+ template<class Point>
+ struct PointTraits; // intentionally undefined; should be specialized for each type
+
+ template<size_t D, typename Real>
+ struct PointTraits< Point<D, Real> > // specialization for dnn::Point
+ {
+ typedef Point<D,Real> PointType;
+ typedef const PointType* PointHandle;
+ typedef std::vector<PointType> PointContainer;
+
+ typedef typename PointType::Coordinate Coordinate;
+ typedef typename PointType::DistanceType DistanceType;
+
+ static DistanceType
+ distance(const PointType& p1, const PointType& p2) { return p1.distance(p2); }
+ static DistanceType
+ distance(PointHandle p1, PointHandle p2) { return distance(*p1,*p2); }
+ static DistanceType
+ sq_distance(const PointType& p1,
+ const PointType& p2) { return p1.sq_distance(p2); }
+ static DistanceType
+ sq_distance(PointHandle p1, PointHandle p2) { return sq_distance(*p1,*p2); }
+ static size_t dimension() { return D; }
+ static Real coordinate(const PointType& p, size_t i) { return p[i]; }
+ static Real& coordinate(PointType& p, size_t i) { return p[i]; }
+ static Real coordinate(PointHandle p, size_t i) { return coordinate(*p,i); }
+
+ static size_t id(const PointType& p) { return p.id(); }
+ static size_t& id(PointType& p) { return p.id(); }
+ static size_t id(PointHandle p) { return id(*p); }
+
+ static PointHandle
+ handle(const PointType& p) { return &p; }
+ static const PointType&
+ point(PointHandle ph) { return *ph; }
+
+ void swap(PointType& p1, PointType& p2) const { return std::swap(p1, p2); }
+
+ static PointContainer
+ container(size_t n = 0, const PointType& p = PointType()) { return PointContainer(n, p); }
+ static typename PointContainer::iterator
+ iterator(PointContainer& c, PointHandle ph) { return c.begin() + (ph - &c[0]); }
+ static typename PointContainer::const_iterator
+ iterator(const PointContainer& c, PointHandle ph) { return c.begin() + (ph - &c[0]); }
+
+ private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int version) {}
+ };
+
+ template<class PointContainer>
+ void read_points(const std::string& filename, PointContainer& points)
+ {
+ typedef typename boost::range_value<PointContainer>::type Point;
+ typedef typename PointTraits<Point>::Coordinate Coordinate;
+
+ std::ifstream in(filename.c_str());
+ std::string line;
+ while(std::getline(in, line))
+ {
+ if (line[0] == '#') continue; // comment line in the file
+ std::stringstream linestream(line);
+ Coordinate x;
+ points.push_back(Point());
+ size_t i = 0;
+ while (linestream >> x)
+ points.back()[i++] = x;
+ }
+ }
+} // dnn
+} // bt
+} // hera
+#endif
diff --git a/bottleneck/include/dnn/local/kd-tree.h b/bottleneck/include/dnn/local/kd-tree.h
new file mode 100644
index 0000000..c1aed2b
--- /dev/null
+++ b/bottleneck/include/dnn/local/kd-tree.h
@@ -0,0 +1,106 @@
+#ifndef HERA_BT_DNN_LOCAL_KD_TREE_H
+#define HERA_BT_DNN_LOCAL_KD_TREE_H
+
+#include "../utils.h"
+#include "search-functors.h"
+
+#include <unordered_map>
+#include <stack>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/range/value_type.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+namespace hera {
+namespace bt {
+namespace dnn
+{
+ // Weighted KDTree
+ // Traits_ provides Coordinate, DistanceType, PointType, dimension(), distance(p1,p2), coordinate(p,i)
+ template< class Traits_ >
+ class KDTree
+ {
+ public:
+ typedef Traits_ Traits;
+ typedef hera::bt::dnn::HandleDistance<KDTree> HandleDistance;
+
+ typedef typename Traits::PointType Point;
+ typedef typename Traits::PointHandle PointHandle;
+ typedef typename Traits::Coordinate Coordinate;
+ typedef typename Traits::DistanceType DistanceType;
+ typedef std::vector<PointHandle> HandleContainer;
+ typedef std::vector<HandleDistance> HDContainer; // TODO: use tbb::scalable_allocator
+ typedef HDContainer Result;
+ typedef std::vector<DistanceType> DistanceContainer;
+ typedef std::unordered_map<PointHandle, size_t> HandleMap;
+ //private:
+ typedef typename HandleContainer::iterator HCIterator;
+ typedef std::tuple<HCIterator, HCIterator, size_t, ssize_t> KDTreeNode;
+ typedef std::tuple<HCIterator, HCIterator> KDTreeNodeNoCut;
+
+ //BOOST_STATIC_ASSERT_MSG(has_coordinates<Traits, PointHandle, int>::value, "KDTree requires coordinates");
+
+ public:
+ KDTree(const Traits& traits):
+ traits_(traits) {}
+
+ KDTree(const Traits& traits, HandleContainer&& handles);
+
+ template<class Range>
+ KDTree(const Traits& traits, const Range& range);
+
+ template<class Range>
+ void init(const Range& range);
+
+ HandleDistance find(PointHandle q) const;
+ Result findR(PointHandle q, DistanceType r) const; // all neighbors within r
+ Result findFirstR(PointHandle q, DistanceType r) const; // first neighbor within r
+ Result findK(PointHandle q, size_t k) const; // k nearest neighbors
+
+ HandleDistance find(const Point& q) const { return find(traits().handle(q)); }
+ Result findR(const Point& q, DistanceType r) const { return findR(traits().handle(q), r); }
+ Result findFirstR(const Point& q, DistanceType r) const { return findFirstR(traits().handle(q), r); }
+ Result findK(const Point& q, size_t k) const { return findK(traits().handle(q), k); }
+
+
+
+ template<class ResultsFunctor>
+ void search(PointHandle q, ResultsFunctor& rf) const;
+
+ const Traits& traits() const { return traits_; }
+
+ void get_path_to_root(const size_t idx, std::stack<KDTreeNodeNoCut>& s);
+ // to support deletion
+ void init_n_elems();
+ void delete_point(const size_t idx);
+ void delete_point(PointHandle p);
+ void update_n_elems(const ssize_t idx, const int delta);
+ void increase_n_elems(const ssize_t idx);
+ void decrease_n_elems(const ssize_t idx);
+ size_t get_num_points() const { return num_points_; }
+ //private:
+ void init();
+
+
+ struct CoordinateComparison;
+ struct OrderTree;
+
+ //private:
+ Traits traits_;
+ HandleContainer tree_;
+ std::vector<char> delete_flags_;
+ std::vector<int> subtree_n_elems;
+ HandleMap indices_;
+ std::vector<ssize_t> parents_;
+
+ size_t num_points_;
+ };
+} // dnn
+} // bt
+} // hera
+#include "kd-tree.hpp"
+
+#endif
diff --git a/bottleneck/include/dnn/local/kd-tree.hpp b/bottleneck/include/dnn/local/kd-tree.hpp
new file mode 100644
index 0000000..5b84eb0
--- /dev/null
+++ b/bottleneck/include/dnn/local/kd-tree.hpp
@@ -0,0 +1,296 @@
+#include <boost/range/counting_range.hpp>
+#include <boost/range/algorithm_ext/push_back.hpp>
+#include <boost/range.hpp>
+
+#include <queue>
+
+#include "../parallel/tbb.h"
+
+template<class T>
+hera::bt::dnn::KDTree<T>::KDTree(const Traits& traits, HandleContainer&& handles):
+ traits_(traits),
+ tree_(std::move(handles)),
+ delete_flags_(handles.size(), static_cast<char>(0) ),
+ subtree_n_elems(handles.size(), static_cast<size_t>(0)),
+ num_points_(handles.size())
+{
+ init();
+}
+
+template<class T>
+template<class Range>
+hera::bt::dnn::KDTree<T>::KDTree(const Traits& traits, const Range& range):
+ traits_(traits)
+{
+ init(range);
+}
+
+template<class T>
+template<class Range>
+void hera::bt::dnn::KDTree<T>::init(const Range& range)
+{
+ size_t sz = std::distance(std::begin(range), std::end(range));
+ subtree_n_elems = std::vector<int>(sz, 0);
+ delete_flags_ = std::vector<char>(sz, 0);
+ num_points_ = sz;
+ tree_.reserve(sz);
+ for (PointHandle h : range)
+ tree_.push_back(h);
+ parents_.resize(sz, -1);
+ init();
+}
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::init()
+{
+ if (tree_.empty())
+ return;
+
+#if defined(TBB)
+ task_group g;
+ g.run(OrderTree(this, tree_.begin(), tree_.end(), -1, 0, traits()));
+ g.wait();
+#else
+ OrderTree(this, tree_.begin(), tree_.end(), -1, 0, traits()).serial();
+#endif
+
+ for (size_t i = 0; i < tree_.size(); ++i)
+ indices_[tree_[i]] = i;
+ init_n_elems();
+}
+
+template<class T>
+struct
+hera::bt::dnn::KDTree<T>::OrderTree
+{
+ OrderTree(KDTree* tree_, HCIterator b_, HCIterator e_, ssize_t p_, size_t i_, const Traits& traits_):
+ tree(tree_), b(b_), e(e_), p(p_), i(i_), traits(traits_) {}
+
+ void operator()() const
+ {
+ if (e - b < 1000)
+ {
+ serial();
+ return;
+ }
+
+ HCIterator m = b + (e - b)/2;
+ ssize_t im = m - tree->tree_.begin();
+ tree->parents_[im] = p;
+
+ CoordinateComparison cmp(i, traits);
+ std::nth_element(b,m,e, cmp);
+ size_t next_i = (i + 1) % traits.dimension();
+
+ task_group g;
+ if (b < m - 1) g.run(OrderTree(tree, b, m, im, next_i, traits));
+ if (e > m + 2) g.run(OrderTree(tree, m+1, e, im, next_i, traits));
+ g.wait();
+ }
+
+ void serial() const
+ {
+ std::queue<KDTreeNode> q;
+ q.push(KDTreeNode(b,e,p,i));
+ while (!q.empty())
+ {
+ HCIterator b, e; ssize_t p; size_t i;
+ std::tie(b,e,p,i) = q.front();
+ q.pop();
+ HCIterator m = b + (e - b)/2;
+ ssize_t im = m - tree->tree_.begin();
+ tree->parents_[im] = p;
+
+ CoordinateComparison cmp(i, traits);
+ std::nth_element(b,m,e, cmp);
+ size_t next_i = (i + 1) % traits.dimension();
+
+ // Replace with a size condition instead?
+ if (m - b > 1)
+ q.push(KDTreeNode(b, m, im, next_i));
+ else if (b < m)
+ tree->parents_[im - 1] = im;
+ if (e - m > 2)
+ q.push(KDTreeNode(m+1, e, im, next_i));
+ else if (e > m + 1)
+ tree->parents_[im + 1] = im;
+ }
+ }
+
+ KDTree* tree;
+ HCIterator b, e;
+ ssize_t p;
+ size_t i;
+ const Traits& traits;
+};
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::update_n_elems(ssize_t idx, const int delta)
+// add delta to the number of points in node idx and update subtree_n_elems
+// for all parents of the node idx
+{
+ //std::cout << "subtree_n_elems.size = " << subtree_n_elems.size() << std::endl;
+ // update the node itself
+ while (idx != -1)
+ {
+ //std::cout << idx << std::endl;
+ subtree_n_elems[idx] += delta;
+ idx = parents_[idx];
+ }
+}
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::increase_n_elems(const ssize_t idx)
+{
+ update_n_elems(idx, static_cast<ssize_t>(1));
+}
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::decrease_n_elems(const ssize_t idx)
+{
+ update_n_elems(idx, static_cast<ssize_t>(-1));
+}
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::init_n_elems()
+{
+ for(size_t idx = 0; idx < tree_.size(); ++idx) {
+ increase_n_elems(idx);
+ }
+}
+
+
+template<class T>
+template<class ResultsFunctor>
+void hera::bt::dnn::KDTree<T>::search(PointHandle q, ResultsFunctor& rf) const
+{
+ typedef typename HandleContainer::const_iterator HCIterator;
+ typedef std::tuple<HCIterator, HCIterator, size_t> KDTreeNode;
+
+ if (tree_.empty())
+ return;
+
+ DistanceType D = std::numeric_limits<DistanceType>::infinity();
+
+ // TODO: use tbb::scalable_allocator for the queue
+ std::queue<KDTreeNode> nodes;
+
+ nodes.push(KDTreeNode(tree_.begin(), tree_.end(), 0));
+
+ //std::cout << "started kdtree::search" << std::endl;
+
+ while (!nodes.empty())
+ {
+ HCIterator b, e; size_t i;
+ std::tie(b,e,i) = nodes.front();
+ nodes.pop();
+
+ CoordinateComparison cmp(i, traits());
+ i = (i + 1) % traits().dimension();
+
+ HCIterator m = b + (e - b)/2;
+ size_t m_idx = m - tree_.begin();
+ // ignore deleted points
+ if ( delete_flags_[m_idx] == 0 ) {
+ DistanceType dist = traits().distance(q, *m);
+ // + weights_[m - tree_.begin()];
+ //std::cout << "Supplied to functor: m : ";
+ //std::cout << "(" << (*(*m))[0] << ", " << (*(*m))[1] << ")";
+ //std::cout << " and q : ";
+ //std::cout << "(" << (*q)[0] << ", " << (*q)[1] << ")" << std::endl;
+ //std::cout << "dist^q + weight = " << dist << std::endl;
+ //std::cout << "weight = " << weights_[m - tree_.begin()] << std::endl;
+ //std::cout << "dist = " << traits().distance(q, *m) << std::endl;
+ //std::cout << "dist^q = " << pow(traits().distance(q, *m), wassersteinPower) << std::endl;
+
+ D = rf(*m, dist);
+ }
+ // we are really searching w.r.t L_\infty ball; could prune better with an L_2 ball
+ Coordinate diff = cmp.diff(q, *m); // diff returns signed distance
+ DistanceType diffToWasserPower = (diff > 0 ? 1.0 : -1.0) * fabs(diff);
+
+ size_t lm = m + 1 + (e - (m+1))/2 - tree_.begin();
+ if ( e > m + 1 and subtree_n_elems[lm] > 0 ) {
+ if (e > m + 1 && diffToWasserPower >= -D) {
+ nodes.push(KDTreeNode(m+1, e, i));
+ }
+ }
+
+ size_t rm = b + (m - b) / 2 - tree_.begin();
+ if ( subtree_n_elems[rm] > 0 ) {
+ if (b < m && diffToWasserPower <= D) {
+ nodes.push(KDTreeNode(b, m, i));
+ }
+ }
+ }
+ //std::cout << "exited kdtree::search" << std::endl;
+}
+
+template<class T>
+typename hera::bt::dnn::KDTree<T>::HandleDistance hera::bt::dnn::KDTree<T>::find(PointHandle q) const
+{
+ hera::bt::dnn::NNRecord<HandleDistance> nn;
+ search(q, nn);
+ return nn.result;
+}
+
+template<class T>
+typename hera::bt::dnn::KDTree<T>::Result hera::bt::dnn::KDTree<T>::findR(PointHandle q, DistanceType r) const
+{
+ hera::bt::dnn::rNNRecord<HandleDistance> rnn(r);
+ search(q, rnn);
+ //std::sort(rnn.result.begin(), rnn.result.end());
+ return rnn.result;
+}
+
+template<class T>
+typename hera::bt::dnn::KDTree<T>::Result hera::bt::dnn::KDTree<T>::findFirstR(PointHandle q, DistanceType r) const
+{
+ hera::bt::dnn::firstrNNRecord<HandleDistance> rnn(r);
+ search(q, rnn);
+ return rnn.result;
+}
+
+template<class T>
+typename hera::bt::dnn::KDTree<T>::Result hera::bt::dnn::KDTree<T>::findK(PointHandle q, size_t k) const
+{
+ hera::bt::dnn::kNNRecord<HandleDistance> knn(k);
+ search(q, knn);
+ // do we need this???
+ std::sort(knn.result.begin(), knn.result.end());
+ return knn.result;
+}
+
+template<class T>
+struct hera::bt::dnn::KDTree<T>::CoordinateComparison
+{
+ CoordinateComparison(size_t i, const Traits& traits):
+ i_(i), traits_(traits) {}
+
+ bool operator()(PointHandle p1, PointHandle p2) const { return coordinate(p1) < coordinate(p2); }
+ Coordinate diff(PointHandle p1, PointHandle p2) const { return coordinate(p1) - coordinate(p2); }
+
+ Coordinate coordinate(PointHandle p) const { return traits_.coordinate(p, i_); }
+ size_t axis() const { return i_; }
+
+ private:
+ size_t i_;
+ const Traits& traits_;
+};
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::delete_point(const size_t idx)
+{
+ // prevent double deletion
+ assert(delete_flags_[idx] == 0);
+ delete_flags_[idx] = 1;
+ decrease_n_elems(idx);
+ --num_points_;
+}
+
+template<class T>
+void hera::bt::dnn::KDTree<T>::delete_point(PointHandle p)
+{
+ delete_point(indices_[p]);
+}
+
diff --git a/bottleneck/include/dnn/local/search-functors.h b/bottleneck/include/dnn/local/search-functors.h
new file mode 100644
index 0000000..63ad11d
--- /dev/null
+++ b/bottleneck/include/dnn/local/search-functors.h
@@ -0,0 +1,119 @@
+#ifndef HERA_BT_DNN_LOCAL_SEARCH_FUNCTORS_H
+#define HERA_BT_DNN_LOCAL_SEARCH_FUNCTORS_H
+
+#include <boost/range/algorithm/heap_algorithm.hpp>
+
+namespace hera
+{
+namespace bt
+{
+namespace dnn
+{
+
+template<class NN>
+struct HandleDistance
+{
+ typedef typename NN::PointHandle PointHandle;
+ typedef typename NN::DistanceType DistanceType;
+ typedef typename NN::HDContainer HDContainer;
+
+ HandleDistance() {}
+ HandleDistance(PointHandle pp, DistanceType dd):
+ p(pp), d(dd) {}
+ bool operator<(const HandleDistance& other) const { return d < other.d; }
+
+ PointHandle p;
+ DistanceType d;
+};
+
+template<class HandleDistance>
+struct NNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+
+ NNRecord() { result.d = std::numeric_limits<DistanceType>::infinity(); }
+ DistanceType operator()(PointHandle p, DistanceType d) { if (d < result.d) { result.p = p; result.d = d; } return result.d; }
+ HandleDistance result;
+};
+
+template<class HandleDistance>
+struct rNNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+ typedef typename HandleDistance::HDContainer HDContainer;
+
+ rNNRecord(DistanceType r_): r(r_) {}
+ DistanceType operator()(PointHandle p, DistanceType d)
+ {
+ if (d <= r)
+ result.push_back(HandleDistance(p,d));
+ return r;
+ }
+
+ DistanceType r;
+ HDContainer result;
+};
+
+template<class HandleDistance>
+struct firstrNNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+ typedef typename HandleDistance::HDContainer HDContainer;
+
+ firstrNNRecord(DistanceType r_): r(r_) {}
+
+ DistanceType operator()(PointHandle p, DistanceType d)
+ {
+ if (d <= r) {
+ result.push_back(HandleDistance(p,d));
+ return -100000000.0;
+ } else {
+ return r;
+ }
+ }
+
+ DistanceType r;
+ HDContainer result;
+};
+
+
+template<class HandleDistance>
+struct kNNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+ typedef typename HandleDistance::HDContainer HDContainer;
+
+ kNNRecord(unsigned k_): k(k_) {}
+ DistanceType operator()(PointHandle p, DistanceType d)
+ {
+ if (result.size() < k)
+ {
+ result.push_back(HandleDistance(p,d));
+ boost::push_heap(result);
+ if (result.size() < k)
+ return std::numeric_limits<DistanceType>::infinity();
+ } else if (d < result[0].d)
+ {
+ boost::pop_heap(result);
+ result.back() = HandleDistance(p,d);
+ boost::push_heap(result);
+ }
+ if ( result.size() > 1 ) {
+ assert( result[0].d >= result[1].d );
+ }
+ return result[0].d;
+ }
+
+ unsigned k;
+ HDContainer result;
+};
+
+} // dnn
+} // bt
+} // hera
+
+#endif // HERA_BT_DNN_LOCAL_SEARCH_FUNCTORS_H
diff --git a/bottleneck/include/dnn/parallel/tbb.h b/bottleneck/include/dnn/parallel/tbb.h
new file mode 100644
index 0000000..1462a9c
--- /dev/null
+++ b/bottleneck/include/dnn/parallel/tbb.h
@@ -0,0 +1,233 @@
+#ifndef HERA_BT_PARALLEL_H
+#define HERA_BT_PARALLEL_H
+
+#ifndef FOR_R_TDA
+#include <iostream>
+#endif
+
+#include <vector>
+
+#include <boost/range.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+
+#ifdef TBB
+
+#include <tbb/tbb.h>
+#include <tbb/concurrent_hash_map.h>
+#include <tbb/scalable_allocator.h>
+
+#include <boost/serialization/split_free.hpp>
+#include <boost/serialization/collections_load_imp.hpp>
+#include <boost/serialization/collections_save_imp.hpp>
+
+namespace hera {
+namespace bt {
+namespace dnn
+{
+ using tbb::mutex;
+ using tbb::task_scheduler_init;
+ using tbb::task_group;
+ using tbb::task;
+
+ template<class T>
+ struct vector
+ {
+ typedef tbb::concurrent_vector<T> type;
+ };
+
+ template<class T>
+ struct atomic
+ {
+ typedef tbb::atomic<T> type;
+ static T compare_and_swap(type& v, T n, T o) { return v.compare_and_swap(n,o); }
+ };
+
+ template<class Iterator, class F>
+ void do_foreach(Iterator begin, Iterator end, const F& f) { tbb::parallel_do(begin, end, f); }
+
+ template<class Range, class F>
+ void for_each_range_(const Range& r, const F& f)
+ {
+ for (typename Range::iterator cur = r.begin(); cur != r.end(); ++cur)
+ f(*cur);
+ }
+
+ template<class F>
+ void for_each_range(size_t from, size_t to, const F& f)
+ {
+ //static tbb::affinity_partitioner ap;
+ //tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f), ap);
+ tbb::parallel_for(from, to, f);
+ }
+
+ template<class Container, class F>
+ void for_each_range(const Container& c, const F& f)
+ {
+ //static tbb::affinity_partitioner ap;
+ //tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f), ap);
+ tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::const_range_type, F>, _1, f));
+ }
+
+ template<class Container, class F>
+ void for_each_range(Container& c, const F& f)
+ {
+ //static tbb::affinity_partitioner ap;
+ //tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f), ap);
+ tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f));
+ }
+
+ template<class ID, class NodePointer, class IDTraits, class Allocator>
+ struct map_traits
+ {
+ typedef tbb::concurrent_hash_map<ID, NodePointer, IDTraits, Allocator> type;
+ typedef typename type::range_type range;
+ };
+
+ struct progress_timer
+ {
+ progress_timer(): start(tbb::tick_count::now()) {}
+ ~progress_timer()
+ {
+#ifndef FOR_R_TDA
+ std::cout << (tbb::tick_count::now() - start).seconds() << " s" << std::endl;
+#endif
+ }
+
+ tbb::tick_count start;
+ };
+}
+}
+}
+
+// Serialization for tbb::concurrent_vector<...>
+namespace boost
+{
+ namespace serialization
+ {
+ template<class Archive, class T, class A>
+ void save(Archive& ar, const tbb::concurrent_vector<T,A>& v, const unsigned int file_version)
+ { stl::save_collection(ar, v); }
+
+ template<class Archive, class T, class A>
+ void load(Archive& ar, tbb::concurrent_vector<T,A>& v, const unsigned int file_version)
+ {
+ stl::load_collection<Archive,
+ tbb::concurrent_vector<T,A>,
+ stl::archive_input_seq< Archive, tbb::concurrent_vector<T,A> >,
+ stl::reserve_imp< tbb::concurrent_vector<T,A> >
+ >(ar, v);
+ }
+
+ template<class Archive, class T, class A>
+ void serialize(Archive& ar, tbb::concurrent_vector<T,A>& v, const unsigned int file_version)
+ { split_free(ar, v, file_version); }
+
+ template<class Archive, class T>
+ void save(Archive& ar, const tbb::atomic<T>& v, const unsigned int file_version)
+ { T v_ = v; ar << v_; }
+
+ template<class Archive, class T>
+ void load(Archive& ar, tbb::atomic<T>& v, const unsigned int file_version)
+ { T v_; ar >> v_; v = v_; }
+
+ template<class Archive, class T>
+ void serialize(Archive& ar, tbb::atomic<T>& v, const unsigned int file_version)
+ { split_free(ar, v, file_version); }
+ }
+}
+
+#else
+
+#include <algorithm>
+#include <map>
+
+namespace hera {
+namespace bt {
+namespace dnn
+{
+ template<class T>
+ struct vector
+ {
+ typedef ::std::vector<T> type;
+ };
+
+ template<class T>
+ struct atomic
+ {
+ typedef T type;
+ static T compare_and_swap(type& v, T n, T o) { if (v != o) return v; v = n; return o; }
+ };
+
+ template<class Iterator, class F>
+ void do_foreach(Iterator begin, Iterator end, const F& f) { std::for_each(begin, end, f); }
+
+ template<class F>
+ void for_each_range(size_t from, size_t to, const F& f)
+ {
+ for (size_t i = from; i < to; ++i)
+ f(i);
+ }
+
+ template<class Container, class F>
+ void for_each_range(Container& c, const F& f)
+ {
+ BOOST_FOREACH(const typename Container::value_type& i, c)
+ f(i);
+ }
+
+ template<class Container, class F>
+ void for_each_range(const Container& c, const F& f)
+ {
+ BOOST_FOREACH(const typename Container::value_type& i, c)
+ f(i);
+ }
+
+ struct mutex
+ {
+ struct scoped_lock
+ {
+ scoped_lock() {}
+ scoped_lock(mutex& ) {}
+ void acquire(mutex& ) const {}
+ void release() const {}
+ };
+ };
+
+ struct task_scheduler_init
+ {
+ task_scheduler_init(unsigned) {}
+ void initialize(unsigned) {}
+ static const unsigned automatic = 0;
+ static const unsigned deferred = 0;
+ };
+
+ struct task_group
+ {
+ template<class Functor>
+ void run(const Functor& f) const { f(); }
+ void wait() const {}
+ };
+
+ template<class ID, class NodePointer, class IDTraits, class Allocator>
+ struct map_traits
+ {
+ typedef std::map<ID, NodePointer,
+ typename IDTraits::Comparison,
+ Allocator> type;
+ typedef type range;
+ };
+
+}
+}
+}
+
+#endif // TBB
+
+namespace dnn
+{
+ template<class Range, class F>
+ void do_foreach(const Range& range, const F& f) { do_foreach(boost::begin(range), boost::end(range), f); }
+}
+
+#endif
diff --git a/bottleneck/include/dnn/parallel/utils.h b/bottleneck/include/dnn/parallel/utils.h
new file mode 100644
index 0000000..9809e77
--- /dev/null
+++ b/bottleneck/include/dnn/parallel/utils.h
@@ -0,0 +1,100 @@
+#ifndef HERA_BT_PARALLEL_UTILS_H
+#define HERA_BT_PARALLEL_UTILS_H
+
+#include "../utils.h"
+
+namespace hera
+{
+namespace bt
+{
+namespace dnn
+{
+ // Assumes rng is synchronized across ranks
+ template<class DataVector, class RNGType, class SwapFunctor>
+ void shuffle(mpi::communicator& world, DataVector& data, RNGType& rng, const SwapFunctor& swap, DataVector empty = DataVector());
+
+ template<class DataVector, class RNGType>
+ void shuffle(mpi::communicator& world, DataVector& data, RNGType& rng)
+ {
+ typedef decltype(data[0]) T;
+ shuffle(world, data, rng, [](T& x, T& y) { std::swap(x,y); });
+ }
+}
+}
+}
+
+template<class DataVector, class RNGType, class SwapFunctor>
+void
+hera::bt::dnn::shuffle(mpi::communicator& world, DataVector& data, RNGType& rng, const SwapFunctor& swap, DataVector empty)
+{
+ // This is not a perfect shuffle: it dishes out data in chunks of 1/size.
+ // (It can be interpreted as generating a bistochastic matrix by taking the
+ // sum of size random permutation matrices.) Hopefully, it works for our purposes.
+
+ typedef typename RNGType::result_type RNGResult;
+
+ int size = world.size();
+ int rank = world.rank();
+
+ // Generate local seeds
+ boost::uniform_int<RNGResult> uniform;
+ RNGResult seed;
+ for (size_t i = 0; i < size; ++i)
+ {
+ RNGResult v = uniform(rng);
+ if (i == rank)
+ seed = v;
+ }
+ RNGType local_rng(seed);
+
+ // Shuffle local data
+ hera::bt::dnn::random_shuffle(data.begin(), data.end(), local_rng, swap);
+
+ // Decide how much of our data goes to i-th processor
+ std::vector<size_t> out_counts(size);
+ std::vector<int> ranks(boost::counting_iterator<int>(0),
+ boost::counting_iterator<int>(size));
+ for (size_t i = 0; i < size; ++i)
+ {
+ hera::bt::dnn::random_shuffle(ranks.begin(), ranks.end(), rng);
+ ++out_counts[ranks[rank]];
+ }
+
+ // Fill the outgoing array
+ size_t total = 0;
+ std::vector< DataVector > outgoing(size, empty);
+ for (size_t i = 0; i < size; ++i)
+ {
+ size_t count = data.size()*out_counts[i]/size;
+ if (total + count > data.size())
+ count = data.size() - total;
+
+ outgoing[i].reserve(count);
+ for (size_t j = total; j < total + count; ++j)
+ outgoing[i].push_back(data[j]);
+
+ total += count;
+ }
+
+ boost::uniform_int<size_t> uniform_outgoing(0,size-1); // in range [0,size-1]
+ while(total < data.size()) // send leftover to random processes
+ {
+ outgoing[uniform_outgoing(local_rng)].push_back(data[total]);
+ ++total;
+ }
+ data.clear();
+
+ // Exchange the data
+ std::vector< DataVector > incoming(size, empty);
+ mpi::all_to_all(world, outgoing, incoming);
+ outgoing.clear();
+
+ // Assemble our data
+ for(const DataVector& vec : incoming)
+ for (size_t i = 0; i < vec.size(); ++i)
+ data.push_back(vec[i]);
+ hera::bt::dnn::random_shuffle(data.begin(), data.end(), local_rng, swap);
+ // XXX: the final shuffle is irrelevant for our purposes. But it's also cheap.
+}
+
+#endif
diff --git a/bottleneck/include/dnn/utils.h b/bottleneck/include/dnn/utils.h
new file mode 100644
index 0000000..f4ce632
--- /dev/null
+++ b/bottleneck/include/dnn/utils.h
@@ -0,0 +1,47 @@
+#ifndef HERA_BT_DNN_UTILS_H
+#define HERA_BT_DNN_UTILS_H
+
+#include <boost/random/uniform_int.hpp>
+#include <boost/foreach.hpp>
+#include <boost/typeof/typeof.hpp>
+
+namespace hera
+{
+namespace bt
+{
+namespace dnn
+{
+
+template <typename T, typename... Args>
+struct has_coordinates
+{
+ template <typename C, typename = decltype( std::declval<C>().coordinate(std::declval<Args>()...) )>
+ static std::true_type test(int);
+
+ template <typename C>
+ static std::false_type test(...);
+
+ static constexpr bool value = decltype(test<T>(0))::value;
+};
+
+template<class RandomIt, class UniformRandomNumberGenerator, class SwapFunctor>
+void random_shuffle(RandomIt first, RandomIt last, UniformRandomNumberGenerator& g, const SwapFunctor& swap)
+{
+ size_t n = last - first;
+ boost::uniform_int<size_t> uniform(0,n);
+ for (size_t i = n-1; i > 0; --i)
+ swap(first[i], first[uniform(g,i+1)]); // picks a random number in [0,i] range
+}
+
+template<class RandomIt, class UniformRandomNumberGenerator>
+void random_shuffle(RandomIt first, RandomIt last, UniformRandomNumberGenerator& g)
+{
+ typedef decltype(*first) T;
+ random_shuffle(first, last, g, [](T& x, T& y) { std::swap(x,y); });
+}
+
+} // dnn
+} // bt
+} // hera
+
+#endif
diff --git a/bottleneck/include/neighb_oracle.h b/bottleneck/include/neighb_oracle.h
new file mode 100644
index 0000000..91ebc0e
--- /dev/null
+++ b/bottleneck/include/neighb_oracle.h
@@ -0,0 +1,295 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_NEIGHB_ORACLE_H
+#define HERA_NEIGHB_ORACLE_H
+
+#include <unordered_map>
+#include <algorithm>
+#include <memory>
+
+#include "basic_defs_bt.h"
+#include "dnn/geometry/euclidean-fixed.h"
+#include "dnn/local/kd-tree.h"
+
+
+
+namespace hera {
+namespace bt {
+
+template<class Real>
+class NeighbOracleSimple
+{
+public:
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointSet = DiagramPointSet<Real>;
+
+private:
+ Real r;
+ Real distEpsilon;
+ DgmPointSet pointSet;
+
+public:
+
+ NeighbOracleSimple() : r(0.0) {}
+
+ NeighbOracleSimple(const DgmPointSet& _pointSet, const Real _r, const Real _distEpsilon) :
+ r(_r),
+ distEpsilon(_distEpsilon),
+ pointSet(_pointSet)
+ {}
+
+ void deletePoint(const DgmPoint& p)
+ {
+ pointSet.erase(p);
+ }
+
+ void rebuild(const DgmPointSet& S, const double rr)
+ {
+ pointSet = S;
+ r = rr;
+ }
+
+ bool getNeighbour(const DgmPoint& q, DgmPoint& result) const
+ {
+ for(auto pit = pointSet.cbegin(); pit != pointSet.cend(); ++pit) {
+ if ( distLInf(*pit, q) <= r) {
+ result = *pit;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void getAllNeighbours(const DgmPoint& q, std::vector<DgmPoint>& result)
+ {
+ result.clear();
+ for(const auto& point : pointSet) {
+ if ( distLInf(point, q) <= r) {
+ result.push_back(point);
+ }
+ }
+ for(auto& pt : result) {
+ deletePoint(pt);
+ }
+ }
+
+};
+
+template<class Real_>
+class NeighbOracleDnn
+{
+public:
+
+ using Real = Real_;
+ using DnnPoint = dnn::Point<2, double>;
+ using DnnTraits = dnn::PointTraits<DnnPoint>;
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointSet = DiagramPointSet<Real>;
+ using DgmPointHash = DiagramPointHash<Real>;
+
+ Real r;
+ Real distEpsilon;
+ std::vector<DgmPoint> allPoints;
+ DgmPointSet diagonalPoints;
+ std::unordered_map<DgmPoint, size_t, DgmPointHash> pointIdxLookup;
+ // dnn-stuff
+ std::unique_ptr<dnn::KDTree<DnnTraits>> kdtree;
+ std::vector<DnnPoint> dnnPoints;
+ std::vector<DnnPoint*> dnnPointHandles;
+ std::vector<size_t> kdtreeItems;
+
+ NeighbOracleDnn(const DgmPointSet& S, const Real rr, const Real dEps) :
+ kdtree(nullptr)
+ {
+ assert(dEps >= 0);
+ distEpsilon = dEps;
+ rebuild(S, rr);
+ }
+
+
+ void deletePoint(const DgmPoint& p)
+ {
+ auto findRes = pointIdxLookup.find(p);
+ assert(findRes != pointIdxLookup.end());
+ //std::cout << "Deleting point " << p << std::endl;
+ size_t pointIdx { (*findRes).second };
+ //std::cout << "pointIdx = " << pointIdx << std::endl;
+ diagonalPoints.erase(p, false);
+ kdtree->delete_point(dnnPointHandles[kdtreeItems[pointIdx]]);
+ }
+
+ void rebuild(const DgmPointSet& S, const Real rr)
+ {
+ //std::cout << "Entered rebuild, r = " << rr << std::endl;
+ r = rr;
+ size_t dnnNumPoints = S.size();
+ //printDebug(isDebug, "S = ", S);
+ if (dnnNumPoints > 0) {
+ pointIdxLookup.clear();
+ pointIdxLookup.reserve(S.size());
+ allPoints.clear();
+ allPoints.reserve(S.size());
+ diagonalPoints.clear();
+ diagonalPoints.reserve(S.size() / 2);
+ for(auto pit = S.cbegin(); pit != S.cend(); ++pit) {
+ allPoints.push_back(*pit);
+ if (pit->isDiagonal()) {
+ diagonalPoints.insert(*pit);
+ }
+ }
+
+ size_t pointIdx = 0;
+ for(auto& dataPoint : allPoints) {
+ pointIdxLookup.insert( { dataPoint, pointIdx++ } );
+ }
+
+ size_t dnnItemIdx { 0 };
+ size_t trueIdx { 0 };
+ dnnPoints.clear();
+ kdtreeItems.clear();
+ dnnPointHandles.clear();
+ dnnPoints.clear();
+ kdtreeItems.reserve(S.size() );
+ // store normal items in kd-tree
+ for(const auto& g : allPoints) {
+ if (true) {
+ kdtreeItems.push_back(dnnItemIdx);
+ // index of items is id of dnn-point
+ DnnPoint p(trueIdx);
+ p[0] = g.getRealX();
+ p[1] = g.getRealY();
+ dnnPoints.push_back(p);
+ assert(dnnItemIdx == dnnPoints.size() - 1);
+ dnnItemIdx++;
+ }
+ trueIdx++;
+ }
+ assert(dnnPoints.size() == allPoints.size() );
+ for(size_t i = 0; i < dnnPoints.size(); ++i) {
+ dnnPointHandles.push_back(&dnnPoints[i]);
+ }
+ DnnTraits traits;
+ //std::cout << "kdtree: " << dnnPointHandles.size() << " points" << std::endl;
+ kdtree.reset(new dnn::KDTree<DnnTraits>(traits, dnnPointHandles));
+ }
+ }
+
+
+ bool getNeighbour(const DgmPoint& q, DgmPoint& result) const
+ {
+ //std::cout << "getNeighbour for q = " << q << ", r = " << r << std::endl;
+ //std::cout << *this << std::endl;
+ // distance between two diagonal points
+ // is 0
+ if (q.isDiagonal()) {
+ if (!diagonalPoints.empty()) {
+ result = *diagonalPoints.cbegin();
+ //std::cout << "Neighbour found in diagonal points, res = " << result;
+ return true;
+ }
+ }
+ // check if kdtree is not empty
+ if (0 == kdtree->get_num_points() ) {
+ //std::cout << "empty tree, no neighb." << std::endl;
+ return false;
+ }
+ // if no neighbour found among diagonal points,
+ // search in kd_tree
+ DnnPoint queryPoint;
+ queryPoint[0] = q.getRealX();
+ queryPoint[1] = q.getRealY();
+ auto kdtreeResult = kdtree->findFirstR(queryPoint, r);
+ if (kdtreeResult.empty()) {
+ //std::cout << "no neighbour within " << r << "found." << std::endl;
+ return false;
+ }
+ if (kdtreeResult[0].d <= r + distEpsilon) {
+ result = allPoints[kdtreeResult[0].p->id()];
+ //std::cout << "Neighbour found with kd-tree, index = " << kdtreeResult[0].p->id() << std::endl;
+ //std::cout << "result = " << result << std::endl;
+ return true;
+ }
+ //std::cout << "No neighbour found for r = " << r << std::endl;
+ return false;
+ }
+
+
+
+ void getAllNeighbours(const DgmPoint& q, std::vector<DgmPoint>& result)
+ {
+ //std::cout << "Entered getAllNeighbours for q = " << q << std::endl;
+ result.clear();
+ // add diagonal points, if necessary
+ if ( q.isDiagonal() ) {
+ for( auto& diagPt : diagonalPoints ) {
+ result.push_back(diagPt);
+ }
+ }
+ // delete diagonal points we found
+ // to prevent finding them again
+ for(auto& pt : result) {
+ //std::cout << "deleting DIAG point pt = " << pt << std::endl;
+ deletePoint(pt);
+ }
+ size_t diagOffset = result.size();
+ std::vector<size_t> pointIndicesOut;
+ // perorm range search on kd-tree
+ DnnPoint queryPoint;
+ queryPoint[0] = q.getRealX();
+ queryPoint[1] = q.getRealY();
+ auto kdtreeResult = kdtree->findR(queryPoint, r);
+ pointIndicesOut.reserve(kdtreeResult.size());
+ for(auto& handleDist : kdtreeResult) {
+ if (handleDist.d <= r + distEpsilon) {
+ pointIndicesOut.push_back(handleDist.p->id());
+ } else {
+ break;
+ }
+ }
+ // get actual points in result
+ for(auto& ptIdx : pointIndicesOut) {
+ result.push_back(allPoints[ptIdx]);
+ }
+ // delete all points we found
+ for(auto ptIt = result.begin() + diagOffset; ptIt != result.end(); ++ptIt) {
+ //printDebug(isDebug, "deleting point pt = ", *ptIt);
+ deletePoint(*ptIt);
+ }
+ }
+
+ //DgmPointSet originalPointSet;
+ template<class R>
+ friend std::ostream& operator<<(std::ostream& out, const NeighbOracleDnn<R>& oracle);
+
+};
+
+} // end namespace bt
+} // end namespace hera
+
+#endif // HERA_NEIGHB_ORACLE_H
diff --git a/bottleneck/tests/data/test_001_A b/bottleneck/tests/data/test_001_A
new file mode 100644
index 0000000..8d04f96
--- /dev/null
+++ b/bottleneck/tests/data/test_001_A
@@ -0,0 +1 @@
+1 2
diff --git a/bottleneck/tests/data/test_001_B b/bottleneck/tests/data/test_001_B
new file mode 100644
index 0000000..9290688
--- /dev/null
+++ b/bottleneck/tests/data/test_001_B
@@ -0,0 +1 @@
+4 6
diff --git a/bottleneck/tests/data/test_002_A b/bottleneck/tests/data/test_002_A
new file mode 100644
index 0000000..8d04f96
--- /dev/null
+++ b/bottleneck/tests/data/test_002_A
@@ -0,0 +1 @@
+1 2
diff --git a/bottleneck/tests/data/test_002_B b/bottleneck/tests/data/test_002_B
new file mode 100644
index 0000000..a4cec9b
--- /dev/null
+++ b/bottleneck/tests/data/test_002_B
@@ -0,0 +1 @@
+1.1 2.2
diff --git a/bottleneck/tests/data/test_003_A b/bottleneck/tests/data/test_003_A
new file mode 100644
index 0000000..fdf0acd
--- /dev/null
+++ b/bottleneck/tests/data/test_003_A
@@ -0,0 +1,2 @@
+1 2
+2 inf
diff --git a/bottleneck/tests/data/test_003_B b/bottleneck/tests/data/test_003_B
new file mode 100644
index 0000000..ac429f9
--- /dev/null
+++ b/bottleneck/tests/data/test_003_B
@@ -0,0 +1,2 @@
+1.1 2.2
+4 inf
diff --git a/bottleneck/tests/data/test_004_A b/bottleneck/tests/data/test_004_A
new file mode 100644
index 0000000..fdf0acd
--- /dev/null
+++ b/bottleneck/tests/data/test_004_A
@@ -0,0 +1,2 @@
+1 2
+2 inf
diff --git a/bottleneck/tests/data/test_004_B b/bottleneck/tests/data/test_004_B
new file mode 100644
index 0000000..5769823
--- /dev/null
+++ b/bottleneck/tests/data/test_004_B
@@ -0,0 +1,3 @@
+1.1 2.2
+4 inf
+4 inf
diff --git a/bottleneck/tests/data/test_005_A b/bottleneck/tests/data/test_005_A
new file mode 100644
index 0000000..e28367d
--- /dev/null
+++ b/bottleneck/tests/data/test_005_A
@@ -0,0 +1,6 @@
+1 2
+2 inf
+3 inf
+10 inf
+inf 21
+inf 44
diff --git a/bottleneck/tests/data/test_005_B b/bottleneck/tests/data/test_005_B
new file mode 100644
index 0000000..7f6032b
--- /dev/null
+++ b/bottleneck/tests/data/test_005_B
@@ -0,0 +1,6 @@
+1.1 2.2
+4 inf
+4 inf
+12 inf
+inf 20
+inf 40
diff --git a/bottleneck/tests/data/test_006_A b/bottleneck/tests/data/test_006_A
new file mode 100644
index 0000000..b5184a5
--- /dev/null
+++ b/bottleneck/tests/data/test_006_A
@@ -0,0 +1,7 @@
+1 2
+2 inf
+3 inf
+10 inf
+inf 21
+inf 44
+1 34
diff --git a/bottleneck/tests/data/test_006_B b/bottleneck/tests/data/test_006_B
new file mode 100644
index 0000000..0d07369
--- /dev/null
+++ b/bottleneck/tests/data/test_006_B
@@ -0,0 +1,7 @@
+2 40
+1.1 2.2
+4 inf
+4 inf
+12 inf
+inf 20
+inf 40
diff --git a/bottleneck/tests/data/test_007_A b/bottleneck/tests/data/test_007_A
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bottleneck/tests/data/test_007_A
diff --git a/bottleneck/tests/data/test_007_B b/bottleneck/tests/data/test_007_B
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bottleneck/tests/data/test_007_B
diff --git a/bottleneck/tests/data/test_008_A b/bottleneck/tests/data/test_008_A
new file mode 100644
index 0000000..50b3df6
--- /dev/null
+++ b/bottleneck/tests/data/test_008_A
@@ -0,0 +1 @@
+0 1.1
diff --git a/bottleneck/tests/data/test_008_B b/bottleneck/tests/data/test_008_B
new file mode 100644
index 0000000..1935b11
--- /dev/null
+++ b/bottleneck/tests/data/test_008_B
@@ -0,0 +1 @@
+0 0.1
diff --git a/bottleneck/tests/data/test_009_A b/bottleneck/tests/data/test_009_A
new file mode 100644
index 0000000..a1b859e
--- /dev/null
+++ b/bottleneck/tests/data/test_009_A
@@ -0,0 +1 @@
+1.1 0
diff --git a/bottleneck/tests/data/test_009_B b/bottleneck/tests/data/test_009_B
new file mode 100644
index 0000000..b5befbc
--- /dev/null
+++ b/bottleneck/tests/data/test_009_B
@@ -0,0 +1 @@
+0.1 0
diff --git a/bottleneck/tests/data/test_010_A b/bottleneck/tests/data/test_010_A
new file mode 100644
index 0000000..8d126f0
--- /dev/null
+++ b/bottleneck/tests/data/test_010_A
@@ -0,0 +1,100 @@
+7.50638 7.78005
+0.991758 2.12178
+5.18481 6.61702
+6.14703 7.08581
+4.09936 4.83024
+3.79915 4.51283
+3.17645 3.75321
+0.61305 0.998622
+0.445643 1.13781
+6.38205 6.53669
+5.96392 6.44093
+7.21047 7.26005
+0.6703 1.26593
+0.529933 1.7027
+7.92495 8.83023
+2.1382 2.71695
+3.79209 4.5197
+5.23354 5.82214
+-0.395097 2.18831
+3.22028 3.88648
+5.56262 5.79949
+8.39623 9.37185
+2.7452 3.84539
+9.5022 10.2414
+1.01374 1.40504
+3.2029 3.89559
+7.61236 8.28485
+6.4371 6.909
+4.45616 5.35067
+1.57802 1.77895
+6.5991 7.76339
+6.66729 6.71714
+6.11898 6.57121
+2.60663 4.36396
+-0.259613 1.17683
+7.72857 9.48862
+4.68398 5.51521
+4.87447 5.4233
+6.86301 6.88244
+4.17814 4.25886
+8.70558 9.72902
+4.40873 4.57389
+6.1824 7.05049
+7.97557 8.79739
+8.52591 8.6985
+5.15336 5.27796
+9.70144 9.77031
+0.561778 1.39045
+9.32553 10.2456
+7.01495 7.74521
+6.83355 7.28255
+1.96721 3.01504
+5.78411 7.59464
+5.64012 6.10721
+3.7249 5.17086
+4.33297 5.91657
+7.11793 7.2545
+5.109 6.76878
+3.02787 3.04077
+0.999365 2.05566
+8.81392 8.9086
+6.20106 6.78943
+6.7987 7.05794
+0.438805 0.449602
+8.71793 9.79853
+-0.150282 0.51997
+5.72257 5.93156
+5.71098 6.09535
+9.0378 9.45942
+0.534987 0.872885
+7.72276 8.57754
+9.26069 9.40289
+4.148 4.80519
+1.04579 3.18109
+0.259767 0.93215
+0.250608 0.511569
+4.88108 5.62239
+4.6731 5.3348
+7.84979 7.93545
+0.912521 1.48142
+4.82553 5.38108
+6.02179 7.61665
+3.85848 6.39418
+5.10754 6.02118
+1.71956 1.86238
+6.47336 6.74034
+-0.0371018 0.212738
+3.97259 4.15465
+2.17413 3.20188
+4.49098 6.09812
+6.62445 7.84196
+6.57541 7.432
+6.81052 9.6653
+3.67502 4.69734
+3.92378 4.14743
+5.93127 6.46154
+0.63424 0.705454
+7.60129 9.23263
+4.23064 4.74575
+0.397705 1.24458
diff --git a/bottleneck/tests/data/test_010_B b/bottleneck/tests/data/test_010_B
new file mode 100644
index 0000000..852799d
--- /dev/null
+++ b/bottleneck/tests/data/test_010_B
@@ -0,0 +1,100 @@
+5.8232 6.36308
+2.16066 2.48668
+2.38754 4.91418
+4.77403 5.43982
+0.291412 1.11147
+3.77337 5.2686
+8.31344 9.05384
+0.734064 1.14844
+7.57606 7.8521
+3.16719 3.86953
+2.55072 2.64932
+9.51707 9.6071
+0.304643 2.41784
+2.79925 3.28234
+5.32901 7.7576
+5.19903 6.30449
+1.87819 2.99454
+8.92272 9.67105
+4.62414 5.05592
+4.0079 4.64148
+2.26369 3.44573
+2.69335 3.13426
+1.90706 2.42652
+2.68113 2.79133
+1.41065 1.56018
+6.55282 7.18725
+5.72986 6.37151
+7.26968 8.22623
+3.32643 3.73606
+3.77325 4.63115
+1.05457 1.83651
+8.6815 8.85251
+3.91285 4.17139
+0.380936 0.842109
+7.33227 7.69334
+8.45635 8.923
+4.1769 5.08373
+0.501374 2.23328
+-0.161782 1.28908
+3.44716 3.4662
+3.15394 4.30243
+8.71416 9.3781
+6.3034 8.62893
+6.53824 7.04611
+0.6386 1.35269
+0.862088 0.960371
+5.12963 5.20203
+1.58695 2.0452
+6.57698 6.63228
+3.87747 4.45669
+1.51273 3.25669
+-0.0992804 0.667302
+4.7489 4.80059
+0.0280559 1.90471
+6.7462 8.27612
+0.915652 1.30007
+2.79556 3.77404
+9.87989 10.0722
+9.39105 9.84229
+7.57235 9.37122
+5.09426 6.44266
+6.3994 6.72037
+5.73441 6.99341
+6.9079 7.88049
+4.2003 4.41933
+-1.72447 2.25877
+9.04907 9.64323
+4.40473 5.3593
+9.31201 9.96079
+7.28343 8.74163
+3.0172 6.23779
+8.08422 8.56069
+6.83038 6.99863
+2.32038 3.1289
+7.42302 8.26286
+6.66905 7.18496
+0.730748 1.61335
+4.00564 5.73993
+2.81231 3.67489
+2.33178 2.37845
+9.03302 9.68681
+0.567816 0.755485
+7.89783 8.7621
+0.177662 0.332833
+-0.181569 1.36821
+6.22158 6.55787
+4.67115 5.16995
+0.806432 0.820738
+7.69636 7.87402
+4.40933 4.54995
+9.1329 9.15037
+8.87416 9.04329
+1.14349 1.8993
+3.29756 4.7172
+6.67873 8.31364
+6.91238 7.1654
+0.483084 1.55006
+2.66058 3.86294
+5.93347 6.06085
+7.40514 9.05071
diff --git a/bottleneck/tests/data/test_011_A b/bottleneck/tests/data/test_011_A
new file mode 100644
index 0000000..164b71d
--- /dev/null
+++ b/bottleneck/tests/data/test_011_A
@@ -0,0 +1,200 @@
+0.471299 1.89241
+2.82136 3.97846
+8.81923 9.20678
+1.42474 1.65425
+8.36963 9.16097
+-0.236476 0.692489
+7.57182 8.06148
+2.89878 3.21958
+7.1285 7.51707
+5.75496 7.09461
+6.00081 6.10914
+9.60869 9.64676
+7.42889 8.97174
+7.26061 8.55944
+2.41226 2.5146
+8.5616 9.44847
+7.4946 8.86962
+5.42244 6.98028
+9.62386 9.96039
+7.70591 9.92849
+1.34119 3.2048
+3.92169 5.15228
+8.82955 9.60318
+7.94213 9.39997
+2.6716 4.02057
+0.375206 0.497663
+1.94572 3.65599
+1.03366 1.46356
+8.91855 10.1838
+7.11087 8.64425
+2.63266 2.78706
+8.93611 10.2943
+8.51999 9.28356
+1.31436 3.13725
+1.92871 4.00178
+8.30503 8.45555
+2.58739 2.82076
+3.20419 5.29453
+7.4015 8.13225
+9.07991 9.74729
+0.822366 0.938371
+2.90508 4.29367
+4.32385 5.4787
+3.63054 4.6918
+8.52962 9.87004
+1.16994 2.39465
+2.61903 3.33772
+4.15505 4.52942
+8.7068 9.66579
+8.10373 9.31351
+0.7954 1.23001
+7.82253 8.69505
+4.59616 5.91996
+1.02032 1.93931
+6.98421 8.46017
+8.42263 11.3447
+2.63444 3.7158
+7.49059 9.1137
+-0.122109 1.41074
+8.29578 8.81161
+6.24793 6.32368
+4.07212 4.39695
+5.32453 7.457
+8.3892 9.82048
+4.35981 4.78063
+5.49932 6.08321
+1.0107 1.53369
+2.48759 2.94139
+4.24977 5.52034
+1.93104 3.35207
+-0.733247 1.22412
+-0.354283 2.36812
+6.34728 6.44213
+5.98172 7.8753
+5.47963 6.82986
+6.01986 6.6588
+4.62793 5.22134
+7.73923 8.29761
+8.85565 9.51494
+5.55307 6.15804
+6.30963 7.17248
+9.4775 10.2636
+7.45333 7.74006
+1.79317 2.33273
+7.73056 8.44999
+3.94172 5.02778
+8.36177 9.85172
+5.91765 8.12935
+7.95436 8.97583
+5.06238 5.37907
+4.56153 4.97175
+9.47572 9.65038
+9.54745 9.922
+7.82271 8.66299
+4.19056 4.75156
+4.15657 5.72352
+0.213845 0.312444
+2.30944 2.6806
+2.42391 3.41888
+6.00512 6.88274
+6.64546 7.61145
+-0.204229 2.78228
+-0.417104 0.667252
+8.18696 8.67785
+9.27818 9.67924
+-0.0174685 0.21355
+5.91137 6.39606
+9.49268 10.1457
+2.11362 4.36526
+6.51084 7.82167
+6.07066 6.44843
+-0.653518 1.08588
+7.46736 7.87137
+5.26045 7.92188
+6.4171 6.8133
+6.73709 7.70383
+3.46451 4.23679
+0.122365 0.809853
+7.98627 8.0505
+1.71192 2.63047
+1.20624 2.12087
+4.6812 5.51566
+2.62672 2.67648
+4.203 5.1052
+5.26482 6.5186
+3.68166 3.74701
+2.72011 3.98338
+3.41652 3.71477
+2.26211 2.90374
+0.930209 1.43211
+1.98603 3.36662
+4.55838 5.9933
+5.66292 6.59838
+3.12432 3.87457
+6.54384 8.38959
+0.205059 0.331022
+8.70617 9.34121
+7.02182 7.38679
+2.36908 2.84197
+9.13221 9.76563
+7.50113 9.49245
+8.15671 8.45093
+1.9517 2.20923
+3.23368 3.43695
+2.97273 4.10133
+7.36338 8.96733
+4.77525 5.18347
+9.47774 10.3537
+1.75218 1.97051
+5.42544 6.18939
+9.75801 10.0151
+6.31285 6.38327
+8.43389 8.721
+7.6108 7.81113
+8.72029 10.3153
+5.18655 7.1101
+7.96243 8.43151
+0.798103 0.860125
+1.1289 2.77549
+5.91084 6.03085
+4.95884 5.46913
+5.88125 6.49667
+7.9394 8.9545
+5.07492 5.55063
+5.92251 6.08548
+3.88602 5.41487
+1.40122 2.15276
+8.74244 8.83223
+4.75577 6.60338
+0.921272 1.44873
+3.77361 3.90348
+8.8999 9.8518
+3.11077 4.85674
+8.56185 10.6345
+8.76335 9.00169
+6.8734 8.60197
+4.54408 4.93892
+5.57849 6.31727
+7.95161 8.30843
+1.55798 2.4957
+3.86082 3.97131
+6.45433 7.17065
+0.96021 2.32897
+6.84576 6.89531
+8.59095 8.70199
+3.57754 4.26457
+5.27979 5.74385
+2.06602 2.90525
+3.0856 4.18179
+2.76214 3.9982
+2.11943 5.4285
+3.1197 3.24389
+0.495798 1.23632
+3.18253 3.99433
+7.02072 8.37949
+2.77905 3.42643
+1.57093 2.30655
+7.10979 7.14006
+6.20994 6.72092
+8.15136 8.33899
diff --git a/bottleneck/tests/data/test_011_B b/bottleneck/tests/data/test_011_B
new file mode 100644
index 0000000..761943d
--- /dev/null
+++ b/bottleneck/tests/data/test_011_B
@@ -0,0 +1,200 @@
+1.17434 1.46837
+2.58198 4.16589
+0.234041 0.968658
+1.52703 1.59579
+6.7103 7.44033
+3.19227 4.41539
+5.42556 5.57369
+3.45417 4.86089
+3.82256 4.1092
+7.82551 7.90784
+3.9384 4.71796
+5.60335 5.9054
+7.96663 9.8987
+6.30305 6.64853
+7.33246 10.5316
+0.623312 1.09008
+2.63041 2.64616
+5.36028 6.28956
+4.64202 5.91858
+7.55219 7.96304
+7.73736 9.18221
+1.67114 1.84851
+5.07514 5.12159
+7.03732 7.05228
+7.5006 7.59212
+0.244947 1.55875
+0.0170454 1.10485
+1.95394 3.53669
+5.66015 6.01949
+5.88211 7.64639
+7.46698 9.27085
+6.37429 7.10154
+4.54535 4.81932
+8.21203 9.35896
+4.89933 6.20802
+3.68683 4.17831
+0.477467 0.828394
+6.17871 6.77834
+9.77523 9.92676
+0.854808 2.38709
+7.93326 8.3553
+2.10917 2.27771
+4.07045 4.72793
+8.2016 8.8011
+2.9205 3.95746
+2.89806 4.39725
+5.5654 5.78669
+9.5219 9.98543
+7.08591 7.19588
+8.35359 9.57893
+9.81348 10.0345
+8.5994 9.71835
+5.43903 7.25234
+1.82768 2.92724
+4.44952 6.79754
+5.66747 7.34386
+5.88153 6.39253
+3.34008 4.22032
+2.46068 2.76051
+0.370778 2.61681
+6.02508 6.26809
+4.32654 4.93262
+7.41536 7.99616
+8.84229 9.87911
+3.8551 5.84353
+1.56832 2.34694
+6.96099 7.42028
+8.15753 8.72014
+9.23141 10.3815
+7.4484 7.80228
+0.473671 0.874895
+3.15689 3.50687
+3.58122 4.09945
+3.55022 3.74767
+4.42708 5.80211
+4.40956 4.68699
+3.80576 4.61856
+7.29965 8.28614
+7.40582 8.15308
+1.69789 1.77669
+1.66419 3.44308
+0.473997 0.872506
+7.83959 8.52898
+6.22416 6.36949
+-0.187159 0.871822
+0.232336 0.585965
+9.29905 9.44357
+1.4459 2.40589
+2.83008 3.19758
+1.15291 2.12112
+2.58686 3.33896
+6.79362 7.88068
+0.228178 1.48318
+5.60001 6.20258
+4.97803 7.10992
+1.70429 1.962
+2.72659 3.13886
+9.22714 9.25889
+3.84694 3.88778
+-0.282077 1.48155
+9.28756 9.58517
+4.34069 5.59751
+8.63909 8.76839
+8.86236 10.7642
+6.77597 8.41888
+7.30621 8.64164
+0.685607 1.22755
+2.91514 3.22638
+2.72098 3.66837
+8.17528 8.32638
+5.19632 5.7506
+7.34177 8.70639
+5.74082 6.35524
+5.95975 6.69284
+9.40187 10.4488
+2.92761 3.36735
+0.399531 3.13082
+4.83399 4.92635
+7.74539 8.56852
+1.76322 3.5086
+6.54479 6.72963
+7.64362 8.12404
+1.35542 1.45313
+0.214385 0.718085
+1.7006 3.21962
+5.91009 6.47862
+2.21093 2.34636
+5.96919 6.79365
+6.59951 8.22203
+1.54571 1.59397
+3.27012 3.79128
+0.32455 0.622995
+1.73926 2.78017
+9.81035 9.84077
+7.38441 7.85171
+8.90372 9.34186
+7.26323 8.41174
+5.7363 5.97348
+8.25473 10.1281
+2.3981 2.52096
+8.53783 9.63442
+8.51755 9.2735
+6.48614 6.773
+3.40182 3.65137
+2.1353 3.04852
+2.95397 3.73285
+6.98063 7.4963
+4.50189 5.26384
+0.21416 1.49363
+0.632196 1.36307
+6.57833 6.60481
+8.0634 9.33903
+2.79759 2.94462
+4.43747 4.58861
+6.48733 6.86569
+2.28008 3.47037
+6.87452 7.77431
+-0.156821 2.71557
+0.72595 1.78862
+1.97586 2.38196
+8.61839 9.1468
+4.55496 5.68986
+0.26923 1.15728
+9.63757 9.7236
+1.39497 1.96698
+4.8643 5.04172
+6.64675 7.66435
+2.56256 2.6015
+-0.381989 0.611211
+0.676336 1.26896
+8.95304 9.03243
+5.62058 6.07997
+3.36522 4.04276
+8.64868 10.5024
+4.75813 5.19834
+1.96608 2.05864
+9.01449 9.10397
+3.72786 4.51921
+5.6938 6.96584
+1.73499 2.9314
+2.73099 3.41409
+8.77171 9.07665
+4.63865 4.67649
+8.6698 9.30782
+-0.168259 2.09581
+9.29672 9.56
+0.372544 2.60567
+0.450487 1.32919
+6.95341 7.6399
+3.4403 5.24993
+5.53469 6.97831
+-0.79664 1.21306
+5.68831 6.14413
+8.85601 8.95444
+3.83309 5.211
+5.51573 6.5114
+3.64009 3.99648
+4.40759 4.99283
+1.85198 2.6457
+2.72645 3.74803
diff --git a/bottleneck/tests/data/test_012_A b/bottleneck/tests/data/test_012_A
new file mode 100644
index 0000000..094c6e0
--- /dev/null
+++ b/bottleneck/tests/data/test_012_A
@@ -0,0 +1,5000 @@
+0.471299 1.89241
+2.82136 3.97846
+8.81923 9.20678
+1.42474 1.65425
+8.36963 9.16097
+-0.236476 0.692489
+7.57182 8.06148
+2.89878 3.21958
+7.1285 7.51707
+5.75496 7.09461
+6.00081 6.10914
+9.60869 9.64676
+7.42889 8.97174
+7.26061 8.55944
+2.41226 2.5146
+8.5616 9.44847
+7.4946 8.86962
+5.42244 6.98028
+9.62386 9.96039
+7.70591 9.92849
+1.34119 3.2048
+3.92169 5.15228
+8.82955 9.60318
+7.94213 9.39997
+2.6716 4.02057
+0.375206 0.497663
+1.94572 3.65599
+1.03366 1.46356
+8.91855 10.1838
+7.11087 8.64425
+2.63266 2.78706
+8.93611 10.2943
+8.51999 9.28356
+1.31436 3.13725
+1.92871 4.00178
+8.30503 8.45555
+2.58739 2.82076
+3.20419 5.29453
+7.4015 8.13225
+9.07991 9.74729
+0.822366 0.938371
+2.90508 4.29367
+4.32385 5.4787
+3.63054 4.6918
+8.52962 9.87004
+1.16994 2.39465
+2.61903 3.33772
+4.15505 4.52942
+8.7068 9.66579
+8.10373 9.31351
+0.7954 1.23001
+7.82253 8.69505
+4.59616 5.91996
+1.02032 1.93931
+6.98421 8.46017
+8.42263 11.3447
+2.63444 3.7158
+7.49059 9.1137
+-0.122109 1.41074
+8.29578 8.81161
+6.24793 6.32368
+4.07212 4.39695
+5.32453 7.457
+8.3892 9.82048
+4.35981 4.78063
+5.49932 6.08321
+1.0107 1.53369
+2.48759 2.94139
+4.24977 5.52034
+1.93104 3.35207
+-0.733247 1.22412
+-0.354283 2.36812
+6.34728 6.44213
+5.98172 7.8753
+5.47963 6.82986
+6.01986 6.6588
+4.62793 5.22134
+7.73923 8.29761
+8.85565 9.51494
+5.55307 6.15804
+6.30963 7.17248
+9.4775 10.2636
+7.45333 7.74006
+1.79317 2.33273
+7.73056 8.44999
+3.94172 5.02778
+8.36177 9.85172
+5.91765 8.12935
+7.95436 8.97583
+5.06238 5.37907
+4.56153 4.97175
+9.47572 9.65038
+9.54745 9.922
+7.82271 8.66299
+4.19056 4.75156
+4.15657 5.72352
+0.213845 0.312444
+2.30944 2.6806
+2.42391 3.41888
+6.00512 6.88274
+6.64546 7.61145
+-0.204229 2.78228
+-0.417104 0.667252
+8.18696 8.67785
+9.27818 9.67924
+-0.0174685 0.21355
+5.91137 6.39606
+9.49268 10.1457
+2.11362 4.36526
+6.51084 7.82167
+6.07066 6.44843
+-0.653518 1.08588
+7.46736 7.87137
+5.26045 7.92188
+6.4171 6.8133
+6.73709 7.70383
+3.46451 4.23679
+0.122365 0.809853
+7.98627 8.0505
+1.71192 2.63047
+1.20624 2.12087
+4.6812 5.51566
+2.62672 2.67648
+4.203 5.1052
+5.26482 6.5186
+3.68166 3.74701
+2.72011 3.98338
+3.41652 3.71477
+2.26211 2.90374
+0.930209 1.43211
+1.98603 3.36662
+4.55838 5.9933
+5.66292 6.59838
+3.12432 3.87457
+6.54384 8.38959
+0.205059 0.331022
+8.70617 9.34121
+7.02182 7.38679
+2.36908 2.84197
+9.13221 9.76563
+7.50113 9.49245
+8.15671 8.45093
+1.9517 2.20923
+3.23368 3.43695
+2.97273 4.10133
+7.36338 8.96733
+4.77525 5.18347
+9.47774 10.3537
+1.75218 1.97051
+5.42544 6.18939
+9.75801 10.0151
+6.31285 6.38327
+8.43389 8.721
+7.6108 7.81113
+8.72029 10.3153
+5.18655 7.1101
+7.96243 8.43151
+0.798103 0.860125
+1.1289 2.77549
+5.91084 6.03085
+4.95884 5.46913
+5.88125 6.49667
+7.9394 8.9545
+5.07492 5.55063
+5.92251 6.08548
+3.88602 5.41487
+1.40122 2.15276
+8.74244 8.83223
+4.75577 6.60338
+0.921272 1.44873
+3.77361 3.90348
+8.8999 9.8518
+3.11077 4.85674
+8.56185 10.6345
+8.76335 9.00169
+6.8734 8.60197
+4.54408 4.93892
+5.57849 6.31727
+7.95161 8.30843
+1.55798 2.4957
+3.86082 3.97131
+6.45433 7.17065
+0.96021 2.32897
+6.84576 6.89531
+8.59095 8.70199
+3.57754 4.26457
+5.27979 5.74385
+2.06602 2.90525
+3.0856 4.18179
+2.76214 3.9982
+2.11943 5.4285
+3.1197 3.24389
+0.495798 1.23632
+3.18253 3.99433
+7.02072 8.37949
+2.77905 3.42643
+1.57093 2.30655
+7.10979 7.14006
+6.20994 6.72092
+8.15136 8.33899
+0.903753 1.57921
+0.380744 1.88053
+1.3164 1.79885
+0.199366 0.576639
+5.53683 6.49433
+8.8705 9.14396
+3.1401 3.98761
+4.82675 6.69396
+7.28593 8.08916
+8.11312 9.92914
+3.25737 3.42109
+2.58413 4.57223
+2.65202 2.77196
+-0.31616 1.51568
+4.1621 5.29563
+4.49155 5.21037
+7.28481 7.31722
+9.70568 10.0406
+2.39057 2.85874
+2.30626 3.16244
+1.15896 2.09616
+5.91343 7.33024
+-0.172181 0.177363
+5.08934 6.10928
+7.15508 7.55315
+4.43036 4.68093
+6.00772 6.49566
+7.9247 8.43809
+1.57028 2.52328
+3.45458 4.43692
+3.18257 4.83824
+1.48243 1.91225
+2.59025 2.99596
+6.93059 8.34359
+4.53752 7.51216
+6.42857 6.51513
+5.5663 6.13877
+7.54367 7.56485
+9.01229 9.19913
+2.84158 3.23347
+0.42959 0.620618
+8.77033 9.33787
+8.06103 8.30989
+6.48425 7.83668
+4.66949 6.00205
+4.46683 4.66247
+8.96738 9.07714
+0.463093 0.514808
+7.72986 9.44537
+6.31391 6.8289
+0.883295 1.70946
+3.73278 3.98015
+6.73453 6.92514
+3.58434 4.43262
+0.236286 1.4601
+2.00505 2.38684
+3.845 4.20708
+1.18852 3.04911
+0.766784 1.00641
+7.38781 8.11216
+8.9396 9.27589
+0.369822 1.53322
+8.76527 9.23987
+0.663408 0.803445
+9.69209 10.1455
+9.73379 10.234
+3.47602 4.89968
+4.12754 5.45249
+7.31984 8.57369
+0.989101 1.47678
+5.57662 5.83292
+4.99092 6.85044
+4.35272 4.3683
+0.0517815 1.92227
+7.2694 7.80634
+1.35565 1.42783
+8.5638 8.91707
+1.74557 2.74123
+2.18226 2.19664
+-0.901334 1.32691
+0.866613 1.03788
+5.30895 6.31774
+7.70178 8.5675
+4.06894 4.16071
+2.59697 3.53162
+4.30201 5.34212
+4.08762 4.19091
+-0.516192 0.848397
+9.85911 10.1066
+0.472991 1.40069
+6.26012 7.0054
+0.707801 2.15445
+1.73825 1.87193
+0.206301 0.831746
+7.77872 7.92715
+4.94477 5.60361
+3.86216 5.16839
+1.35166 1.54482
+2.91721 3.56193
+4.57242 4.75913
+7.09303 8.29678
+8.18431 8.92151
+6.80303 10.87
+1.29208 1.72027
+1.22224 1.31693
+5.26756 6.26459
+2.55221 3.94397
+6.58902 6.78354
+7.85917 8.89791
+6.59279 7.63115
+4.45787 7.26828
+3.48759 5.33991
+2.13838 3.86589
+1.53368 3.57313
+1.41722 3.19336
+3.48388 4.11958
+1.53756 2.98451
+7.29083 8.22109
+1.2713 2.16915
+6.94685 7.31029
+6.2494 7.04676
+3.00376 3.02028
+1.25232 1.43301
+1.50413 2.25
+2.89098 4.77198
+4.50766 5.89294
+5.5403 6.07893
+-0.101858 0.409209
+3.87963 6.1053
+-0.19564 1.46589
+-0.342077 0.694623
+6.63875 7.42223
+7.89982 9.05857
+4.91121 5.48031
+5.90743 8.35815
+7.13881 8.21597
+4.11493 5.08147
+3.59673 3.77176
+8.08236 8.3237
+1.35842 1.48934
+5.42963 5.85906
+4.60778 4.9734
+-0.607198 0.91225
+5.40263 5.7017
+5.08624 5.63236
+7.34529 9.02233
+7.30013 8.12907
+6.56106 6.75585
+6.82576 7.25434
+2.96037 3.56454
+3.60283 4.09137
+6.35408 6.71888
+-0.688103 0.84579
+8.45128 8.69771
+6.31749 7.3294
+5.82223 6.04761
+1.72983 2.38205
+6.94974 7.76985
+9.681 10.0141
+8.65394 9.2456
+2.52904 3.39548
+6.66609 7.35785
+4.18963 4.5473
+3.58643 3.80513
+2.88796 3.82413
+0.992066 1.1477
+4.57942 5.15419
+3.02826 4.32268
+5.91565 6.82087
+4.13694 5.13393
+6.28717 6.53257
+1.3149 2.36944
+0.488974 0.981461
+4.32763 4.98272
+-0.420836 0.63619
+7.13406 7.31362
+0.367782 1.91138
+6.14763 6.16713
+0.837933 1.92794
+9.3781 10.0609
+3.22887 5.44584
+5.91554 6.65974
+5.68608 6.02435
+7.99715 8.55953
+5.37106 5.38574
+0.254544 0.374268
+0.184701 0.917061
+9.38005 9.54042
+6.86741 7.35628
+0.87398 1.69093
+7.75845 8.53773
+0.370425 1.35335
+0.699837 0.810893
+3.73223 4.32089
+3.81804 3.85752
+4.85936 5.10097
+2.70381 3.10519
+3.82523 5.27699
+9.13422 10.3317
+4.62775 4.77988
+7.91139 7.95504
+2.72614 4.79958
+0.863357 1.88643
+4.14155 5.02327
+2.49683 4.11585
+1.06741 1.11516
+6.20979 8.38443
+0.936362 2.46703
+6.58231 7.85063
+1.89469 2.31422
+8.70668 9.14006
+5.76486 6.1122
+3.15778 3.76679
+0.248282 2.19881
+1.25317 1.92694
+7.81837 9.53067
+-0.582906 0.818904
+8.34194 8.37845
+4.4913 5.10164
+3.86376 5.5453
+6.94054 7.68699
+2.07462 2.5811
+0.518698 2.1529
+3.51773 4.60946
+8.39915 8.98446
+1.63685 2.19755
+6.60737 9.05917
+2.06667 3.23994
+3.18822 3.31219
+2.44332 3.22088
+4.755 4.87118
+4.34245 4.91565
+4.64562 4.8104
+2.73282 3.35646
+9.48057 9.86441
+0.640899 1.03356
+0.789475 0.925731
+1.4247 1.58347
+1.47747 2.25408
+8.8612 9.81597
+8.44147 10.6885
+9.07046 10.0877
+0.350125 1.15765
+4.45375 5.73964
+4.06526 4.26457
+7.50776 8.23491
+1.55452 1.63786
+2.8399 4.52559
+1.34319 1.47951
+5.21572 5.65702
+5.85695 6.75574
+8.21826 10.657
+-0.0479956 1.79162
+1.72905 1.78113
+3.35685 4.03797
+3.7123 5.82296
+8.56751 10.2992
+4.07987 4.25273
+5.8347 6.07253
+3.25283 3.99065
+9.31995 10.3647
+0.649025 1.14496
+1.06966 2.04182
+7.59831 7.85826
+3.35263 3.84374
+4.91371 5.10148
+8.0875 9.23421
+3.00484 5.14282
+8.60448 9.09442
+5.61429 6.24037
+3.4729 4.17907
+7.18702 7.26274
+0.729966 0.928899
+2.27264 2.81241
+2.67248 3.91661
+3.98443 4.64406
+5.50463 6.92435
+-0.257961 0.905736
+5.71363 6.67387
+4.12643 4.66467
+3.97623 4.64917
+9.71227 9.8243
+8.66674 8.97634
+7.94673 8.73904
+7.45228 8.14466
+3.78405 4.81189
+4.05505 5.00011
+2.84957 3.15451
+6.93785 7.58172
+1.85006 1.96814
+6.82256 7.00166
+2.42727 2.68161
+8.06129 8.76308
+1.53758 3.67482
+2.5057 4.18495
+7.09618 7.79664
+1.12843 1.46228
+1.61447 2.2668
+5.58639 5.70776
+8.15398 8.34959
+2.49733 2.57643
+5.18817 5.32462
+5.62963 5.86377
+1.95215 2.26641
+7.22129 7.23255
+5.99833 6.18639
+6.20875 7.13868
+6.814 7.6597
+7.41314 9.49798
+5.48819 6.31634
+4.81318 5.08156
+9.15434 9.42787
+4.83201 5.43295
+1.44477 2.6455
+8.8907 10.4727
+3.19487 3.21255
+1.47291 3.13113
+4.14796 5.10058
+5.85016 8.41212
+7.58183 8.53659
+9.5978 10.2877
+1.5954 2.58394
+2.65561 4.0975
+-0.157024 0.16627
+7.04379 7.75368
+2.39896 2.7728
+2.42376 3.58085
+0.158653 0.857045
+7.82101 9.01833
+6.80499 7.35261
+6.62833 6.66255
+4.90229 5.45681
+8.50205 8.69236
+2.01845 2.06924
+8.2503 9.04222
+4.58265 5.52758
+8.6176 9.74887
+1.28468 1.77019
+5.40424 6.20705
+0.943905 1.98023
+4.2702 4.41287
+3.89454 4.4814
+0.585132 1.56351
+9.45354 10.5374
+3.7501 5.07553
+7.53248 8.14004
+4.60026 4.78921
+1.61073 4.22368
+6.22591 7.40966
+0.57866 1.0522
+5.877 6.55882
+3.54573 3.7731
+7.64294 7.66103
+8.2399 9.14032
+0.307808 0.571367
+7.89791 9.25734
+5.2852 5.84332
+0.45713 2.42223
+7.73426 8.48158
+8.0058 9.46405
+8.03189 8.41868
+1.54624 1.98914
+7.24167 7.27699
+8.61226 8.83199
+5.38365 6.52599
+0.827018 1.51428
+7.19285 7.48372
+-0.0969552 2.16007
+4.08084 6.32563
+9.16026 10.2604
+0.206147 0.717435
+4.00643 4.8093
+2.16139 3.14759
+1.73359 3.13485
+9.1103 9.36052
+7.05621 7.43901
+4.83509 6.07581
+5.67164 7.89488
+7.93353 8.18454
+2.59566 3.1842
+3.62521 4.95121
+3.0297 3.18649
+1.08515 2.69289
+3.77063 5.7789
+0.106035 1.27409
+0.601099 2.13481
+6.98837 7.58833
+9.22955 9.79149
+1.6398 1.78726
+2.30423 3.34814
+2.3912 2.81842
+4.71724 6.16966
+5.13553 5.5016
+5.34117 5.45075
+9.32776 10.0676
+4.54244 5.29058
+4.01337 5.73188
+8.17427 8.39652
+1.96122 2.6921
+0.594267 1.00176
+-0.136973 0.977133
+6.41362 6.78056
+1.68388 2.39891
+9.50795 10.2315
+-0.262703 1.15557
+8.72229 9.683
+5.41821 5.67519
+4.93514 7.15867
+4.07046 4.26702
+-0.00866106 0.252353
+8.65877 10.1527
+2.10958 3.40353
+2.94947 3.43201
+6.32014 7.06279
+2.55034 2.89646
+3.87777 5.68044
+2.05325 3.00968
+5.11855 6.55784
+8.99618 9.22608
+3.36303 3.84902
+2.6234 3.70832
+7.35189 8.30856
+6.43777 7.28495
+5.33954 5.48055
+0.15999 0.391114
+3.4492 5.07088
+2.38503 2.42742
+3.88912 4.93246
+2.76303 4.54991
+6.56261 7.60381
+3.64198 3.72471
+1.70542 1.78806
+9.71115 9.88315
+0.471586 1.82377
+9.27611 10.5725
+0.486889 0.851587
+4.39234 5.10637
+9.54209 9.8955
+6.99602 7.42461
+2.98797 3.74623
+5.89424 6.4498
+9.63845 9.86333
+4.39828 5.18646
+2.30118 3.5758
+8.68128 9.56011
+9.00505 10.4304
+-0.22184 0.233296
+6.48492 7.60283
+1.54156 2.60693
+4.06808 6.39369
+5.52361 6.26241
+-0.698727 0.745524
+2.30742 2.41924
+0.655833 1.65752
+6.94733 7.81866
+7.83136 9.10651
+6.45284 7.1931
+6.09683 6.66159
+9.03299 9.4163
+1.86392 3.26189
+0.54863 2.07194
+0.364026 1.38376
+0.706954 1.0736
+-0.111015 0.584367
+1.54265 2.1413
+0.501172 0.57928
+2.09411 2.28902
+1.89894 4.09104
+8.72895 8.87045
+5.27709 5.72545
+0.164581 1.64188
+8.39203 8.73608
+8.21523 8.45002
+9.62006 10.1665
+4.79076 6.26442
+3.44189 3.68669
+8.93789 9.38343
+7.07036 7.64194
+8.34396 9.56445
+8.29992 8.64954
+5.82566 7.83287
+2.43008 3.4476
+1.81121 2.12203
+4.36108 4.3842
+6.28756 6.95939
+3.8698 5.79519
+0.644581 0.699162
+9.71982 10.2422
+4.86545 5.00544
+8.3808 9.29356
+1.34495 1.40972
+1.03641 2.01838
+8.55609 9.99958
+1.40813 3.46097
+3.20928 4.08838
+8.24345 9.11587
+1.27604 2.03462
+8.28298 8.46252
+2.20644 3.19585
+1.91396 2.30108
+4.2553 5.66006
+7.34925 8.38275
+6.28319 7.22199
+8.42171 9.62596
+1.12059 1.18262
+1.37555 1.84196
+4.39663 4.93639
+9.28044 9.58437
+5.47407 6.88593
+8.36529 8.49813
+9.40208 10.5922
+-0.451389 1.92404
+2.89431 3.19453
+6.51433 8.02158
+5.52163 6.06786
+7.63525 9.86457
+4.13898 5.05845
+0.136662 0.503748
+6.13492 6.74997
+8.37416 9.18971
+8.64164 8.82663
+0.941173 1.16158
+6.9073 8.26916
+8.37278 8.44326
+8.8951 9.20427
+8.40149 9.17577
+3.60361 4.57183
+8.67263 10.1127
+5.89716 6.45412
+1.97285 2.35593
+7.22973 8.13467
+9.55645 9.92529
+0.261578 0.836274
+9.04414 9.45485
+6.18043 6.54229
+8.88579 9.54087
+1.82613 2.93849
+5.7599 5.96366
+5.23105 5.5541
+0.425229 1.44436
+0.32065 2.60892
+7.83655 9.48786
+2.3168 3.45972
+2.35466 3.23342
+8.24494 8.27258
+7.32678 7.74264
+8.37275 10.0741
+4.17337 4.98348
+-0.162009 0.724431
+9.49757 9.76377
+8.69435 9.08089
+4.13841 4.7514
+7.26358 7.55514
+6.91912 6.93
+6.7883 7.18296
+-0.614315 1.1857
+6.05907 7.33557
+4.86704 4.87705
+8.50012 9.14836
+1.83683 3.09895
+6.16389 8.39248
+3.03556 4.41004
+4.72416 5.05782
+1.98183 3.19183
+2.77103 5.71501
+4.90002 4.9817
+0.269258 0.725628
+5.59551 7.05038
+2.95416 3.09633
+2.17662 3.18385
+6.67536 7.56762
+7.31678 7.39321
+3.84158 3.85359
+4.38203 5.10149
+0.816784 1.09918
+0.70131 0.739502
+0.276631 2.32633
+9.15839 9.49433
+0.721295 1.97673
+2.63875 2.75437
+5.00344 5.5645
+2.24555 2.81234
+7.74465 9.07646
+2.35244 4.90632
+0.812093 0.954419
+3.97904 5.2071
+4.19177 4.83646
+0.853012 1.331
+2.64112 3.25613
+0.0894716 1.61954
+3.39617 3.40859
+1.56906 2.28518
+2.37258 4.36515
+1.60997 1.7561
+5.15275 5.33281
+6.47824 7.47529
+2.51145 3.29949
+2.71094 2.77785
+8.84653 9.48398
+1.3246 1.66664
+7.43718 7.5546
+3.68985 4.24649
+4.50553 4.51669
+4.15617 4.54887
+8.55319 10.2136
+2.1448 3.55805
+4.64594 4.71505
+1.71763 1.99977
+4.98066 5.46709
+7.7779 8.36497
+-0.0604997 0.301294
+5.11873 7.32867
+4.94567 5.5986
+5.32645 6.26835
+2.5768 3.13511
+3.31604 3.87555
+1.60834 2.68762
+3.30552 3.85211
+4.26741 4.98636
+0.820475 1.18854
+7.91501 10.7203
+5.17391 5.30351
+4.00452 5.75141
+2.37722 3.4602
+2.2373 2.94837
+1.62462 3.48264
+7.98507 9.2566
+5.32504 5.56388
+0.760614 0.7802
+0.855659 1.01522
+3.11231 4.43223
+5.62821 6.21564
+4.96845 5.35921
+8.10559 9.11106
+1.02533 1.13103
+6.99976 7.0788
+1.87628 2.58801
+1.11023 2.24655
+5.23343 5.45086
+0.95875 2.25343
+7.45917 8.23614
+2.72245 3.04663
+8.66816 8.70698
+5.55734 7.12262
+1.01935 1.88271
+0.804417 1.76187
+7.82703 8.78426
+4.77321 6.15199
+2.91503 3.69352
+0.776735 1.08883
+5.19981 5.46442
+9.06483 10.4008
+7.72082 8.26398
+2.9854 3.26573
+0.584028 2.60443
+0.700994 1.10379
+5.47612 5.94502
+-0.318442 0.986786
+5.0704 5.08055
+3.83732 4.4826
+5.60843 6.59005
+8.81432 9.7851
+6.28792 6.65284
+1.16812 2.27701
+7.15234 9.66795
+9.02188 9.15339
+1.76112 2.04839
+7.49419 7.6204
+5.1765 5.497
+1.45855 1.94969
+1.35003 1.55822
+2.50453 2.86815
+7.10451 8.51352
+3.87727 4.1124
+1.84876 2.79351
+3.01661 4.05396
+-0.16814 0.366484
+-0.538895 0.608786
+7.59933 9.00744
+0.938648 2.38471
+5.76934 6.16572
+8.20416 8.62505
+8.64542 8.7264
+2.75784 2.7828
+0.794451 1.97817
+9.21331 10.5156
+8.46671 8.80572
+3.94814 5.16845
+6.73654 6.97397
+4.05301 4.93008
+6.37833 6.77985
+7.21161 8.15994
+3.74993 4.61029
+-0.127938 1.09853
+2.82957 4.28816
+6.50564 6.59445
+8.37926 8.48332
+0.757443 1.74585
+0.232438 0.972293
+6.99187 8.7098
+7.20368 8.44301
+4.4801 6.07501
+4.34015 6.1495
+2.19394 3.22334
+7.29817 8.41021
+1.16627 2.68901
+4.62423 5.08039
+0.955655 2.22882
+1.45862 3.07065
+1.69815 2.56291
+4.01179 4.36587
+7.135 7.75829
+6.6823 7.27765
+5.44745 5.67195
+4.94594 5.42067
+0.267772 0.301939
+0.676432 1.6296
+1.37335 1.91645
+1.89051 2.38631
+4.84386 6.30539
+8.95613 10.944
+2.18119 2.41821
+5.74901 6.16952
+7.5431 7.88071
+9.05278 9.8128
+0.201334 1.65323
+2.82787 3.82083
+3.07073 3.08475
+8.99671 10.1766
+5.43261 6.12137
+4.83693 4.86848
+6.31804 7.21544
+2.34491 3.2562
+6.05941 6.53725
+-0.483381 1.17347
+5.53777 5.72651
+3.28875 3.47472
+3.94609 4.9418
+7.45585 8.6871
+1.50066 2.57215
+8.10112 8.67954
+6.24737 6.42635
+0.64413 1.05759
+7.1741 8.21476
+0.502722 1.77462
+0.783663 1.74174
+9.52704 9.9109
+-0.473873 2.01013
+7.07946 7.11474
+0.857335 1.6501
+4.00225 4.84453
+5.40598 6.30573
+8.18802 8.30067
+9.00412 10.9588
+9.8362 10.1517
+7.62735 8.37572
+3.41477 4.63099
+2.51254 2.81559
+6.36702 6.56061
+5.11842 5.35515
+5.21873 5.73296
+5.73528 7.77276
+3.64993 4.66826
+7.12664 8.46553
+8.7257 9.16851
+1.27615 2.20376
+7.46188 8.20752
+2.64939 2.66373
+4.94147 6.0509
+6.3805 7.48841
+6.25197 7.12327
+0.0885331 1.2682
+4.97356 6.58488
+4.11917 4.27267
+9.08793 9.70385
+0.897277 1.31702
+6.87538 8.25544
+1.55565 1.59492
+2.62483 3.54274
+1.49631 2.92263
+9.45305 9.97728
+6.24087 6.4577
+3.94636 5.13669
+-0.000956745 1.08235
+1.46134 1.83767
+9.18517 10.6601
+-0.740186 1.81269
+5.81977 6.15818
+7.0529 7.99421
+6.17753 7.49749
+8.63091 9.04205
+9.65219 10.1558
+3.12839 4.99211
+2.97262 4.07384
+4.28605 4.33171
+4.15906 5.6805
+1.35165 1.50732
+0.524207 2.12307
+5.32468 7.01472
+3.16982 4.87893
+6.88786 8.34191
+3.81703 5.22335
+3.86772 4.37359
+8.19386 10.0705
+1.73155 3.16695
+4.31685 4.62261
+9.40618 9.89612
+4.41215 5.19659
+2.35595 2.63543
+7.88481 8.14203
+7.17062 10.3534
+9.41379 10.389
+7.99867 9.01239
+3.31382 4.04915
+5.39222 6.07657
+8.5187 8.65976
+9.30132 10.6131
+7.17351 7.93596
+4.80134 6.72724
+3.59756 4.65182
+1.08248 1.17479
+1.03124 1.06871
+6.43154 6.95098
+-0.102199 0.59801
+4.94795 5.18081
+6.39126 7.30258
+1.52738 2.04271
+1.80373 2.33093
+2.72251 3.01677
+0.296722 1.10844
+6.39104 6.51567
+8.70965 8.78714
+2.07858 4.41695
+1.91027 2.9718
+1.42944 2.01864
+1.96347 2.73397
+4.0701 4.22456
+4.02859 4.05107
+7.10977 7.98092
+8.21148 9.54287
+6.59231 7.65109
+0.144191 0.830665
+2.0192 2.23704
+8.03482 8.39591
+8.90473 9.98543
+2.18284 2.70166
+3.05569 3.54238
+8.35319 9.39539
+2.00803 2.42866
+2.35282 3.13763
+2.20155 2.79377
+1.76531 2.94892
+7.52749 7.72567
+3.02266 3.24778
+4.01741 4.22521
+9.75263 9.91571
+6.45502 6.67838
+2.24912 3.47262
+1.84372 2.26517
+4.09559 5.71188
+1.43811 2.33732
+3.89171 4.16905
+3.01506 3.9725
+0.0273168 1.51766
+5.04118 5.80507
+3.08517 4.17316
+8.81637 8.8332
+8.74055 9.50143
+2.36904 2.69008
+6.39733 6.44221
+8.53272 9.51114
+9.48423 9.55002
+8.65645 9.04872
+6.66352 7.48009
+5.64389 7.88656
+5.75301 6.6759
+3.28645 4.22757
+4.99482 5.82988
+3.00004 4.0273
+1.45249 1.56662
+4.96263 5.32195
+7.91351 8.1437
+1.02034 1.56249
+0.71376 1.73319
+0.709968 1.44651
+9.01414 9.54799
+4.02116 4.68005
+7.10903 7.27075
+7.21322 8.71031
+1.6644 2.27186
+3.71304 4.68764
+9.66257 10.1452
+5.34477 5.46136
+9.27722 10.583
+3.82328 4.83316
+4.77019 5.07928
+9.07112 9.23836
+6.99091 7.25634
+2.11871 2.3054
+7.88242 7.98572
+0.570809 0.714073
+8.51532 9.49151
+0.329247 2.48897
+4.78202 5.36476
+1.47969 2.78867
+6.75011 7.36769
+2.31162 2.39533
+3.50434 4.48026
+5.84603 6.28861
+7.5337 7.62538
+1.09955 2.85741
+6.09915 7.20381
+0.933825 2.37925
+0.576363 2.0182
+3.12126 3.22507
+2.85313 3.02656
+3.25724 3.92077
+5.48575 6.58011
+1.02824 1.65415
+8.68703 9.06219
+3.28389 3.86349
+5.80264 6.12775
+7.11846 7.47444
+1.29638 3.38601
+6.37908 7.05986
+-0.592438 0.854361
+0.39233 1.17768
+2.1497 3.94423
+2.42336 2.43441
+6.94806 8.30626
+0.79865 1.4173
+1.41455 1.43684
+0.240074 1.16712
+4.18593 5.9929
+6.161 6.564
+0.726091 1.90706
+0.375606 0.694866
+4.09349 4.26452
+2.01652 2.68038
+8.99301 9.90549
+8.93909 9.17673
+1.10427 2.01247
+9.12668 9.15282
+1.08098 1.55374
+0.377836 0.414809
+7.28611 8.86318
+8.3542 8.53251
+3.86353 4.12875
+6.7631 7.40068
+4.61679 4.78182
+2.12935 3.45492
+3.68233 4.0457
+6.68131 8.22111
+8.79197 8.80474
+1.8915 2.26287
+0.387586 3.073
+6.46798 7.57381
+7.79742 9.34526
+-1.21538 1.67303
+2.07845 2.66028
+3.14148 4.46647
+1.66789 2.73375
+8.49821 10.0574
+8.42537 8.89906
+0.618349 2.72887
+6.8229 7.54501
+6.99343 7.35322
+7.34223 8.68781
+3.18834 3.98274
+8.86908 10.2535
+3.39839 3.76171
+0.188168 0.392276
+1.68187 3.53401
+6.50423 6.71714
+7.61191 8.89715
+1.68463 2.09275
+5.94627 7.6003
+2.15865 3.24126
+7.93639 8.53826
+2.99626 3.43273
+7.71028 8.41172
+3.19472 4.60878
+8.36123 8.92549
+8.92975 9.02783
+2.87187 3.49672
+6.76949 7.71139
+8.09121 9.31151
+6.84199 7.44009
+0.730655 0.800873
+7.5208 7.54109
+6.75992 7.55017
+6.09818 6.17399
+0.639209 1.27283
+3.01917 3.22327
+1.69181 2.60614
+9.49245 9.5842
+-0.418034 1.08035
+5.77705 6.4705
+6.79362 8.51993
+9.73155 9.81609
+3.71503 3.92022
+6.18589 6.77634
+3.94124 4.23942
+7.59911 8.05275
+3.68865 5.10948
+7.63926 8.63019
+-0.049855 0.0844425
+-0.41188 0.807786
+1.35962 1.81039
+5.40579 6.15098
+1.38594 2.0059
+6.93444 8.71958
+7.01229 9.38008
+-0.0974976 0.962679
+4.74131 6.59152
+1.02343 1.59245
+1.55629 1.9128
+6.28353 8.38021
+5.66349 5.79644
+1.72629 2.28563
+1.64539 2.82654
+0.359466 1.05106
+4.37569 4.82703
+5.87657 6.37853
+1.46316 1.65333
+7.44494 7.5985
+1.16846 1.98579
+4.43371 4.93234
+2.31838 2.47777
+7.52687 8.44423
+6.08056 7.42253
+9.16144 9.94783
+4.74382 4.95616
+0.248344 1.05335
+6.12345 7.43941
+9.45647 9.99799
+3.77124 4.75199
+3.31315 3.44873
+-0.0909828 1.51271
+7.03234 8.02546
+8.11403 9.11461
+6.734 7.34799
+1.08903 1.18319
+2.72871 4.31607
+6.53688 7.52754
+1.07868 1.27792
+6.28409 6.56795
+4.89866 5.79458
+9.06994 9.1221
+2.54989 3.14338
+3.69971 5.71717
+3.7113 4.55076
+8.91864 9.64522
+8.75634 8.82359
+9.02242 9.03869
+3.59945 4.20169
+4.98557 5.07401
+4.81526 5.74009
+7.264 8.63749
+2.79579 4.43389
+2.87204 4.66432
+2.32487 3.72127
+3.99704 4.72567
+8.17229 9.0158
+-0.72926 0.823658
+2.52355 3.32725
+5.3446 6.63868
+4.48935 7.37833
+3.08173 3.0968
+2.41585 3.23026
+9.23187 10.5413
+5.50099 5.51888
+1.29634 1.88846
+-0.0113225 1.41526
+6.34508 7.53417
+0.383019 2.25144
+5.0649 5.40222
+3.08221 3.76296
+9.29111 10.6833
+2.19714 2.94735
+8.75711 9.48583
+8.61564 8.69349
+1.9362 3.96191
+3.7962 4.44382
+7.78501 9.03843
+5.79649 7.29675
+6.03048 7.4316
+1.31105 4.36446
+6.5882 7.03622
+4.88148 7.12474
+6.62305 6.90973
+2.27488 2.73731
+8.42703 9.28888
+7.72928 8.53989
+7.27021 8.63879
+0.992908 1.92001
+-0.282737 0.511292
+7.88963 8.03117
+6.93371 8.26148
+-0.0346633 0.403617
+8.7827 8.82558
+5.16876 5.59742
+8.61275 8.73843
+5.70578 6.02783
+9.08706 9.35903
+9.32728 9.83021
+9.20058 10.2497
+6.79824 7.3024
+7.17979 7.51783
+0.918555 2.67878
+7.9662 8.63241
+8.85903 10.3145
+9.34614 10.1964
+9.05027 9.79872
+8.28959 8.45837
+1.32518 2.04557
+8.72848 9.16742
+5.92126 6.77277
+8.31504 8.78631
+1.02487 1.70172
+4.45204 4.72842
+8.20636 10.4724
+5.86211 6.25457
+6.15754 7.71303
+8.37832 8.82577
+4.25233 4.59417
+9.41451 9.95324
+9.372 10.4461
+1.8346 2.7144
+8.00681 8.14717
+7.03997 7.06753
+7.16892 7.70102
+7.01781 7.46799
+1.78526 1.7969
+1.63304 2.2011
+8.59718 8.61083
+9.43498 10.3636
+4.98718 5.32487
+3.65451 4.89601
+8.82368 9.11333
+-0.104862 0.598773
+4.97756 5.62342
+1.99876 3.24686
+2.32242 4.01096
+4.04914 4.77892
+3.81545 4.32583
+3.30153 3.46783
+3.14287 4.04718
+8.65711 8.76768
+9.09385 10.6898
+4.82771 5.64405
+5.98783 6.36785
+7.93397 9.6543
+4.89726 5.65486
+5.08717 5.22314
+6.59377 7.23748
+3.58289 3.98597
+0.177884 0.397629
+5.30856 5.79257
+2.53943 3.98007
+6.51217 6.59644
+0.196888 1.99904
+3.8709 4.1901
+2.37646 2.50997
+7.03837 8.13287
+6.8674 6.89535
+0.576964 2.08851
+0.902928 2.86981
+8.59261 9.20279
+5.96621 7.49899
+0.617602 1.83267
+2.29189 2.6361
+4.34207 4.61026
+6.19963 6.76443
+1.15955 1.44068
+5.25852 6.33905
+6.37306 7.53103
+9.13334 10.039
+8.67743 9.93959
+5.62973 6.04375
+8.32286 8.77042
+3.28772 6.1722
+4.97902 5.47249
+3.37765 5.07238
+4.58025 4.84341
+2.76807 3.18817
+4.27581 4.43023
+6.92572 7.68461
+0.279247 1.0561
+1.10903 2.61106
+6.71708 6.73132
+2.66415 3.75702
+8.0513 9.80334
+4.82466 6.04232
+2.59971 2.85768
+9.04689 9.73945
+3.48338 5.16622
+7.90925 8.92774
+7.30264 8.06247
+7.59087 8.26476
+0.150315 0.423068
+8.62726 9.74636
+9.01983 9.71707
+6.84007 7.40541
+8.87829 9.48342
+2.69214 3.71481
+0.580036 0.77289
+9.474 9.83397
+5.80151 6.08527
+3.63837 5.27137
+8.5848 8.65779
+7.88338 8.13276
+3.27992 4.20963
+6.21244 7.28079
+-0.348924 1.38478
+5.26688 5.93787
+3.78941 5.01009
+6.41929 8.38529
+1.41724 1.67733
+0.212821 1.58246
+0.0697189 0.160497
+9.57839 10.2377
+9.03332 9.70645
+4.94572 5.15163
+3.16999 4.536
+5.77494 6.68359
+5.89258 6.11852
+7.72257 8.21668
+8.42501 8.44905
+8.7196 8.86465
+4.392 5.1076
+1.88249 2.54422
+1.38092 1.60326
+5.04142 6.37374
+4.31795 5.91152
+1.79399 2.09314
+6.65405 8.32262
+1.36356 1.58538
+5.45456 6.55824
+4.95807 6.22848
+8.72077 10.2825
+0.745968 2.01546
+6.85041 7.11076
+4.82028 5.34442
+5.77673 8.01294
+8.58582 9.33714
+8.49884 9.21533
+9.05574 9.4096
+3.19932 3.27024
+9.50227 9.96685
+0.771636 1.0617
+9.00621 9.36397
+-0.097167 1.39463
+7.79622 8.43537
+8.05228 10.1504
+2.21685 4.17072
+1.82476 2.45381
+4.34408 4.56578
+9.27538 9.54701
+6.80153 7.44115
+7.38884 7.84448
+7.17526 8.00165
+5.85812 7.67326
+5.25545 6.30791
+5.68518 5.94055
+3.77685 4.1545
+0.530928 0.737248
+3.9772 4.59563
+8.96322 9.45618
+7.98322 8.44165
+3.42929 4.22329
+3.66445 4.7583
+-0.183652 0.434842
+3.16492 3.95726
+6.87407 7.89944
+5.08921 5.7745
+2.85466 3.04505
+7.12685 7.41248
+0.715419 0.876676
+3.47441 5.21753
+9.13594 9.87799
+5.52459 6.35691
+5.12544 6.12935
+2.44296 2.91543
+2.75148 4.19886
+1.43478 4.3919
+6.6352 7.07768
+4.72283 5.11506
+6.36434 7.69268
+2.32643 2.75289
+5.46566 6.22854
+6.37995 6.76989
+1.52564 3.55871
+1.05807 2.19393
+1.95374 4.08727
+8.11273 8.12767
+2.85955 4.71355
+4.89009 6.88516
+2.06859 2.25512
+7.50556 8.77923
+4.43353 5.11915
+5.16308 5.9695
+1.12072 1.69277
+3.96494 4.38143
+7.06931 7.89524
+0.514522 1.51265
+6.56389 7.01146
+1.51362 1.8541
+4.90339 5.51209
+2.11422 3.15457
+2.50094 3.92557
+8.24319 8.62826
+-0.0843505 0.710377
+6.35956 7.89457
+-0.790954 1.2964
+4.02253 5.19193
+2.7425 3.46763
+9.41469 10.1367
+1.57636 2.25105
+3.18647 3.38738
+8.36644 9.66791
+0.180846 0.461221
+7.07675 7.71881
+0.265366 1.19275
+5.43007 6.4854
+9.13912 9.23294
+9.52905 10.4029
+1.18712 2.66227
+5.22714 5.62601
+1.87413 2.8716
+5.71882 6.16374
+5.38169 6.13948
+-0.196005 0.236738
+5.36803 6.4395
+8.27713 8.71262
+8.82031 8.8598
+-0.53845 0.564783
+1.80716 1.94173
+5.67905 7.47291
+2.37779 3.64893
+0.574727 0.766424
+4.60701 4.86591
+3.17989 4.37738
+1.36777 3.15112
+1.48092 3.06573
+3.37009 4.06028
+4.17179 6.2073
+6.47953 6.88994
+5.74431 6.5253
+4.88827 5.49049
+5.44148 5.59239
+1.66153 2.63132
+7.69387 7.82267
+5.20911 5.48488
+-0.103218 0.497402
+7.18003 7.33324
+6.54305 8.81732
+0.278108 1.27452
+2.38323 2.94772
+1.2461 2.03246
+5.47052 5.75781
+7.31505 7.35895
+2.22248 4.23589
+0.0305319 0.430773
+8.32043 10.1222
+6.11732 7.09764
+5.08797 5.74991
+6.62491 7.34164
+5.55795 5.66083
+3.27549 4.13145
+1.0113 3.24631
+0.0717186 0.519738
+7.82905 9.30839
+9.90251 9.98691
+0.841457 0.952276
+-0.133927 0.510174
+1.14614 2.82218
+2.59767 4.19742
+3.41095 3.95265
+3.38951 3.75838
+8.86766 9.19437
+9.27927 10.261
+2.33249 2.79402
+5.69681 5.93469
+4.02502 5.38732
+0.797157 1.22845
+7.23558 7.8651
+1.1253 1.99184
+8.58296 8.64267
+-0.400141 0.74698
+3.46677 3.50526
+6.03252 6.64842
+5.8493 6.68938
+3.53209 3.84014
+7.22078 8.98106
+6.21943 7.69944
+0.887198 2.07323
+3.36591 4.57442
+4.30143 6.41179
+4.07556 4.54276
+8.77552 10.0615
+6.7247 7.04044
+9.05494 10.1126
+7.46604 7.80632
+3.38601 3.8043
+5.60475 7.02788
+9.09811 9.4654
+9.33447 9.80012
+8.66499 10.1002
+3.87007 3.88281
+2.87624 3.11359
+5.92385 6.80801
+4.49711 5.01863
+8.84524 9.36225
+6.40944 6.82093
+2.90915 3.68288
+3.96801 4.82534
+5.51744 5.84233
+3.2959 3.44409
+0.18526 0.207322
+5.49717 5.72648
+6.9522 7.1952
+0.769572 1.79343
+5.95522 6.03918
+6.54327 7.7475
+2.13516 3.83957
+-0.388892 0.775076
+1.30128 2.29414
+9.76761 10.1604
+7.38731 8.66002
+7.09229 7.43495
+9.1379 9.52432
+6.75942 7.88717
+7.42824 8.82063
+6.93078 8.19884
+2.307 2.93836
+8.38254 8.84691
+3.90159 5.37938
+0.0413204 0.112203
+0.638217 1.53943
+0.88678 2.49435
+1.99104 2.60847
+6.61595 7.65064
+2.37641 4.71719
+7.94945 9.21404
+5.44594 7.13646
+5.45737 6.12335
+7.39207 8.02885
+5.51588 7.39341
+8.1581 10.0632
+0.197869 1.44516
+-0.0161139 0.73487
+4.24155 4.7304
+0.00374564 1.26481
+8.1878 8.20011
+-0.115544 1.74771
+0.912347 2.52922
+2.72234 4.83268
+6.45577 7.07776
+9.74201 10.1772
+7.11008 8.72914
+4.41921 4.8673
+7.97673 8.36658
+0.438659 0.647061
+4.35086 5.44482
+8.22919 9.34379
+3.53242 5.65576
+1.126 2.32177
+5.95118 6.51364
+3.10519 3.9447
+1.28889 2.26267
+7.04255 7.67791
+3.12614 3.17626
+8.09968 8.49162
+6.07924 7.219
+5.99554 6.52549
+9.14378 9.5773
+5.82872 6.53112
+9.3361 10.1704
+4.3751 6.51675
+3.288 3.98328
+4.56342 4.80185
+7.16574 7.43901
+7.7638 8.47758
+7.31514 7.78499
+7.98942 9.50252
+4.31211 4.70724
+2.9094 3.33304
+0.108736 0.668815
+8.08409 9.11098
+-0.0053985 0.589992
+1.31926 2.72153
+2.28664 2.38813
+7.95237 8.26388
+-0.0283047 0.452099
+7.50295 8.71708
+7.72356 8.63468
+3.48953 3.89579
+7.73814 8.73456
+4.54487 5.45817
+6.45109 7.00312
+3.99915 5.41716
+6.81436 8.5682
+6.86726 7.55999
+2.67863 3.7053
+2.6837 3.39567
+2.84347 2.91724
+5.79383 5.80493
+2.41217 3.0619
+8.78163 9.0998
+1.43456 2.50854
+6.73393 8.53005
+3.02563 3.56456
+3.34628 4.2934
+2.44985 2.92819
+1.38262 2.89341
+4.56337 5.75702
+0.275735 1.16604
+1.39763 2.8108
+9.69128 9.90361
+8.54868 9.66756
+3.01838 3.72831
+8.34017 10.5262
+1.82721 3.0476
+5.9732 6.83307
+2.77874 4.25603
+1.71987 3.1227
+6.33773 7.89103
+1.31982 2.82992
+4.21601 4.9627
+6.68166 6.72653
+0.87708 1.06828
+1.03483 1.26625
+2.996 4.03087
+1.54718 1.57452
+2.33087 2.38226
+2.29464 3.36496
+2.03064 3.41867
+5.8456 6.10406
+7.54614 8.2874
+1.42938 2.89154
+2.65935 3.53883
+3.98845 4.42049
+6.85632 7.15487
+8.12038 9.34993
+0.873558 1.32129
+6.61595 8.00766
+9.49147 9.81947
+-0.0225601 0.328769
+-0.481519 1.37204
+6.31457 7.45251
+4.59738 5.81395
+4.83304 5.63008
+1.95746 2.78657
+2.97889 3.74408
+9.08327 10.702
+3.58219 4.93634
+7.87068 9.77851
+0.330978 1.36031
+4.78145 5.36918
+4.94672 5.56644
+7.66806 8.08613
+4.78512 6.35461
+5.17367 5.74386
+8.65884 9.97088
+9.22053 9.60447
+6.15061 6.58817
+0.0875971 0.541643
+6.45597 7.92002
+0.636824 1.05267
+5.31677 6.12838
+6.51127 6.6731
+0.459551 1.69382
+5.75106 6.41377
+3.68438 4.67415
+9.36302 9.78281
+5.46195 7.99215
+2.55471 2.59231
+-0.0640245 1.33755
+9.36027 10.6198
+2.67955 2.77882
+3.51443 4.10619
+6.83904 7.23692
+2.59553 2.81418
+7.74628 8.95169
+3.86464 3.90067
+3.32377 3.992
+1.43737 2.52191
+3.83927 3.99402
+5.24426 5.35179
+0.833857 1.05277
+8.4062 8.51964
+9.62299 9.66254
+3.55427 5.19048
+1.7003 2.62107
+6.8059 7.49246
+-0.761104 0.773528
+1.37137 1.95048
+2.1222 2.59387
+0.633505 2.04796
+0.605156 1.04336
+7.22842 8.3365
+4.28716 5.28921
+8.14286 9.52015
+7.62467 9.18603
+1.11029 1.81278
+5.05654 5.13597
+0.862653 0.97827
+7.24766 7.92167
+8.80103 8.91467
+3.05841 4.82292
+1.28204 1.55969
+1.58886 2.57874
+0.0537678 1.28837
+8.09303 9.71678
+8.37599 8.85705
+3.18107 4.01971
+6.67019 7.75848
+6.29836 8.21603
+0.86271 1.30358
+3.86126 6.49694
+5.84446 6.24913
+0.475025 0.598151
+6.3477 7.08327
+3.60161 4.51824
+7.13317 8.13858
+4.89052 6.23701
+5.69441 5.99027
+7.18735 8.34853
+9.30182 9.34894
+6.06589 6.15141
+8.05917 8.89642
+5.6136 7.14058
+0.838337 0.959487
+0.56421 2.00841
+6.46876 6.63629
+2.4434 3.92184
+7.97216 9.45372
+8.17926 8.66756
+1.86522 2.01888
+0.983342 1.89079
+2.07322 2.09765
+3.52974 4.73717
+3.24973 4.88691
+5.47789 5.95384
+4.11218 4.57076
+6.61174 7.47165
+8.09302 8.36193
+1.67911 1.69022
+4.436 6.17515
+5.6544 5.74951
+1.50354 1.76043
+4.41433 4.83589
+1.82528 3.53979
+3.98749 4.65527
+6.42503 7.5787
+8.69554 10.1767
+8.39215 8.56999
+8.71646 9.66209
+1.59091 3.39622
+6.12574 6.94955
+7.92527 8.25049
+9.19858 9.49137
+2.73382 2.97747
+4.56558 5.94738
+8.33983 8.58548
+9.00798 9.01838
+4.93268 5.28383
+3.15356 3.58606
+8.28171 8.79351
+1.47358 1.9581
+0.891797 2.05345
+1.56032 2.38159
+2.5152 3.80485
+8.0963 9.88138
+1.1262 1.89279
+7.99336 8.2352
+5.25067 5.41251
+4.57532 5.20101
+1.87911 4.59415
+4.25142 4.70467
+8.18782 8.76989
+9.20478 9.3612
+7.70898 9.7752
+0.655865 0.958924
+4.8883 5.77477
+3.03279 3.47456
+1.01979 1.41661
+8.94219 10.6987
+2.49348 4.58195
+2.44003 3.29005
+3.4725 3.55572
+9.3917 9.95851
+7.08658 7.47686
+3.56413 4.44089
+-0.47868 1.11453
+6.82615 8.00596
+3.49451 3.74705
+8.13286 8.47976
+7.01732 8.82556
+1.19064 1.48887
+5.28851 6.88637
+8.83175 9.49879
+0.939903 1.17024
+7.49124 9.01906
+2.9285 4.23224
+5.68296 6.86273
+8.53897 8.77886
+2.9107 5.01232
+0.748655 1.10265
+4.77258 5.12626
+3.995 4.75289
+2.71467 4.26926
+6.21665 7.16233
+4.53883 5.75731
+4.37153 4.76125
+7.47635 8.75777
+4.82013 6.4699
+9.36015 9.58451
+4.43054 5.86752
+2.10934 2.34705
+3.00306 3.06539
+7.81957 8.44081
+1.97221 3.06916
+0.153393 0.503956
+5.05611 5.27536
+5.73277 5.89001
+3.64807 4.85582
+6.13416 6.1528
+3.85511 4.14045
+0.411725 1.36529
+2.26932 2.5447
+3.51164 4.93266
+2.50955 4.34201
+8.74663 9.39268
+6.2229 6.39303
+4.38059 4.91592
+7.29109 8.62318
+6.31801 6.99532
+9.75036 10.0514
+1.69019 2.41527
+4.20462 5.27729
+6.32944 6.94729
+3.5736 5.21496
+4.48316 4.61828
+1.76915 2.43263
+2.42026 4.09159
+2.08762 2.43074
+5.48161 6.02473
+5.51826 7.47042
+2.78026 3.1552
+7.89469 9.49867
+3.09084 4.54697
+7.20417 7.42408
+5.36528 5.74851
+1.86239 2.41988
+1.55994 2.85743
+4.40182 4.6638
+7.91619 9.01242
+3.08119 3.74714
+1.54108 2.08538
+3.61461 3.64631
+8.76851 9.66257
+-0.645571 1.3366
+-0.707083 1.21005
+7.19571 8.23405
+5.42865 5.89329
+2.12897 2.59222
+0.603102 0.930391
+3.75025 4.63181
+6.14867 6.4526
+7.30947 7.51461
+7.83183 8.79802
+6.06658 8.53246
+1.67895 2.50063
+1.14179 2.04478
+8.59583 8.90112
+-0.918885 1.30717
+0.182607 0.613593
+3.3335 3.77196
+0.783053 2.4368
+6.49331 7.60104
+2.85101 3.28637
+7.42273 7.66905
+3.96433 5.02573
+8.26262 8.40749
+9.24451 9.32783
+4.89036 7.07214
+6.45431 6.96815
+5.20701 6.58747
+7.40142 7.98615
+4.19768 4.9831
+3.32546 3.88811
+-0.471996 0.967855
+9.36172 9.63532
+1.96831 3.00632
+7.537 9.72671
+4.67746 4.81135
+3.10782 4.93642
+4.94809 6.54855
+4.16763 5.25628
+9.04992 10.316
+0.668935 0.680886
+4.02935 4.84503
+5.32499 5.76636
+5.32267 7.15457
+5.18886 5.23491
+4.37053 5.36801
+2.39955 2.74657
+8.19764 8.86645
+4.24706 5.69703
+1.87851 2.36988
+0.886553 1.05064
+7.27428 7.90224
+9.08417 9.44879
+3.11534 4.02019
+6.3284 7.39925
+4.96029 5.59076
+2.58248 3.11741
+7.76513 8.13505
+4.93613 6.51523
+0.565355 1.70512
+2.12366 3.0319
+5.32422 6.84146
+-0.135396 1.08591
+3.7901 4.86303
+4.49677 5.41847
+0.615748 0.834712
+0.64784 1.81859
+6.65505 7.13894
+-1.12744 1.61017
+0.550814 1.24316
+6.66639 6.89866
+6.19271 8.17468
+3.09382 3.78684
+4.41221 4.95889
+7.96091 8.48824
+8.32129 10.2917
+2.13168 2.19835
+1.4635 2.38989
+5.78102 6.42215
+1.70153 3.20616
+5.35068 5.71016
+4.27702 4.37203
+5.13888 6.04764
+4.79644 5.37927
+6.75314 7.66368
+6.04484 6.84064
+4.34947 4.45643
+9.08755 10.396
+0.88804 2.17441
+6.86788 7.88301
+7.94296 8.61664
+8.02387 8.79591
+1.79024 2.40559
+5.50404 6.01044
+7.76772 8.1932
+1.174 1.23693
+6.20571 6.9224
+4.20863 4.48702
+4.16743 4.39075
+-0.11965 0.120778
+7.01234 7.52619
+5.91415 6.46151
+5.28713 5.72354
+6.26981 6.31237
+0.643056 1.43864
+1.62562 1.99875
+0.544992 0.721386
+6.92522 7.09165
+-0.107048 1.12273
+0.644674 0.91244
+8.56904 9.01883
+2.23079 2.56598
+9.79034 10.1123
+8.13788 8.4131
+1.86753 1.95236
+2.97577 3.33272
+8.57454 10.0193
+1.20043 1.53408
+3.43515 3.86571
+5.79075 6.41293
+1.71558 2.52845
+2.39907 3.46652
+9.08289 9.91182
+0.859644 1.07475
+5.30144 5.42157
+-0.441497 0.890794
+3.55044 4.14918
+-0.340115 1.19239
+6.5534 6.76908
+0.836514 2.09196
+8.15747 8.96484
+4.80087 5.14227
+7.72071 8.88223
+5.11901 5.65559
+4.44996 4.63562
+-0.328404 1.3002
+0.90759 1.34556
+5.94839 6.35058
+1.76504 1.78344
+1.32585 2.08994
+7.18641 8.20945
+0.62657 1.06025
+6.28086 6.40975
+5.05525 5.16143
+5.82694 8.07685
+6.23677 7.55394
+-0.226265 0.661443
+1.42599 2.36325
+9.04445 9.92971
+-0.169286 0.185741
+8.34636 10.9042
+9.52494 10.0475
+8.39989 10.1377
+3.89956 4.70428
+3.98673 4.97185
+5.43008 5.67936
+7.76475 7.98591
+4.46895 4.73188
+0.584662 1.54474
+2.12622 2.79994
+1.40578 2.2461
+1.45171 2.02105
+2.05665 3.04611
+2.29818 2.68118
+1.77344 2.98698
+4.92092 5.55302
+7.18758 8.37525
+8.83407 10.0565
+2.91182 4.71932
+6.47293 6.74664
+2.49238 3.69749
+0.487234 0.541003
+4.703 4.92744
+9.8867 9.94918
+1.7713 1.9792
+5.68316 6.90242
+5.62485 6.70656
+7.24837 9.60197
+7.71147 7.76519
+5.22324 5.30661
+9.11258 9.28071
+8.2827 8.90115
+8.90865 9.42138
+7.47233 8.72308
+4.89712 5.65153
+4.12392 4.20239
+5.65325 6.55887
+8.65945 9.05845
+7.9165 8.36489
+1.4952 2.43991
+5.49665 5.80793
+1.67206 2.55302
+0.943544 1.58521
+0.47 0.860959
+6.47638 7.43101
+4.38434 5.97278
+8.12782 9.10574
+5.78143 6.6539
+9.23616 9.40513
+1.6845 2.00736
+6.56955 7.37847
+7.42993 9.04718
+-0.179632 0.450904
+8.65819 9.07724
+7.86567 8.80824
+1.85428 2.7755
+2.29222 2.65374
+4.03614 4.51729
+6.9326 7.07635
+5.50807 6.498
+6.17637 7.26432
+8.7688 9.16308
+7.65 8.88604
+3.74495 4.29991
+8.5671 10.5661
+7.41964 8.21083
+8.04302 9.78783
+0.269663 0.317601
+8.29804 9.40991
+3.90673 4.22298
+8.82384 10.9441
+7.27081 8.19548
+1.30184 1.98993
+8.13028 8.92385
+7.21224 7.35137
+5.02122 5.69666
+0.817219 0.974073
+-0.128067 0.589359
+2.12137 2.74019
+5.24657 5.44714
+1.55805 3.10332
+9.91031 10.0748
+7.13941 7.9143
+-0.183908 0.934079
+3.987 4.11053
+3.26678 3.67608
+9.75921 10.1121
+0.755391 1.06346
+7.28479 7.49982
+1.37522 3.80623
+0.944351 1.46531
+9.49278 10.2372
+8.28946 8.67597
+9.43537 9.58003
+7.73357 8.756
+2.64043 2.8687
+4.70448 6.99929
+3.82199 3.89343
+3.43825 4.10908
+4.42362 5.69086
+8.08536 8.60142
+8.43208 9.31272
+7.5889 8.39208
+7.90112 7.9734
+6.10381 6.80568
+8.76283 8.80151
+1.46728 2.53288
+1.68884 2.47102
+7.63343 8.29838
+9.18852 9.5558
+0.977174 1.4792
+4.7577 5.74873
+4.66433 6.37375
+-0.0952277 0.378184
+5.30929 6.07469
+4.98811 5.16146
+3.0744 5.59799
+0.944909 1.25222
+1.38561 2.51277
+3.77811 4.23459
+2.11604 3.32458
+0.920929 1.17187
+5.23496 6.34905
+6.9953 7.65745
+4.81803 4.89553
+4.69301 5.36777
+-0.208926 2.6111
+7.97334 9.83269
+-0.396673 0.779988
+5.91367 6.47682
+6.27249 6.83533
+5.58931 6.89679
+2.03394 2.67025
+-0.197752 0.383167
+4.69751 7.695
+4.5989 6.07875
+3.7285 4.27396
+7.9807 8.27693
+-0.00248985 1.30934
+2.68016 3.916
+0.881558 1.14567
+4.77066 5.05302
+0.552268 0.919467
+2.46862 2.65199
+1.4009 2.51701
+-0.171185 1.28252
+9.27842 9.90243
+3.51778 3.57728
+6.10071 6.92163
+9.05387 10.0894
+5.52995 5.89082
+8.40216 9.0272
+9.02911 10.1602
+4.85818 7.38829
+1.6762 2.32334
+6.45416 8.62337
+5.44592 6.0245
+3.45876 3.94274
+9.07144 9.16725
+6.51885 7.6363
+7.92593 9.01986
+0.270702 1.57395
+6.11245 6.70173
+1.37658 2.19068
+2.42668 3.43827
+7.98226 8.43306
+3.72269 4.74654
+8.16252 8.58873
+8.81456 9.5363
+-0.338386 0.864811
+1.90693 2.25796
+3.5305 4.17475
+6.07997 7.67393
+0.53347 1.68815
+7.31182 8.44458
+7.77462 8.33613
+3.79975 4.15552
+9.08822 9.9771
+-0.101698 1.05442
+8.44869 9.95724
+-0.0318759 0.532673
+8.09238 9.51356
+5.51514 6.60799
+8.66528 10.3297
+8.25556 9.97893
+-0.220428 0.247563
+0.00453913 0.540444
+1.53599 1.61735
+3.77213 5.06896
+2.65332 2.75864
+6.05811 6.43112
+0.302534 0.803651
+0.393766 1.11611
+9.31035 9.62387
+0.568281 1.7765
+-0.721118 1.27387
+1.83573 2.62578
+1.39953 1.91158
+6.51883 8.52813
+2.60154 2.95054
+6.58322 9.37818
+5.61178 5.67661
+9.56511 10.2767
+9.09174 10.0697
+2.55846 3.39943
+8.38146 9.06138
+7.97019 8.18074
+6.1426 6.42787
+1.15876 1.55463
+2.93483 2.96376
+7.23883 7.29158
+9.64606 10.0674
+4.89825 6.70366
+7.35635 7.96328
+2.2702 2.36797
+-0.0464389 0.395244
+1.14883 2.10411
+4.7309 5.10593
+6.07946 7.37741
+5.50202 6.28822
+3.66574 3.96271
+1.9944 2.3862
+7.58159 7.59275
+1.98712 3.30587
+2.10317 2.89161
+9.66889 9.97287
+1.57327 2.15421
+8.14125 8.30983
+3.77185 4.12658
+8.51624 9.51485
+9.25211 9.722
+2.06312 3.0453
+9.34954 9.91254
+7.31475 8.89322
+7.85044 9.20242
+0.226243 1.28465
+0.0260868 0.575177
+9.40743 10.1655
+4.04324 5.05341
+1.02626 1.48332
+3.33074 3.72025
+9.2005 9.61387
+6.68317 7.14109
+6.82083 8.6312
+4.34816 4.50329
+-0.48874 0.975608
+4.26651 5.68526
+4.89731 5.57569
+2.68984 3.5661
+0.499714 1.01055
+9.01902 9.36142
+3.22067 4.59054
+0.65132 0.860512
+1.6791 2.36642
+8.28222 8.7579
+2.84349 3.24134
+5.64949 6.09512
+3.44026 4.43245
+2.60889 2.6248
+-0.00849234 0.984046
+7.5745 8.65675
+2.07464 2.6488
+2.59747 2.65772
+6.36828 7.42208
+3.83342 4.50127
+5.41167 5.7011
+6.53606 7.53796
+8.21975 9.56176
+1.90113 3.08684
+7.74402 7.82057
+4.26515 5.11327
+5.42743 5.59215
+8.69709 10.0912
+2.87019 3.94798
+9.27013 9.54627
+9.30568 10.2136
+9.02985 9.62917
+3.7589 4.59642
+6.59359 6.86939
+3.26574 4.83488
+5.14545 7.70086
+7.43163 8.05103
+5.72972 5.74457
+0.490113 1.31151
+7.018 7.42627
+6.22976 6.27589
+9.07732 9.30419
+4.3917 4.42663
+8.50298 10.3728
+6.18671 7.53619
+3.51053 4.097
+2.17172 3.56595
+6.08046 6.23691
+9.07361 10.9129
+3.95757 4.11333
+-0.136516 0.78995
+1.34923 3.47002
+0.0562579 0.686502
+9.10943 10.2731
+5.80174 6.16971
+7.86011 7.87649
+5.34384 5.51645
+6.32167 6.76387
+7.70566 8.28038
+-0.319903 0.867682
+-0.372564 0.570014
+8.83696 10.8439
+7.78947 9.38211
+9.25815 10.1092
+5.59721 5.67148
+0.234719 2.42489
+1.06314 2.87416
+1.75391 2.69799
+5.4536 6.66068
+1.35696 1.87102
+2.17418 3.1459
+7.61817 7.98287
+2.92194 3.18393
+7.68243 7.83261
+9.33163 10.5531
+1.14227 2.50228
+5.47911 5.70857
+9.88123 10.0758
+8.81249 8.83145
+6.02747 6.43183
+4.81158 5.79178
+6.65666 7.5047
+4.89085 5.56569
+0.935564 1.71547
+-0.0452879 1.16222
+4.03524 4.6206
+5.88518 6.02658
+2.06227 2.9581
+0.207246 2.2404
+2.81757 3.70318
+0.704257 1.98403
+2.38486 3.30039
+3.57073 4.78358
+1.53721 3.00546
+8.37852 8.39527
+1.54619 1.59789
+1.00447 1.40778
+5.31977 6.43861
+3.82175 3.83209
+3.37738 4.44002
+5.46644 5.97254
+3.88191 5.00688
+4.88046 5.39031
+4.15092 4.93679
+1.75182 2.07399
+1.16434 1.76541
+3.37032 4.29676
+3.1685 3.98533
+1.28787 1.59775
+5.86338 6.17993
+3.8645 4.25757
+1.83947 2.48092
+0.184795 0.586724
+3.13752 3.76447
+2.14264 3.03248
+5.78182 5.9029
+2.47969 3.8088
+2.59206 3.08362
+-0.354871 1.03627
+7.94041 8.05947
+9.48014 9.93817
+0.992727 1.48877
+6.1525 7.51387
+5.00071 6.15665
+7.42074 8.27606
+9.6539 9.83042
+1.08984 1.46387
+5.46282 6.95907
+4.74506 5.13968
+0.357565 1.91464
+9.07652 9.65474
+0.201095 0.646211
+7.04306 7.69131
+1.17728 1.2237
+5.92183 6.29165
+-0.41356 0.491524
+8.38339 10.4509
+8.08648 8.11344
+3.32474 3.39522
+5.762 5.83732
+2.26778 2.55548
+4.86127 5.92868
+3.75949 5.16608
+4.83431 5.88632
+2.65122 3.31344
+9.30295 9.38948
+6.03391 6.32749
+5.12035 5.59414
+5.68785 5.979
+7.89553 9.15202
+2.54445 2.74715
+2.36337 2.49709
+4.71661 6.12198
+3.72447 4.68735
+1.0541 1.53187
+3.45178 4.80929
+7.90773 8.26212
+8.1816 9.18627
+0.322569 0.871041
+7.24823 7.32699
+1.7003 2.78087
+9.70927 10.2515
+3.75922 4.01081
+1.06949 1.40253
+1.21774 1.4734
+6.02123 6.32973
+2.76396 3.09484
+2.80358 3.00026
+5.25666 6.31369
+4.71714 5.30669
+4.37906 4.50557
+7.40824 7.44969
+7.89081 9.18263
+8.8136 10.3074
+9.1757 9.37261
+7.1938 8.51137
+0.580081 2.32678
+2.02497 2.95434
+6.01446 6.78851
+8.54365 9.21454
+3.03567 3.27089
+0.650657 1.5716
+5.05518 6.36521
+1.64301 2.76399
+4.15989 4.34183
+3.72791 3.98156
+3.91372 4.06182
+3.04507 3.88871
+3.82596 4.25694
+3.36492 5.00402
+6.50019 8.17974
+3.54621 3.81009
+0.546921 2.09811
+5.1789 5.9826
+4.98983 6.31221
+2.47557 2.63878
+4.64568 4.81101
+9.1462 9.21888
+7.37417 7.5276
+2.21604 2.50113
+8.29804 10.2722
+5.1282 6.06353
+8.58281 10.1589
+6.47084 7.04085
+6.27806 6.72674
+7.11554 7.85687
+6.01085 6.02773
+5.46694 7.52872
+9.51078 9.85387
+3.36627 4.06552
+2.96126 5.12635
+3.09314 3.40691
+5.05456 6.62548
+7.56469 8.97053
+1.33727 2.87482
+5.6572 6.28169
+0.120924 0.296475
+7.09139 7.41322
+2.10076 3.28507
+8.74998 10.1094
+7.45072 9.50796
+7.75294 8.59218
+0.740374 2.44897
+7.63001 8.91562
+4.30743 4.81716
+6.40813 7.29159
+6.30213 7.35987
+6.44392 7.32584
+8.41155 9.4466
+-0.377892 0.689618
+5.88857 6.70983
+6.67779 7.70668
+4.831 5.17464
+2.62342 3.82764
+8.57453 9.29283
+7.32648 7.96725
+9.32937 9.9726
+7.30774 7.65754
+3.97456 4.59876
+5.73092 7.20962
+1.958 2.10551
+3.2115 3.81482
+5.76497 7.42425
+2.77219 3.29692
+4.95297 5.14843
+5.96367 6.3619
+2.49872 4.61736
+8.21817 8.23425
+2.13615 2.61877
+7.84121 9.55011
+8.63416 10.2773
+5.61084 6.32053
+4.86002 5.79944
+9.07858 10.688
+5.95829 6.42504
+3.3289 4.17849
+3.27989 4.91625
+8.28046 9.23021
+2.18691 2.6072
+1.3962 1.75013
+2.13627 3.73117
+2.11128 2.57303
+7.22357 7.50136
+7.43862 8.03136
+2.80578 3.02886
+0.176906 0.761142
+5.99314 6.6075
+1.90398 3.3925
+5.48264 6.73579
+7.18447 7.49811
+3.24434 5.05219
+5.53263 6.04178
+1.71172 2.45682
+0.297266 0.481632
+2.62582 3.36142
+0.243865 1.49321
+8.86142 10.169
+3.93193 4.39404
+4.98182 5.15675
+7.99209 9.73159
+8.18033 9.45596
+4.25235 4.41546
+1.59603 2.15581
+6.47724 8.69649
+5.24138 7.93131
+3.4267 3.49003
+0.0439912 0.316407
+1.99983 3.87206
+-0.103124 0.568771
+4.62451 4.80117
+2.89065 4.16315
+5.82817 7.43232
+6.89255 7.82189
+5.71037 6.81241
+4.34551 5.24905
+7.33931 7.3741
+-0.855192 1.27129
+8.94842 9.10813
+9.19877 9.68412
+6.42658 7.77968
+-0.0669636 0.430107
+6.40366 7.40701
+8.91175 9.24059
+3.21388 4.21676
+3.38557 3.79509
+4.24411 4.97032
+7.259 7.34896
+2.55995 3.18361
+8.77438 10.5503
+8.18685 9.79378
+2.78397 4.4563
+8.6891 9.38337
+6.51749 7.59374
+2.52346 3.46101
+8.40526 9.35647
+5.26942 6.33572
+4.15094 5.00668
+0.471666 1.53842
+7.63441 7.96745
+2.39974 3.7814
+2.71989 3.02994
+8.12085 8.33493
+6.19474 6.84381
+6.6133 8.31417
+5.1758 6.94983
+8.66241 8.79095
+6.10878 8.22083
+8.81883 9.08031
+8.28969 8.45176
+7.19851 8.37836
+1.5722 1.6836
+4.57814 6.95063
+7.66128 8.10631
+0.742483 3.08515
+1.15026 1.98074
+3.90133 4.12003
+7.61145 7.73433
+8.32187 10.2933
+0.407205 1.08089
+1.26545 2.60796
+2.70646 3.92753
+-0.196551 1.83536
+-0.413063 1.23838
+0.264484 0.556192
+6.30158 6.96097
+-0.66246 0.809062
+9.34243 10.3521
+8.70093 8.79679
+0.745195 1.92911
+9.12892 9.68193
+7.98533 8.30538
+6.23671 7.04296
+6.5603 6.95483
+7.08133 7.10563
+2.15769 2.41541
+8.24752 8.73978
+5.27693 5.61904
+0.317419 1.48404
+3.48029 5.46979
+7.38901 8.56554
+1.06587 1.62384
+5.54926 6.04924
+4.46577 6.48749
+5.349 6.15584
+8.04249 8.17359
+3.37651 3.56179
+3.64706 5.57403
+4.49844 5.26404
+3.93361 4.92128
+5.82184 6.29881
+0.984273 1.70318
+1.12773 1.80726
+3.11675 3.17451
+5.07913 5.46291
+0.615591 1.81465
+1.08948 2.77847
+7.97412 8.07365
+5.05207 5.82497
+0.0407709 0.558817
+6.11142 6.48205
+3.4461 3.57315
+8.6547 8.80553
+8.18965 9.64194
+5.55564 7.9703
+4.01776 4.16989
+2.4668 2.82018
+0.911925 2.56662
+4.68814 5.03614
+7.4899 8.49036
+8.40912 9.14001
+2.32725 3.16377
+0.0723972 1.42049
+6.6441 6.6953
+3.65586 4.38222
+6.35844 6.57833
+4.44435 5.73077
+1.81779 2.57257
+4.17692 4.59722
+8.54682 9.38058
+1.61135 1.81629
+3.91926 5.00536
+9.78302 9.85143
+1.25632 3.10345
+5.53191 6.08174
+-0.231868 0.676811
+1.03054 2.58105
+0.0402172 0.690608
+0.974571 1.25234
+5.22227 5.92302
+8.05843 10.1439
+8.48938 8.50755
+0.0965782 1.24008
+6.53821 7.47765
+0.189991 0.475204
+8.48963 8.54995
+9.68363 10.0534
+1.49381 2.71302
+6.75552 7.41283
+7.91075 9.15302
+0.520922 1.40928
+1.17957 2.11221
+4.00122 4.40686
+7.32467 7.9273
+6.39126 7.90248
+6.50534 8.19308
+7.19888 7.22234
+-0.136797 0.731889
+0.870318 1.25614
+2.07126 2.28297
+6.10995 7.60408
+3.02174 3.90102
+-0.657541 1.57517
+0.993121 2.66255
+7.27232 7.50832
+2.16079 3.75428
+9.27397 9.75098
+8.36865 8.5545
+4.56641 4.97607
+3.60746 4.34616
+6.31304 7.70611
+2.91442 3.7602
+4.85814 6.70407
+4.45876 5.67661
+8.06749 8.82229
+2.02826 3.59873
+1.92922 2.50088
+2.63867 3.48117
+2.17665 2.54826
+8.62674 9.10675
+0.96648 1.47671
+8.86336 9.53978
+5.52747 5.80829
+0.77099 3.06106
+2.2307 2.53877
+6.29165 6.63018
+4.44717 5.04651
+3.80894 4.63054
+7.47519 7.87072
+0.933668 1.9949
+-0.712945 1.21558
+7.30206 8.38376
+5.80281 7.00022
+7.96578 8.6558
+0.24063 0.706466
+4.41893 4.58472
+4.0132 4.92768
+5.29626 6.09397
+3.43602 4.00728
+0.780945 1.66499
+8.83861 9.15168
+9.06411 9.75544
+3.45618 3.62529
+9.51413 10.0148
+0.842106 1.75695
+1.06485 1.44192
+6.89987 8.05314
+7.89154 8.73313
+8.71675 9.79526
+2.40574 2.58062
+8.55952 8.78132
+5.61716 6.06282
+3.71059 3.77929
+2.50187 2.99137
+6.92852 7.23184
+7.00442 7.93869
+8.82232 8.8756
+4.10389 4.53702
+7.6907 7.77577
+9.31554 10.2674
+8.51082 8.70339
+4.83332 6.70311
+4.6904 5.42892
+4.71407 5.67695
+4.12047 4.44089
+7.51845 8.26858
+1.31781 1.9397
+6.26854 8.02093
+6.92072 7.77774
+0.438156 2.18909
+0.898035 1.72074
+3.81121 3.8643
+1.01676 1.34308
+9.28445 9.42801
+2.43133 4.43516
+4.33664 5.9904
+2.19178 2.37244
+1.5457 1.79785
+2.23781 2.6481
+6.8365 6.87073
+0.82568 2.74775
+9.59404 9.89262
+8.48394 9.15107
+6.16085 6.42224
+3.5667 5.97689
+4.16931 7.41638
+6.95636 7.0982
+6.87987 7.09233
+3.12619 3.14821
+7.76636 7.98459
+4.60371 5.59136
+3.92189 4.88302
+6.90694 8.19858
+3.85132 5.19015
+8.05045 8.32483
+4.8338 6.05032
+1.93576 3.18873
+2.4182 3.55039
+5.56905 5.8172
+4.18436 6.01283
+3.04944 3.85936
+7.83585 8.95233
+1.76281 3.0558
+3.44143 3.6317
+8.69887 9.40371
+5.67867 5.73236
+0.859809 1.76578
+6.92284 7.13601
+8.27495 9.13414
+5.44385 6.42599
+-0.941603 1.8215
+7.88161 8.79447
+0.965018 1.17732
+5.56442 5.79546
+8.79032 10.9909
+5.28632 5.79175
+4.80998 6.07002
+8.4021 9.81107
+3.16415 5.08682
+-0.212163 1.2052
+5.683 5.83625
+0.738527 1.31842
+2.03835 2.52756
+7.4543 8.91243
+-0.568869 1.44659
+3.58855 4.42371
+6.33058 7.18779
+-0.645579 1.94313
+2.18149 2.24157
+3.80281 4.67323
+5.14628 5.97452
+2.55239 3.45685
+3.56586 6.23355
+6.74752 7.19693
+8.99006 10.5533
+0.259833 0.99882
+8.9005 9.75401
+7.28058 8.41075
+4.57803 5.70104
+9.82823 9.90251
+6.94375 7.42033
+7.8878 8.81951
+5.01137 5.52693
+2.25503 2.28817
+6.65772 7.11107
+0.647512 2.04416
+4.34796 4.5706
+4.5395 4.91529
+2.65423 3.49531
+7.97384 8.78377
+5.53873 5.76806
+9.78641 10.1351
+6.01664 6.44407
+3.47406 3.75187
+4.59421 4.81804
+1.20641 2.00488
+2.48904 2.80768
+5.77372 6.10692
+2.49363 3.24499
+1.8483 2.62965
+2.28556 3.22209
+3.17819 4.51426
+3.5548 4.23276
+3.25239 3.57895
+0.613317 2.44862
+3.82234 4.78976
+4.72809 6.46528
+9.54107 10.4426
+9.20052 10.1921
+8.24152 9.89817
+5.17594 6.19462
+7.83364 8.17082
+5.67992 6.36464
+8.9943 10.1426
+2.20598 3.0081
+3.38199 5.16464
+0.599928 1.35804
+0.841211 1.60761
+5.29338 5.89919
+1.11061 2.29219
+3.41512 3.95907
+7.9375 10.0203
+8.73852 9.66917
+9.95092 10.0162
+4.02544 4.30219
+4.1461 5.37827
+1.08089 1.59196
+7.87513 8.21121
+7.85673 8.0973
+0.96237 1.56519
+2.45532 2.61678
+6.1829 6.23637
+0.135135 0.613518
+3.18324 3.78587
+5.64796 7.20194
+0.861169 1.71661
+9.66005 10.1169
+0.880774 1.12452
+1.29389 1.57658
+5.60299 5.89759
+5.53642 7.07306
+0.540268 1.31836
+6.60244 7.98105
+4.21877 4.57159
+3.15367 4.75356
+7.81055 8.40378
+8.00942 8.10861
+5.78071 6.35646
+3.15993 4.99293
+2.36526 2.78444
+8.1361 8.76071
+1.40066 2.96474
+-0.17906 1.05877
+5.94933 6.6808
+3.43187 4.05553
+3.02912 4.68942
+2.1506 2.29413
+2.3516 2.38305
+2.87496 3.0851
+6.71294 8.99858
+3.76177 5.52545
+1.58417 2.57063
+2.74646 4.27445
+5.48407 6.60696
+-0.133321 0.716559
+3.53886 3.58196
+2.28729 2.40198
+-0.209646 1.21263
+6.62795 7.32318
+0.714781 0.880466
+2.96831 4.05932
+6.00935 6.38896
+5.39798 6.11983
+8.47679 9.70468
+1.4339 1.74845
+2.35223 4.75732
+4.31357 4.9642
+5.26493 7.70538
+7.91888 8.94851
+6.51439 7.69469
+7.69015 7.85411
+3.94274 5.15373
+6.25852 7.32402
+2.73567 3.43236
+7.09564 8.42242
+2.55932 4.29066
+1.79489 1.84559
+8.86427 9.35669
+7.23854 8.27062
+7.8488 7.98307
+0.710888 2.22424
+0.0413624 1.10578
+1.54302 1.97696
+1.64924 3.01081
+8.15535 10.2397
+0.305662 1.63835
+8.20375 9.03123
+1.66617 2.08748
+4.01691 4.88505
+3.32856 4.10709
+5.15342 5.44616
+5.80751 7.38872
+0.485341 1.07648
+3.98267 4.20211
+6.96867 9.37655
+9.48055 9.85181
+8.39277 9.50424
+2.47589 2.79873
+3.48046 5.37417
+4.98279 6.01686
+1.29845 2.31199
+-0.204348 2.50289
+0.23488 1.00378
+6.26899 7.14823
+4.62903 5.49672
+0.199052 0.822066
+6.97297 7.69083
+4.23783 4.65198
+0.530497 0.839143
+6.61355 8.22831
+-0.0103941 2.16307
+0.148601 1.20044
+0.314438 0.67632
+3.43415 4.06208
+1.95498 3.25728
+4.23094 4.84942
+9.5493 10.0057
+2.64964 3.52073
+8.21388 9.1622
+-0.112496 0.47622
+7.97551 8.19546
+2.16155 2.6289
+0.38442 1.46032
+3.85675 3.91557
+1.00605 1.42016
+2.4853 3.53086
+-0.0765625 0.504366
+8.11302 8.46334
+7.18135 7.80218
+6.46466 8.12336
+3.75968 5.33954
+9.08789 9.73677
+6.47459 7.49454
+0.90148 1.47681
+3.44733 3.54163
+7.32968 7.909
+1.30055 2.75407
+8.78735 8.92461
+8.21764 8.59414
+0.888162 1.08404
+5.65195 6.26421
+6.23881 7.33284
+8.69731 9.88088
+3.55695 5.36909
+6.49248 7.02755
+2.31407 3.01952
+5.7803 6.1286
+6.30415 8.01577
+7.73864 8.27496
+0.741078 1.69184
+4.94671 5.68254
+3.28226 5.02894
+1.97446 2.60413
+3.26555 5.54754
+2.56179 3.41897
+3.20058 3.32486
+6.96915 7.69055
+6.89302 7.39856
+1.9659 2.61404
+1.31107 1.36867
+6.23573 6.33677
+0.17616 0.517772
+8.55548 8.79155
+9.61632 10.2651
+2.20331 2.34017
+6.93195 7.42939
+1.25398 2.23119
+1.06577 1.41048
+5.99156 7.09818
+3.34821 4.1271
+4.61618 6.90956
+2.30853 3.52875
+0.0518063 0.113732
+5.38513 6.09734
+1.73468 2.64838
+7.24679 7.63999
+4.18175 5.06728
+7.09602 7.13414
+9.06191 9.11605
+6.2309 7.67675
+3.96576 4.63237
+-0.552645 1.37948
+5.76964 6.89903
+4.9272 7.5832
+4.59003 6.49719
+4.12281 6.9664
+5.12256 5.58387
+1.78859 2.76954
+4.36808 5.05712
+8.41165 9.54483
+8.11513 8.43405
+8.42016 9.52715
+8.50598 9.34564
+1.80028 1.83558
+8.08502 8.43726
+6.96667 8.12021
+5.4726 6.26772
+7.1141 9.29989
+7.83324 8.1744
+8.74368 9.16491
+2.5515 3.01706
+5.92375 6.44495
+7.45628 8.41582
+9.04829 9.71503
+4.58856 4.75356
+7.26064 7.32462
+1.81695 2.40529
+6.88067 7.95052
+1.91408 2.02663
+1.32005 1.45025
+7.47733 8.42004
+4.99403 5.85297
+0.95744 2.28875
+-0.089503 0.536888
+1.09978 2.48865
+1.9959 3.098
+0.376116 0.448329
+3.98908 6.49684
+9.10178 9.51012
+5.41394 7.31529
+6.60708 7.59071
+4.38466 5.76203
+1.84355 2.60304
+0.658705 0.933522
+6.98725 7.05509
+5.60064 6.98804
+1.0603 1.1521
+4.06192 4.46156
+0.351018 1.00807
+9.17113 10.2192
+6.71641 6.74659
+8.85392 10.5272
+4.50816 5.22908
+1.13934 2.43196
+3.3746 3.57576
+7.62137 9.3234
+6.93482 7.16058
+5.66506 6.44324
+5.13364 5.86068
+1.97257 2.03803
+2.69746 2.73067
+0.989591 1.38342
+4.18819 4.69676
+4.31608 5.12265
+2.79556 4.87763
+3.55387 5.34421
+-0.112466 0.585639
+2.43156 2.70221
+5.88314 7.08322
+-0.450332 1.29858
+1.22202 2.46588
+6.74433 7.32925
+5.14596 5.37435
+6.76754 7.41799
+1.48762 2.45958
+4.57241 5.3382
+4.17465 5.02296
+6.48856 7.5576
+0.383566 0.823394
+8.50875 9.08734
+1.79393 2.24548
+5.06812 6.49508
+3.55364 3.61502
+5.58973 6.58885
+0.631097 2.10041
+0.323995 0.941782
+8.8798 10.1036
+6.37114 6.88202
+6.9393 7.83288
+3.09503 3.41759
+3.65269 3.70305
+5.61676 5.8924
+1.90199 2.38446
+4.23683 5.35609
+9.18649 9.88878
+8.28736 8.37734
+3.04805 5.03593
+8.02926 8.38975
+3.58161 4.01331
+3.20923 3.48207
+6.85118 8.78281
+5.06518 7.49843
+1.57456 3.05552
+3.0154 4.23782
+2.83557 3.24854
+1.29358 1.89328
+1.42911 2.72661
+3.17067 3.96651
+0.353554 1.48472
+3.46227 4.25611
+6.17639 7.24657
+5.60878 7.13562
+4.11129 5.52476
+9.17596 9.4123
+3.08339 3.65766
+4.083 4.63013
+0.628465 1.92141
+7.81989 8.39386
+3.35589 3.87531
+5.35974 5.41743
+4.48321 4.64376
+0.888177 1.37343
+8.49061 8.50063
+5.09078 6.01801
+9.65314 9.99342
+1.60502 3.0115
+1.37928 2.77642
+6.60322 8.94046
+6.74573 7.45157
+-0.291156 0.325249
+6.1518 6.66827
+5.38199 6.46959
+3.50128 5.22692
+1.31774 1.70159
+0.550546 1.48845
+7.51187 7.85496
+4.2014 5.23193
+3.88255 3.97209
+2.60555 2.84958
+5.15706 6.00036
+2.99284 3.27867
+0.395077 0.768383
+3.30863 3.60594
+0.0325231 0.379208
+6.55183 7.33346
+1.44554 2.95846
+0.245421 1.29751
+3.98808 5.41226
+5.90242 6.266
+4.11097 5.02597
+0.134753 0.929866
+0.609287 1.16311
+0.231832 1.06825
+6.22093 7.05584
+9.18429 9.80637
+0.544139 1.30185
+1.69143 2.90306
+6.75109 8.67893
+5.49641 6.76104
+8.91712 10.0271
+7.09126 8.12404
+8.82958 10.2847
+0.569249 0.69421
+3.59288 5.8053
+9.25068 9.4226
+8.51607 9.26259
+5.00906 5.17068
+1.83467 2.99102
+7.32006 7.64842
+0.405532 0.603773
+6.41882 6.60495
+0.721592 1.44375
+2.78393 4.46732
+7.14806 7.16117
+5.12868 5.27918
+2.74138 3.1737
+2.95394 4.26547
+7.82827 8.21028
+9.06982 10.7279
+0.108376 0.290131
+6.34574 6.97141
+4.39022 5.50801
+7.98339 8.79674
+3.80026 4.71831
+5.43594 5.66916
+1.6743 2.61476
+4.29763 5.47402
+7.95714 8.69311
+3.4152 3.7387
+8.01715 8.8941
+6.53723 7.44437
+-0.0222108 1.04503
+4.96242 6.01648
+1.70885 1.75511
+7.62434 8.53526
+6.82863 7.39782
+8.19967 9.22283
+1.99719 2.11323
+-0.0124079 0.240201
+4.48577 4.87935
+2.586 4.41666
+6.37848 6.67092
+4.39606 5.67983
+9.39761 10.1095
+7.10866 7.15796
+3.91993 4.52129
+5.10552 5.36997
+7.08963 8.32694
+9.12669 9.58509
+9.26894 10.1974
+0.737413 1.26523
+2.77833 5.28516
+3.19039 4.36857
+4.32954 5.45614
+4.98069 5.49295
+7.54745 8.76142
+5.70425 7.05749
+-0.250513 0.36578
+4.76997 5.89607
+2.03075 2.32111
+6.54141 6.55896
+4.19799 4.45091
+8.7796 9.11915
+5.75014 6.05646
+5.36885 5.42775
+-0.00433056 0.865304
+3.65169 5.4751
+0.23625 0.872926
+0.0386337 0.792214
+4.40245 4.56789
+6.44567 7.42162
+5.51394 5.98005
+3.50146 3.83147
+8.47573 9.85647
+7.91378 8.47044
+9.44297 9.90241
+5.962 6.68782
+4.49034 4.86927
+2.17774 3.47061
+8.80614 9.26595
+7.92096 8.13838
+7.80209 7.93317
+7.78915 8.29735
+6.98111 7.162
+0.491059 1.14901
+8.97965 9.38792
+3.30207 3.53207
+3.17127 4.43581
+3.97564 4.43746
+6.79008 7.17877
+5.61669 7.51263
+4.0853 5.38748
+4.42181 6.32041
+8.08599 8.9095
+2.46938 2.55499
+1.20692 2.06351
+1.98995 2.35216
+8.17116 9.17158
+7.53414 8.37086
+3.7744 4.46197
+3.29464 4.38
+7.33246 7.81959
+4.89572 6.2831
+-0.152496 1.56427
+0.636242 0.938556
+5.62066 6.06096
+9.42994 10.473
+8.95446 9.46311
+0.277891 2.80311
+6.92968 7.29845
+2.75677 3.02975
+2.2859 2.51308
+2.96683 3.03857
+6.44584 6.49518
+8.33607 8.60407
+7.20303 7.7616
+7.07205 7.46849
+2.35677 2.7904
+5.86404 6.12906
+2.42371 4.62735
+3.27237 4.11016
+0.0668578 0.644021
+6.77371 7.45187
+3.66596 5.21874
+0.718034 0.755944
+6.06162 7.05
+6.91473 7.09753
+5.0749 6.08914
+0.759874 1.11978
+8.54591 9.64997
+3.97266 4.70679
+1.51133 3.17164
+7.21772 7.69877
+8.00719 8.37052
+0.284003 0.38001
+4.08842 4.16227
+5.04461 5.79973
+4.60604 5.31979
+2.2461 2.28157
+6.25631 7.69766
+9.12404 9.67586
+7.73134 8.98923
+1.0513 1.46408
+9.17225 9.42567
+3.66795 4.29168
+8.84403 9.28497
+9.93613 9.94729
+3.16615 5.09374
+-0.149675 1.43397
+2.30855 2.48392
+0.843172 0.951801
+8.32945 8.8506
+8.97012 9.94697
+2.8559 2.92359
+-0.321715 0.89173
+7.48565 7.71775
+1.44301 1.47795
+6.6649 6.76187
+9.10721 9.93599
+1.82207 3.03935
+3.61893 4.5306
+2.53746 3.81243
+0.424528 1.29026
+9.51874 9.68841
+7.94954 8.14396
+7.49282 7.52655
+3.04604 3.69656
+9.45461 9.47212
+7.69209 8.16412
+0.607135 1.16564
+0.150291 0.450632
+3.28914 4.01085
+5.45597 6.02921
+8.16157 8.36605
+9.76573 10.2325
+0.151994 1.07074
+1.3748 1.68548
+2.29854 2.63593
+7.92162 8.68895
+1.28795 1.61949
+7.85469 8.26683
+4.32268 6.33174
+6.13964 6.3596
+1.25714 1.88002
+2.05006 2.28294
+8.31864 8.34151
+9.0613 10.0715
+-0.041568 0.25139
+6.79984 6.81686
+5.10674 5.70583
+5.92937 7.01652
+7.57649 8.05834
+0.937157 2.25362
+7.48567 7.59746
+2.33403 2.88942
+7.3805 7.73421
+5.586 5.75327
+0.828854 2.12988
+8.22741 8.59954
+9.69214 10.1207
+6.55359 7.08114
+1.85342 2.634
+6.08756 7.28893
+6.34993 6.93474
+8.93548 10.1463
+5.49445 5.8338
+1.47951 2.14646
+2.62089 2.75888
+2.35352 3.10539
+4.98774 5.28931
+4.92239 5.40697
+7.52674 8.78948
+4.52451 4.83819
+5.45854 5.75838
+5.51553 6.3901
+4.82905 6.44407
+6.20655 6.4483
+5.68116 7.06109
+7.97301 9.15827
+8.8854 9.91623
+9.60198 10.2449
+1.93322 2.67684
+0.441852 1.87646
+5.19981 5.71385
+2.54799 2.5809
+4.34591 5.02655
+7.54678 8.75202
+6.1496 7.19033
+1.13658 1.30756
+1.38724 2.08252
+2.13624 2.30419
+8.49196 9.41369
+-0.21387 0.685093
+2.47875 4.19982
+3.69093 4.00543
+5.70643 6.50331
+7.07443 8.83588
+6.85756 7.68937
+1.69241 1.83242
+0.140565 0.502156
+2.15007 3.23784
+4.97403 5.69757
+5.08315 6.25554
+3.45026 4.01942
+3.37482 4.73009
+7.4154 8.34013
+6.95399 7.59768
+8.07995 9.86199
+8.43993 8.88645
+7.66844 8.12742
+-0.0200687 0.435846
+4.47984 5.9416
+7.66804 10.0801
+4.14578 5.98717
+0.256533 0.89254
+6.43216 7.4474
+3.60295 4.79419
+3.90129 4.29812
+5.30606 5.58674
+9.11552 9.79229
+5.60702 5.85299
+2.39514 2.64865
+4.51164 4.60227
+6.31154 6.77441
+3.12239 3.13505
+7.50962 7.89478
+3.90928 4.88831
+9.64625 10.0629
+5.9465 6.02877
+2.08554 2.10477
+0.087547 0.34748
+2.34295 2.53703
+6.846 7.3043
+1.37869 2.11446
+4.03371 4.26278
+5.38623 6.40917
+4.75848 6.25417
+6.03478 6.15991
+-0.585543 1.2091
+2.52824 3.57712
+3.95687 5.40914
+4.42955 4.71909
+2.9328 3.98848
+5.40471 6.97056
+7.64789 9.30279
+6.19595 7.07492
+8.27328 9.41596
+8.29855 9.13665
+2.54035 3.10488
+8.25038 8.87903
+5.66599 5.88701
+7.40067 8.71195
+6.63762 6.67694
+-0.0163105 1.72666
+4.77743 6.60356
+0.567991 1.14977
+5.96841 6.42987
+3.02266 4.58424
+6.72121 7.35492
+7.51477 8.65223
+8.55055 8.81014
+5.59759 5.82816
+0.218944 1.82542
+1.03197 2.36652
+7.84302 9.1594
+2.11542 4.7332
+6.37618 6.92981
+1.34963 1.59353
+0.516281 1.08859
+-0.0151152 0.0624718
+6.45603 7.23063
+4.76865 5.46588
+7.5893 8.42021
+1.04534 1.99034
+2.62638 3.04997
+5.00254 5.98512
+7.7588 9.44547
+6.82186 7.34321
+8.7629 9.82272
+-0.309554 0.54858
+4.19843 4.92981
+5.62327 6.80846
+6.40599 7.6073
+6.1547 6.53898
+3.93941 4.44985
+3.28342 3.72778
+7.17256 7.23035
+2.31269 3.05437
+7.99132 8.20926
+7.19338 8.08381
+7.29139 7.96441
+4.25818 4.4208
+0.802894 0.81938
+0.990115 1.04066
+0.443898 0.490936
+3.44459 3.95977
+9.07812 10.3145
+7.86709 8.26338
+-0.230114 0.390748
+7.50905 8.49199
+-0.715424 1.97535
+2.92248 3.12903
+5.44209 6.62431
+0.991914 1.99037
+5.92275 6.7724
+9.10818 9.2797
+4.46434 4.83462
+4.21122 5.48353
+1.8721 3.40764
+7.04713 7.60526
+3.76581 4.76317
+7.00667 7.36475
+6.87244 7.39431
+7.6349 8.46695
+-0.0728922 0.351194
+5.02925 5.6834
+1.45779 2.83702
+0.339175 1.46574
+6.40414 6.9165
+6.30401 6.91007
+5.6392 5.78172
+5.63288 6.44639
+7.45285 8.89031
+4.09741 4.57929
+8.76728 9.06448
+1.62324 1.84552
+5.72509 6.54553
+8.65273 10.3652
+7.3362 7.8953
+8.96224 10.3113
+0.217316 1.7827
+1.28523 2.90127
+8.78746 9.11602
+8.6075 9.9606
+-0.647788 0.779976
+4.9702 5.47602
+4.15553 4.57497
+1.08174 2.80993
+4.01011 4.8145
+6.79603 7.2317
+4.3711 4.43566
+9.65087 9.79922
+8.19407 9.21784
+3.04008 4.94094
+6.0883 7.23919
+6.88708 6.97172
+0.438073 2.00665
+8.53083 8.83004
+4.22258 4.65233
+6.72856 7.61085
+3.17591 3.18978
+5.07955 5.6938
+2.09043 2.55351
+3.28085 4.43556
+7.29225 8.03925
+7.78034 7.82608
+6.59677 7.67719
+5.56032 6.38139
+8.72663 8.82535
+2.96505 3.11983
+1.67192 2.11727
+7.85386 8.49025
+6.30965 6.72799
+8.53082 9.3801
+2.8976 3.39972
+8.90427 9.44661
+-0.0665785 0.410254
+4.58099 5.81135
+1.88015 2.21838
+3.38693 4.10149
+7.46378 7.68246
+8.80985 9.72212
+6.54877 7.25642
+7.18249 7.71509
+7.41978 8.64805
+1.00839 1.78626
+0.39421 0.526751
+7.13516 7.28317
+7.28011 7.80573
+1.90158 2.49032
+1.66181 4.17994
+8.81106 9.21133
+9.46151 10.5007
+0.52585 0.575082
+7.66495 8.64072
+7.72794 8.50991
+4.92409 6.23879
+2.28769 3.21774
+3.62671 4.40932
+5.77688 7.31314
+8.94253 10.0664
+0.416618 0.635111
+1.81377 2.41356
+7.91755 8.83363
+1.62715 1.82626
+8.22065 9.51656
+0.020228 0.724724
+8.81119 9.95764
+8.66509 9.61079
+5.28201 5.32152
+3.95724 4.22138
+7.09339 7.77685
+9.63428 10.1514
+3.69117 3.779
+3.82195 4.76757
+5.75824 6.62265
+3.69984 4.75163
+3.58259 4.8788
+8.32635 8.85873
+5.81959 7.32506
+8.11265 9.14304
+2.20118 3.32511
+7.79582 8.52691
+6.5891 7.13584
+0.385393 0.440656
+1.13414 1.9951
+1.76482 2.69977
+4.76194 5.82757
+6.33633 7.5348
+4.7663 5.65083
+1.98298 3.01285
+0.956973 2.38629
+5.60955 7.65827
+9.11064 9.14351
+2.99933 3.37975
+3.36304 4.57437
+3.89886 4.50733
+8.73838 9.3514
+9.11824 9.66042
+1.47961 2.93909
+0.615297 1.13217
+1.70646 2.32478
+4.35168 4.99362
+0.986601 1.18332
+4.01551 4.92342
+7.68944 9.86838
+4.47611 4.85316
+0.051839 0.86288
+3.59624 5.5628
+7.08729 8.90374
+9.53464 9.9196
+4.69871 5.74189
+8.43146 10.6889
+3.23774 3.77777
+9.35399 9.62741
+1.15259 2.69451
+6.6368 7.33773
+5.26395 6.09857
+6.87415 7.21717
+-0.925645 1.06118
+8.49641 8.67659
+2.31486 3.25354
+2.51057 2.58303
+0.921997 1.48762
+6.29777 6.74738
+4.03945 4.27305
+7.1668 7.3471
+8.44572 8.80343
+7.16937 7.84526
+8.89008 9.4332
+7.01815 7.66319
+-0.420804 0.982878
+1.59755 1.64672
+0.700814 0.72579
+6.3138 7.37379
+8.49276 9.93522
+-0.795656 0.819657
+0.772253 1.05926
+0.917593 1.3917
+3.30076 4.12274
+-0.0237176 0.260552
+6.82385 7.49119
+6.98638 7.52012
+8.24915 9.08397
+4.17486 4.25908
+3.08435 4.64404
+8.17114 9.91412
+8.95923 9.3751
+0.596707 1.89462
+0.982917 1.40236
+6.79552 7.36657
+8.2599 9.69551
+8.85126 10.4342
+7.98967 9.14514
+0.766355 1.63286
+7.76211 7.99247
+5.23163 5.89338
+4.4707 5.50457
+9.257 9.27862
+2.11049 2.59654
+1.65501 2.06238
+0.551768 2.10873
+0.0285582 0.194421
+3.66153 3.85615
+5.07097 5.55806
+5.29145 5.80735
+2.03499 3.0863
+0.73171 2.29494
+2.63023 3.6417
+6.17478 6.25997
+5.79646 6.46363
+9.10633 10.5516
+7.23415 7.84823
+6.49951 7.1506
+9.94647 10.0242
+7.91236 8.09097
+7.8127 7.97662
+3.34238 3.42907
+8.50796 9.8311
+8.75792 8.98028
+9.34125 10.4441
+2.84413 3.71602
+1.49884 2.35652
+7.52317 9.18955
+9.5587 10.3525
+4.85436 6.1181
+5.91369 6.12194
+6.88463 8.34471
+1.51952 2.99156
+4.29022 5.12674
+8.0229 8.41246
+2.44841 3.04779
+7.59975 7.91485
+2.74491 3.62575
+0.0169968 0.240919
+5.85351 6.29039
+4.99825 5.93439
+2.153 3.35304
+1.19032 1.41763
+6.13337 7.80615
+7.05013 7.89364
+8.38056 9.92
+6.35525 6.64521
+3.93342 5.15885
+2.87656 3.47116
+3.56176 4.41159
+6.72084 7.9171
+8.03801 9.12442
+1.03329 2.56255
+7.64542 8.61709
+2.85627 2.89437
+8.8303 9.79838
+1.08032 2.34573
+7.51366 8.39169
+9.09685 10.3677
+6.753 7.41904
+-0.217662 1.42059
+6.72492 7.97553
+7.99325 8.8976
+0.765372 1.10894
+4.37958 6.04671
+8.72027 9.58928
+6.00234 7.29277
+8.43912 9.25356
+2.98816 3.17389
+0.4292 0.552167
+1.69827 2.80318
+5.99904 7.09981
+4.68367 5.87791
+-0.203208 1.09587
+2.65367 3.28472
+3.87051 3.88111
+6.36178 7.18853
+-0.0815935 0.200848
+6.82255 7.18488
+4.99295 5.08405
+2.67155 3.08447
+5.82099 6.77145
+8.76434 9.01086
+5.94982 6.18665
+3.23369 3.71743
+0.934129 2.73456
+1.13233 1.24208
+8.21931 9.03906
+6.25425 6.69972
+0.971299 4.21205
+5.68426 6.45281
+2.85786 3.3955
+8.17715 8.88439
+2.72802 5.01235
+6.12811 6.53711
+5.22878 6.45864
+0.453655 0.922032
+0.466162 0.85262
+2.40916 2.64759
+5.63583 6.37476
+2.18434 3.14105
+0.912811 2.08432
+8.9464 10.1515
+6.77323 7.27133
+0.7167 1.60579
+5.89813 6.32997
+7.66593 8.4611
+6.54145 6.88337
+5.95421 6.21188
+1.10383 1.92226
+5.37168 5.65707
+1.51874 1.66339
+4.60748 5.00384
+8.97354 10.5394
+2.05022 3.20373
+8.17316 8.19283
+2.33792 2.72643
+8.81577 9.3704
+5.95738 6.59855
+5.69025 6.17335
+6.91889 7.88142
+2.17529 2.81528
+6.65046 7.19698
+7.10694 8.78046
+2.09613 2.47484
+1.92423 2.25333
+-0.0906039 0.861376
+6.61481 7.70609
+6.7448 6.84276
+3.43655 5.28405
+6.05404 6.48902
+3.24637 3.36149
+5.69528 5.77157
+5.12352 5.31024
+7.65858 8.80828
+3.69209 4.4851
+0.25765 1.29637
+3.1537 4.13191
+3.12328 3.83765
+2.99798 4.8748
+4.49566 4.67827
+3.50822 4.03987
+8.00334 8.34084
+8.61039 9.00704
+0.0332147 0.166124
+4.55193 5.36546
+4.20308 4.31589
+0.955466 1.20095
+-0.382972 1.47625
+0.803913 1.01916
+3.78333 4.0707
+6.58604 6.70173
+3.02066 3.82562
+1.16515 2.2816
+7.87242 8.24214
+4.057 4.60368
+2.84714 3.59726
+2.77804 3.69136
+-0.139996 1.36416
+4.50647 6.37579
+8.86647 10.1549
+9.24372 10.1442
+0.743107 1.84722
+6.18761 7.65841
+0.214887 0.443938
+8.8513 9.55063
+4.04856 5.79916
+6.69671 7.10025
+6.97477 7.79702
+4.82551 5.10538
+0.821772 2.85828
+9.3086 9.74805
+5.45623 6.66668
+7.64296 8.67451
+7.53052 8.31024
+7.45352 7.5063
+1.31412 1.4979
+7.81176 8.48083
+0.228964 1.73207
+5.52579 5.93103
+6.58544 8.48938
+2.75407 4.18746
+3.21396 3.96298
+1.13806 2.34106
+0.899331 2.87945
+5.69016 6.61624
+2.48172 2.58082
+0.676004 1.43405
+3.41766 3.9503
+0.104554 0.298373
+6.50673 8.21831
+6.00349 6.69385
+9.62453 10.3147
+4.09379 6.02911
+-1.12803 1.68823
+1.83324 3.43133
+8.30576 9.09288
+-0.363911 0.405218
+1.91686 3.34928
+6.98331 7.15885
+-0.31591 0.996789
+0.145813 0.35408
+5.32016 6.13679
+6.99664 7.48644
+-0.140875 0.821045
+9.0119 9.19742
+1.69616 1.72453
+4.38064 5.07542
+6.85898 7.55478
+3.9145 4.27935
+5.77592 6.16806
+1.45345 3.01301
+4.13024 5.59662
+8.14557 8.41669
+4.00075 4.829
+-0.283024 1.59436
+5.92468 7.17507
+6.84458 7.18356
+1.06987 1.42839
+8.618 8.66235
+0.432802 1.59512
+3.78058 4.36051
+1.6113 4.21135
+6.73475 7.01057
+6.74819 6.90498
+6.93146 8.54681
+9.02605 9.91613
+3.888 4.00526
+1.07958 2.27915
+4.78456 5.10764
+3.92952 4.89555
+9.09348 9.30304
+6.73107 7.21036
+7.42366 7.73225
+4.04079 4.72919
+1.21726 1.34683
+8.82903 9.73504
+0.577663 1.00786
+1.56822 2.08675
+4.84315 5.44994
+1.01008 1.16524
+5.99782 6.01535
+0.996739 1.75305
+4.76128 6.39012
+8.93563 9.51972
+-0.0698166 0.453543
+5.9084 6.95139
+0.535401 0.692258
+4.80729 5.48335
+3.42581 4.76147
+3.58715 4.43541
+7.50236 7.71227
+5.19742 5.87901
+1.79752 2.43097
+7.29762 7.57608
+5.65169 6.47762
+6.02249 7.93642
+0.840131 2.81176
+6.2646 6.96911
+7.46014 8.17136
+9.79049 9.94054
+4.61094 5.35819
+7.30902 7.41873
+1.21883 1.84621
+6.41743 6.57736
+1.53114 1.62859
+6.73237 7.47083
+6.05618 7.56831
+7.63374 8.16821
+5.20839 6.05382
+0.619043 1.44065
+2.38657 4.88786
+3.88289 5.18788
+4.42283 4.51106
+9.15575 9.22388
+3.18678 3.72243
+3.20638 3.65935
+4.2219 4.97961
+4.63725 6.90959
+2.57123 2.59101
+4.08581 4.37325
+6.53926 6.80412
+1.77475 3.89149
+9.22854 10.426
+2.67375 4.36551
+3.17194 4.0433
+1.10304 2.0348
+3.67233 4.04957
+3.23526 3.5012
+5.17684 6.47301
+4.4 4.67662
+4.15842 5.85903
+5.88496 6.61616
+7.26489 7.51279
+4.17402 6.6997
+-0.540216 0.54573
+4.36063 4.60442
+9.18146 9.96239
+0.977216 2.42032
+9.09143 9.61178
+5.06686 6.23076
+2.04772 2.92048
+1.4154 2.00707
+7.80442 9.54824
+4.55549 4.7148
+7.56964 8.80172
+1.35347 3.21648
+9.12751 10.0605
+1.81735 2.06061
+5.63798 8.0918
+6.79492 7.98002
+9.23053 10.1299
+1.74639 2.02724
+3.71825 4.09879
+2.4995 3.42493
+4.1255 5.66758
+4.75493 6.99687
+8.22481 8.72036
+6.13689 7.53026
+5.41315 5.66358
+4.21425 5.62743
+6.22936 6.44392
+2.02303 2.96414
+-0.0655462 0.130508
+6.1487 6.70994
+4.36674 6.24985
+7.51129 7.63176
+7.9729 8.98613
+3.92117 4.15596
+4.54398 5.43399
+6.34248 6.92305
+-0.550253 1.16167
+9.15142 9.53717
+8.99354 9.65952
+6.28988 7.90053
+3.36505 3.782
+8.80005 9.70553
+1.99947 2.18573
+1.15023 2.07069
+0.253723 1.32958
+2.0392 2.93977
+2.89024 3.00836
+8.16735 8.2049
+1.49508 2.95258
+6.19092 7.44552
+2.33328 3.06758
+6.44166 7.4649
+7.34749 7.79488
+7.5557 8.04141
+2.76812 5.13617
+7.97308 9.25668
+4.73539 5.22234
+7.53377 8.41651
+-0.355405 1.36499
+4.72111 4.73744
+-1.22753 1.84842
+5.5033 5.63808
+3.95421 4.19313
+6.24752 6.98229
+4.49694 5.07277
+3.70871 4.30093
+1.31984 1.50116
+7.16044 8.70868
+2.44587 3.34659
+6.08322 7.20376
+2.75012 2.82555
+0.0394442 0.863634
+3.90896 4.73696
+4.77494 5.04158
+8.41473 8.82932
+1.7049 2.71024
+9.01684 10.1044
+4.57959 5.01066
+3.2484 4.21875
+1.11596 2.88792
+3.53616 4.14001
+5.80672 5.82478
+5.85844 7.70293
+6.18239 6.30124
+2.22913 3.23412
+2.97521 3.08481
+2.2749 3.70611
+2.3457 3.86609
+2.71695 4.04473
+7.22863 7.40115
+1.80428 2.39815
+1.80781 2.33028
+2.78662 3.14936
+9.40717 9.94906
+6.54968 6.80773
+2.76862 3.24492
+1.96034 2.87404
+3.53295 3.54927
+5.36042 5.67073
+8.63339 8.93752
+0.932415 1.70402
+4.32923 4.55594
+9.3491 10.4969
+0.121416 1.15499
+-0.172998 1.36319
+2.02349 2.29887
+1.75352 2.35329
+0.502555 2.01665
+6.71754 6.80014
+3.35175 3.93337
+7.17133 7.9851
+8.51299 9.95771
+5.86103 6.36734
+1.44593 3.46008
+4.49699 4.60855
+2.29261 3.10053
+6.68713 8.19499
+5.43776 6.84387
+8.58591 9.02134
+5.24746 6.15595
+1.3847 2.5074
+6.62143 7.07775
+1.7101 2.077
+9.70898 10.2789
+6.67451 7.92058
+2.56858 3.60374
+1.61917 2.60482
+1.77902 2.16908
+4.76209 6.00461
+3.8894 3.98269
+7.0278 7.276
+5.4866 5.59417
+1.69306 2.92506
+2.45744 3.76592
+2.5689 2.80611
+5.98283 6.06154
+9.5267 9.9626
+9.55652 10.4128
+6.6111 6.64606
+3.38826 4.26111
+3.61887 3.73455
+4.14924 6.13796
+7.15863 7.28212
+5.78984 6.56662
+2.09304 2.2681
+4.39867 4.88557
+6.20907 6.81034
+4.63336 4.91476
+0.939805 2.43621
+1.56774 5.13599
+8.40908 9.82058
+2.06273 2.20306
+2.53524 5.01482
+2.9314 3.23661
+2.48535 3.47368
+0.366389 1.4699
+8.81131 9.01654
+2.05102 2.87972
+1.9699 2.22723
+6.18333 6.98224
+1.3425 2.4443
+0.767883 1.77423
+3.1538 3.43248
+0.891006 0.903458
+5.7136 5.8713
+0.437569 1.37539
+3.98533 5.01646
+8.65764 9.89518
+3.74889 3.98561
+7.74507 8.30657
+8.24671 8.43006
+6.88467 7.42036
+1.99426 2.03522
+1.90486 2.04181
+1.12911 1.71807
+9.25253 10.105
+1.92989 2.0346
+5.60044 6.25585
+9.16848 10.087
+6.67824 6.72257
+1.88522 2.80222
+0.242758 0.852689
+5.09249 7.71484
+5.54974 6.44414
+7.66767 8.72936
+3.48884 3.83156
+3.4697 5.14646
+8.48582 8.7692
+6.76259 7.06897
+7.83856 8.62005
+5.81853 6.76571
+2.04803 2.94439
+6.85396 7.22985
+6.52449 7.39764
+9.26838 9.34809
+4.64449 5.64975
+7.51845 7.80279
+-1.27268 1.65344
+0.686101 4.20373
+7.80552 8.37119
+7.20419 8.35284
+9.33962 9.87975
+4.31238 5.58683
+2.39198 3.84398
+1.29248 2.59269
+4.71612 6.195
+5.27332 6.52174
+7.71492 7.84702
+8.18064 8.72233
+1.55223 2.31294
+6.34374 7.31758
+6.48966 6.92611
+2.62268 3.09895
+4.09064 5.06197
+2.66367 4.12126
+1.53391 2.93092
+8.64516 8.70655
+9.20047 9.28957
+4.00474 4.11716
+8.5418 9.45901
+8.73386 9.73253
+9.22596 9.63179
+1.34204 2.7834
+8.4489 9.21027
+7.75158 8.51085
+5.98856 6.11212
+1.29906 2.08111
+9.24315 9.76291
+6.84345 6.91607
+5.88294 5.90545
+3.03022 3.39941
+3.22222 3.4089
+1.12791 1.65898
+6.70232 7.36336
+8.60042 8.82377
+1.26451 1.30362
+2.76682 2.92693
+1.54763 2.19582
+6.5865 7.24173
+4.15242 4.21742
+8.39615 8.78524
+1.67017 2.08717
+9.03012 9.97041
+2.31463 2.45877
+8.29872 8.51813
+1.66689 2.51919
+-0.807606 1.47794
+1.31452 1.94418
+0.0739222 0.512106
+4.23577 4.25889
+7.45273 7.97505
+3.34234 3.46608
+7.97304 9.14131
+1.9029 2.99946
+8.84087 9.79689
+4.92769 5.68685
+2.74004 3.04513
+0.889257 2.20448
+3.10574 3.9758
+3.91547 4.32303
+7.17475 8.07377
+5.92903 8.03738
+1.57974 1.65527
+3.76339 4.2285
+2.28263 2.7559
+9.53105 9.87477
+2.10154 3.2222
+4.23683 5.34347
+1.38769 2.48482
+5.39838 5.51872
+8.50975 10.1382
+8.04108 9.21474
+8.5252 9.67823
+8.893 10.7726
+7.1294 8.18211
+1.15642 1.73882
+0.436911 0.756698
+3.66142 3.71659
+6.37686 6.7
+8.88506 8.99896
+2.31891 3.79061
+2.61615 2.81909
+1.35216 1.39571
+3.04217 3.52564
+7.8409 9.34099
+0.470596 1.49157
+6.94014 7.18365
+8.05483 8.49979
+8.18511 8.25608
+7.03597 8.45251
+2.47411 2.65172
+0.112716 0.193057
+4.45039 5.10584
+4.53906 5.80013
+5.11702 5.27151
+1.24211 1.90757
+4.64114 4.72912
+1.77254 3.45037
+-0.1275 0.99675
+5.69637 7.67722
+2.21252 2.44032
+3.89623 4.40192
+2.79904 3.15569
+8.37911 9.42424
+5.27199 6.2026
+1.84791 3.75411
+0.522801 0.54806
+3.83644 4.64785
+6.65497 7.55638
+6.75104 6.98564
+2.34979 2.98049
+8.27176 8.60459
+5.07773 5.44064
+1.16934 1.98872
+4.2914 5.37557
+6.83462 7.95408
+3.91405 5.73229
+7.77473 8.53538
+9.23441 9.90185
+4.03659 5.2473
+5.99336 7.8004
+4.2432 5.89276
+6.39847 7.81276
+9.13909 10.4164
+1.12009 2.5649
+2.35157 3.18468
+4.46918 5.55572
+3.82512 5.53666
+7.18238 8.10193
+8.40911 9.23639
+8.99555 10.4192
+6.69547 8.87825
+4.79012 5.34858
+9.23615 10.0986
+-0.590587 1.14603
+2.74289 3.48244
+-0.248403 1.1591
+3.35663 3.7229
+7.37504 7.6481
+6.64796 7.64695
+0.778081 2.41212
+4.49242 4.7772
+8.01419 8.109
+6.6494 7.76619
+8.86331 10.1205
+0.817273 0.937855
+8.00019 8.21556
+6.19405 6.54794
+6.11798 7.30421
+3.40164 4.28921
+5.31927 6.21584
+2.79377 3.40938
+3.59494 3.90321
+7.79218 10.3132
+2.99546 3.86111
+1.71916 3.40283
+6.1768 6.81915
+7.59629 8.68568
+1.59724 2.348
+6.20151 6.5391
+6.30798 6.70478
+0.489786 1.51322
+1.28396 1.86775
+5.18031 5.43007
+6.61276 7.70565
+1.4909 2.11165
+4.56163 5.49277
+1.93598 4.35147
+3.65568 5.00224
+1.68028 2.00363
+7.82874 8.67399
+1.23053 2.87598
+-0.164275 0.194491
+2.58349 4.01302
+1.23279 2.02984
+0.599702 1.09257
+9.50965 9.80164
+2.33108 3.58037
+4.38659 4.62378
+2.65097 2.87349
+0.0537058 0.576502
+4.20415 5.15693
+5.41458 5.98382
+4.37747 5.10347
+2.62536 2.70073
+6.96845 8.15356
+6.91533 8.41638
+9.36431 9.58863
+6.13019 7.25915
+2.7818 3.4951
+9.44641 10.1301
+2.68817 4.19772
+5.65664 5.6814
+8.25308 10.498
+3.50374 3.64458
+1.47063 1.78567
+8.21901 8.98152
+3.99261 4.47339
+2.51395 3.38788
+4.66178 5.24959
+9.08415 10.3467
+5.92351 7.20447
+1.74145 2.35957
+7.62653 8.96797
+6.43542 7.68775
+5.49047 6.56355
+4.9225 6.22555
+0.257967 0.704837
+3.42488 3.52873
+8.67606 9.77824
+5.12981 6.37856
+5.97359 6.32151
+1.58517 2.28129
+0.530687 1.54545
+7.04056 8.15296
+1.8541 3.1902
+9.46286 10.0098
+3.17967 4.02237
+3.49966 3.80271
+6.24894 6.49618
+1.19944 1.59215
+5.30422 6.94823
+7.49137 7.78584
+7.02669 8.16282
+2.21673 3.36471
+7.66183 8.34763
+4.13876 4.87421
+3.0199 4.07124
+8.40439 8.82943
+-0.274649 0.429602
+6.11215 7.65609
+3.34781 5.03006
+1.28231 1.77258
+7.57256 8.59456
+5.36208 5.81735
+7.18511 8.96618
+8.86053 9.49567
+5.39097 5.93211
+6.59094 7.26553
+3.69159 4.01914
+8.73797 8.81611
+1.41144 1.82827
+7.83555 8.07567
+6.13821 8.44907
+5.83432 6.48744
+2.93596 4.66271
+7.03215 7.59658
+1.65252 2.45337
+2.91358 4.90129
+8.94415 9.14642
+5.21005 6.1166
+0.33225 1.17039
+7.40089 8.07586
+9.30427 9.40776
+2.34188 2.81124
+1.02811 3.3344
+6.28117 7.62089
+4.80105 7.10049
+8.90252 10.0057
+2.20932 2.33093
+8.20746 10.6268
+4.31887 5.23945
+9.258 9.8985
+3.80742 4.15057
+1.11313 1.23711
+9.53067 9.70165
+7.95467 8.67187
+9.66031 9.83223
+3.61385 4.09571
+0.623148 0.652817
+7.77809 8.62118
+0.86157 1.98606
+3.12528 3.75815
+1.9363 3.22621
+8.23521 8.99175
+8.95406 10.4487
+3.38526 3.90652
+0.34281 2.0226
+0.739384 0.793829
+3.55637 3.96384
+6.1562 7.28647
+5.30211 7.51385
+1.46275 1.78688
+-0.0144662 0.868488
+0.0740443 0.119828
+9.26206 9.83923
+0.743397 1.40754
+4.68823 6.62985
+8.8291 9.17373
+4.66711 5.09313
+4.023 4.44994
+5.68937 5.79194
+8.04835 8.06763
+6.94662 8.00075
+0.774686 1.13428
+0.381819 2.34757
+2.1235 2.63524
+5.42795 6.89998
+6.07662 6.29083
+6.47821 6.7872
+2.58305 2.6192
+-0.598336 1.23458
+4.29089 5.43332
+8.09914 8.28229
+5.05925 5.35258
+0.181705 0.444466
+3.27849 4.79932
+0.310314 1.43125
+1.13836 2.76825
+1.2529 4.09336
+0.198106 0.608625
+1.77442 2.23777
+6.29823 6.64574
+1.22125 1.37929
+1.77592 3.04011
+1.43999 2.90926
+4.20495 5.32396
+4.98874 5.33211
+8.36483 8.67875
+5.65373 7.14132
+2.8303 3.05037
+3.41509 3.54032
+7.21702 7.85857
+5.79848 5.8913
+4.52711 5.65511
+2.04663 2.66919
+5.76363 6.77903
+-0.153046 0.77878
+4.37474 4.49936
+6.86786 7.81999
+8.92084 9.16368
+7.5975 8.56954
+0.197493 1.07503
+3.99803 4.67019
+9.35123 9.60094
+1.46442 2.4256
+5.21501 5.79612
+8.80879 8.99085
+-0.109252 1.30631
+7.34965 7.87947
+7.08703 8.12723
+0.985946 2.14663
+0.48521 0.856118
+6.57719 6.70623
+8.71165 8.72286
+3.16883 4.8714
+-0.21189 0.412944
+3.6526 4.37121
+0.364649 1.3363
+9.27722 9.35135
+3.47517 3.8793
+5.67149 6.28631
+6.52789 6.61039
+9.36323 10.4189
+4.30743 6.18638
+7.93653 9.4877
+8.24024 8.41475
+2.75692 3.13935
+8.80223 9.1489
+3.42656 3.90557
+8.96598 9.3217
+1.99582 4.84803
+5.1178 5.8688
+4.47901 5.73433
+7.30397 7.85527
+0.18463 0.656832
+7.80806 8.41666
+8.50023 9.42628
+7.67563 8.64756
+9.46783 9.52169
+2.06797 3.3107
+5.08863 5.10167
+0.82146 1.39055
+7.5428 8.04736
+9.09407 10.8208
+9.15219 9.99706
+1.61637 3.46354
+5.3812 5.96247
+9.34115 9.73575
+6.49221 7.30031
+1.56337 3.39704
+8.463 8.60841
+-0.322779 0.658242
+8.50173 8.72125
+0.854851 1.83405
+7.81945 8.12841
+2.60724 3.19985
+5.03714 5.55331
+1.85041 3.36816
+7.26119 7.64364
+5.75223 5.99653
+4.00026 4.43863
+5.00939 6.03009
+6.22879 6.6638
+6.44231 7.18622
+1.66002 1.88587
+2.59781 2.84919
+4.96399 5.40545
+5.70327 6.95018
+6.97141 7.08346
+3.98535 4.6179
+5.96795 7.14997
+5.07581 5.8262
+4.65665 4.98851
+8.65646 8.70986
+3.04175 3.19155
+0.796073 1.0952
+8.24859 8.57828
+5.26952 6.34245
+7.94685 8.78542
+0.193963 0.968524
+6.61159 6.80186
+9.37533 9.79195
+8.94048 9.74959
+5.77272 6.48616
+6.0092 7.86718
+2.52621 2.58938
+8.91347 9.22421
+4.20466 5.45909
+4.82157 5.09167
+7.35464 7.36611
+5.12413 6.45063
+2.12404 2.81187
+8.88875 9.20752
+2.59731 3.20587
+1.54772 2.08968
+6.70449 7.08952
+-0.0967146 0.888521
+3.10207 4.34815
+1.20807 2.35497
+6.00753 6.08492
+3.21837 4.00446
+4.34095 6.0963
+4.24821 4.79576
+4.49523 6.6669
+1.49483 2.52552
+0.0411497 0.641526
+8.3854 9.20954
+8.12419 8.93702
+0.0201515 1.06914
+1.57617 3.44176
+1.4173 1.76847
+5.42261 6.51539
+6.6744 8.46109
+3.05234 3.59179
+6.49059 7.24618
+7.01989 7.69901
+2.34664 2.90601
+9.17324 9.86754
+5.50919 5.70258
+2.40486 4.6009
+3.74368 4.00093
+6.9211 7.33554
+7.41358 8.7413
+8.78284 9.62033
+2.96753 3.01602
+-0.200693 0.535532
+6.4383 6.45049
+8.28835 9.42148
+4.2379 5.35128
+4.68397 5.04593
+5.7185 7.03177
+5.37494 6.43977
+2.99518 4.08138
+7.28064 7.54638
+9.10622 10.4907
+1.23839 1.50915
+6.7823 9.24533
+8.45679 8.62427
+0.106718 0.69304
+2.84119 3.50375
+3.60466 4.51338
+8.04709 8.19023
+3.31632 3.48054
+5.9027 7.46331
+-0.621072 1.13003
+8.57167 8.69262
+0.301047 1.42246
+1.24229 2.44616
+0.962706 1.55754
+8.77327 9.55275
+1.77899 2.44335
+0.368575 1.84726
+9.05918 9.07832
+6.61723 7.68015
+8.59899 8.80383
+-0.133927 0.20271
+5.69266 5.74809
+0.68202 1.52342
+7.17359 7.91482
+5.74049 7.34297
+7.88371 7.9683
+1.58749 2.26543
+3.96728 4.45988
+5.4354 6.88336
+1.68706 1.6976
+6.56907 7.40696
+0.518151 0.724124
+8.99155 9.36995
+6.00506 7.91529
+5.26967 6.11536
+2.37416 2.50887
+8.47983 9.31509
+2.38155 2.54346
+8.08415 9.65214
+1.00693 3.19203
+1.6523 1.73553
+6.85283 6.9958
+4.11425 4.90193
+1.39597 1.58725
+5.05551 5.19458
+5.89969 6.11394
+5.9148 7.26824
+9.32271 9.93989
+1.62911 2.58215
+5.43399 6.14203
+3.11393 3.58792
+8.57619 9.3788
+2.23349 2.7884
+8.09022 8.54326
+9.7114 9.87076
+5.91086 6.10885
+7.35805 7.57276
+0.650002 0.879866
+3.24977 3.75531
+2.73948 3.41051
+3.08006 4.62772
+3.71868 4.31519
+4.13905 5.78577
+1.77297 3.02983
+5.85931 5.89333
+3.68972 3.93193
+1.43922 2.98425
+6.51534 8.33386
+6.6821 7.50874
+1.2541 2.11722
+5.40634 5.54411
+4.55502 4.60346
+4.32484 4.68497
+3.40711 4.31975
+9.20893 10.0853
+6.12594 6.9009
+0.12664 0.347193
+7.53378 8.82258
+7.79572 8.91645
+2.50098 3.39701
+4.17873 4.97732
+1.05822 2.47032
+3.1012 4.97736
+8.42126 8.74568
+7.83301 8.17843
+9.26618 10.584
+3.02667 3.7128
+8.30654 8.69242
+2.87173 3.43275
+6.59917 7.54843
+7.03447 8.20283
+5.75718 6.40637
+2.62899 4.1855
+-0.520148 0.902194
+5.1538 5.61763
+1.25625 2.33142
+4.16336 4.3384
+3.01296 3.41026
+3.16515 3.26305
+2.40944 3.21897
+6.80742 8.57141
+1.15125 1.54824
+8.72251 9.50878
+3.15703 4.04482
+0.470308 0.726093
+0.199979 0.878243
+7.8908 9.17915
+6.91793 7.16038
+4.64783 5.00217
+2.21237 3.03073
+1.5825 1.63362
+3.18806 5.20795
+5.92725 5.95595
+4.65027 5.09868
+6.42204 6.87201
+8.08637 9.40221
+4.95542 6.16185
+7.45987 7.57979
+8.826 9.13961
+4.42078 5.27977
+7.26216 8.97585
+2.26919 3.33512
+9.4077 9.81908
+0.722223 1.03378
+-0.0497795 1.19355
+8.22686 9.31082
+0.0733766 0.93037
+7.47883 7.9062
+5.28731 5.74181
+1.78496 3.61348
+0.690987 0.764344
+2.56442 3.54999
+4.27944 5.43124
+4.04412 5.35376
+0.663756 1.88268
+1.73567 1.78553
+8.07666 9.41842
+7.70138 8.42873
+9.27113 9.55873
+0.982413 2.5565
+0.994807 1.02007
+5.01226 5.31923
+8.87435 10.0597
+1.74836 3.22578
+0.151528 0.191719
+5.82608 6.06438
+1.17239 1.59955
+3.18515 4.11049
+1.92258 3.70604
+1.63692 1.8266
+1.83542 2.66228
+2.21954 3.11425
+3.97546 4.3928
+0.731374 2.05705
+5.44809 5.96359
+9.85934 10.0553
+8.42169 9.63654
+6.68148 8.43446
+2.00014 3.3485
+0.735924 1.73
+1.61833 3.05643
+7.87934 8.67316
+8.67441 10.0032
+0.794573 1.2493
+6.11926 6.41441
+5.2715 5.82597
+9.41854 9.46625
+3.46299 4.06742
+5.6487 5.79053
+1.46503 3.43496
+0.9957 1.53939
+2.4714 3.1301
+0.887049 1.6196
+3.04884 3.19662
+1.24337 2.05758
+7.61142 8.55766
+0.998279 1.64425
+4.74917 5.85236
+2.97632 3.94611
+4.11786 5.62709
+7.40498 7.62083
+1.47854 3.64736
+2.1176 2.64511
+4.55533 5.89436
+7.44618 9.79926
+-0.410242 0.737348
+5.719 6.30861
+8.33692 8.38222
+8.78122 9.98195
+3.75452 4.26866
+2.23771 2.44985
+6.72455 7.61362
+5.9797 6.58846
+6.72885 7.60315
+-0.710302 1.18332
+7.73287 9.383
+6.61213 7.67394
+4.12945 5.68527
+-0.300887 0.341615
+5.77978 6.41534
+8.34001 9.96874
+1.62323 1.8283
+1.71788 2.23905
+7.43484 8.0418
+3.47322 3.8047
+3.47311 3.51261
+7.82093 8.86377
+2.46973 2.99125
+7.91166 8.55065
+3.39807 3.43599
+8.94792 10.0437
+7.70859 8.32487
+5.86852 7.13103
+7.64996 9.19033
+6.66742 7.8092
+7.88241 8.58675
+9.42939 10.3479
diff --git a/bottleneck/tests/data/test_012_B b/bottleneck/tests/data/test_012_B
new file mode 100644
index 0000000..5f6e43c
--- /dev/null
+++ b/bottleneck/tests/data/test_012_B
@@ -0,0 +1,5000 @@
+1.17434 1.46837
+2.58198 4.16589
+0.234041 0.968658
+1.52703 1.59579
+6.7103 7.44033
+3.19227 4.41539
+5.42556 5.57369
+3.45417 4.86089
+3.82256 4.1092
+7.82551 7.90784
+3.9384 4.71796
+5.60335 5.9054
+7.96663 9.8987
+6.30305 6.64853
+7.33246 10.5316
+0.623312 1.09008
+2.63041 2.64616
+5.36028 6.28956
+4.64202 5.91858
+7.55219 7.96304
+7.73736 9.18221
+1.67114 1.84851
+5.07514 5.12159
+7.03732 7.05228
+7.5006 7.59212
+0.244947 1.55875
+0.0170454 1.10485
+1.95394 3.53669
+5.66015 6.01949
+5.88211 7.64639
+7.46698 9.27085
+6.37429 7.10154
+4.54535 4.81932
+8.21203 9.35896
+4.89933 6.20802
+3.68683 4.17831
+0.477467 0.828394
+6.17871 6.77834
+9.77523 9.92676
+0.854808 2.38709
+7.93326 8.3553
+2.10917 2.27771
+4.07045 4.72793
+8.2016 8.8011
+2.9205 3.95746
+2.89806 4.39725
+5.5654 5.78669
+9.5219 9.98543
+7.08591 7.19588
+8.35359 9.57893
+9.81348 10.0345
+8.5994 9.71835
+5.43903 7.25234
+1.82768 2.92724
+4.44952 6.79754
+5.66747 7.34386
+5.88153 6.39253
+3.34008 4.22032
+2.46068 2.76051
+0.370778 2.61681
+6.02508 6.26809
+4.32654 4.93262
+7.41536 7.99616
+8.84229 9.87911
+3.8551 5.84353
+1.56832 2.34694
+6.96099 7.42028
+8.15753 8.72014
+9.23141 10.3815
+7.4484 7.80228
+0.473671 0.874895
+3.15689 3.50687
+3.58122 4.09945
+3.55022 3.74767
+4.42708 5.80211
+4.40956 4.68699
+3.80576 4.61856
+7.29965 8.28614
+7.40582 8.15308
+1.69789 1.77669
+1.66419 3.44308
+0.473997 0.872506
+7.83959 8.52898
+6.22416 6.36949
+-0.187159 0.871822
+0.232336 0.585965
+9.29905 9.44357
+1.4459 2.40589
+2.83008 3.19758
+1.15291 2.12112
+2.58686 3.33896
+6.79362 7.88068
+0.228178 1.48318
+5.60001 6.20258
+4.97803 7.10992
+1.70429 1.962
+2.72659 3.13886
+9.22714 9.25889
+3.84694 3.88778
+-0.282077 1.48155
+9.28756 9.58517
+4.34069 5.59751
+8.63909 8.76839
+8.86236 10.7642
+6.77597 8.41888
+7.30621 8.64164
+0.685607 1.22755
+2.91514 3.22638
+2.72098 3.66837
+8.17528 8.32638
+5.19632 5.7506
+7.34177 8.70639
+5.74082 6.35524
+5.95975 6.69284
+9.40187 10.4488
+2.92761 3.36735
+0.399531 3.13082
+4.83399 4.92635
+7.74539 8.56852
+1.76322 3.5086
+6.54479 6.72963
+7.64362 8.12404
+1.35542 1.45313
+0.214385 0.718085
+1.7006 3.21962
+5.91009 6.47862
+2.21093 2.34636
+5.96919 6.79365
+6.59951 8.22203
+1.54571 1.59397
+3.27012 3.79128
+0.32455 0.622995
+1.73926 2.78017
+9.81035 9.84077
+7.38441 7.85171
+8.90372 9.34186
+7.26323 8.41174
+5.7363 5.97348
+8.25473 10.1281
+2.3981 2.52096
+8.53783 9.63442
+8.51755 9.2735
+6.48614 6.773
+3.40182 3.65137
+2.1353 3.04852
+2.95397 3.73285
+6.98063 7.4963
+4.50189 5.26384
+0.21416 1.49363
+0.632196 1.36307
+6.57833 6.60481
+8.0634 9.33903
+2.79759 2.94462
+4.43747 4.58861
+6.48733 6.86569
+2.28008 3.47037
+6.87452 7.77431
+-0.156821 2.71557
+0.72595 1.78862
+1.97586 2.38196
+8.61839 9.1468
+4.55496 5.68986
+0.26923 1.15728
+9.63757 9.7236
+1.39497 1.96698
+4.8643 5.04172
+6.64675 7.66435
+2.56256 2.6015
+-0.381989 0.611211
+0.676336 1.26896
+8.95304 9.03243
+5.62058 6.07997
+3.36522 4.04276
+8.64868 10.5024
+4.75813 5.19834
+1.96608 2.05864
+9.01449 9.10397
+3.72786 4.51921
+5.6938 6.96584
+1.73499 2.9314
+2.73099 3.41409
+8.77171 9.07665
+4.63865 4.67649
+8.6698 9.30782
+-0.168259 2.09581
+9.29672 9.56
+0.372544 2.60567
+0.450487 1.32919
+6.95341 7.6399
+3.4403 5.24993
+5.53469 6.97831
+-0.79664 1.21306
+5.68831 6.14413
+8.85601 8.95444
+3.83309 5.211
+5.51573 6.5114
+3.64009 3.99648
+4.40759 4.99283
+1.85198 2.6457
+2.72645 3.74803
+2.04751 3.00998
+3.19365 3.9383
+8.09529 9.45596
+8.88173 9.5618
+0.609816 2.67806
+1.57288 2.60884
+1.68354 1.80124
+4.92058 5.9959
+1.48728 1.84885
+0.299669 0.413905
+9.02156 9.56731
+7.50854 8.49023
+0.667131 1.89987
+2.22472 2.58793
+5.84395 8.79426
+2.35839 2.66935
+3.43111 3.69982
+6.71023 7.36801
+6.75697 9.0991
+2.35352 2.85316
+6.73054 7.39006
+9.48673 10.1493
+6.71226 6.72805
+9.22083 9.71889
+8.36513 9.33921
+0.0652672 0.319993
+3.26467 4.60881
+7.62269 7.79878
+6.48608 6.69515
+6.21737 6.88645
+6.56094 6.9699
+1.61317 2.7167
+5.08621 6.29754
+2.24676 2.8076
+3.09943 3.93921
+9.74093 10.0968
+0.417699 1.6381
+9.2958 10.2973
+3.6663 4.1369
+0.0229943 0.448065
+9.2928 10.1833
+3.66334 4.22032
+0.812172 2.19952
+7.88025 8.71192
+8.69379 9.34922
+1.70691 2.95352
+8.28737 8.29985
+5.22491 5.354
+4.03526 4.14084
+6.49359 7.05924
+0.24853 1.44718
+7.86936 8.75135
+5.76 6.68919
+5.85437 6.14314
+5.86292 6.0516
+2.35692 2.91295
+0.0990674 1.29386
+2.9911 3.56188
+0.552671 0.638929
+5.80756 6.22761
+1.21067 1.77175
+4.51882 4.72936
+1.99969 2.89732
+3.65968 6.61987
+0.478582 1.33355
+0.259061 0.289813
+3.89264 5.02474
+0.349236 0.438003
+7.70442 8.1729
+7.90389 10.1876
+3.06898 3.15219
+4.77811 5.29095
+9.76561 9.89451
+4.14295 4.2489
+0.540224 2.28623
+9.60749 10.2284
+8.49555 9.00307
+7.89668 9.76886
+4.12631 4.70897
+7.87898 7.91814
+9.29858 9.52908
+9.24009 9.91544
+3.73498 4.70275
+5.44467 5.9274
+2.13453 4.85697
+2.29607 2.88771
+0.807842 1.82319
+0.319005 2.08473
+1.62 1.63649
+2.20431 3.23869
+2.00132 2.77136
+6.64752 6.71706
+8.12249 8.28379
+7.55541 7.7813
+3.51763 3.64484
+9.21075 10.2811
+2.24501 2.54426
+5.64566 6.46452
+6.72307 8.56698
+3.91728 4.60262
+4.02535 4.29548
+3.0499 3.53135
+1.30677 2.32194
+9.36908 9.90669
+3.92387 4.33848
+2.87312 3.08243
+4.49167 5.2749
+5.43143 6.74905
+6.94595 9.16539
+1.9784 2.00429
+9.42478 10.2226
+3.7185 3.96576
+9.37729 9.50574
+5.34283 6.89736
+4.95341 5.84626
+2.91654 4.28413
+8.26544 9.3076
+6.23114 7.20273
+1.02585 2.21446
+1.6718 2.29591
+2.28926 2.73452
+-0.648145 1.105
+1.44194 2.18562
+6.78584 8.37985
+2.00402 2.08248
+1.64076 2.04067
+0.0419044 0.455962
+5.51723 5.72098
+5.42117 6.81165
+5.70331 5.81707
+4.97889 5.60741
+3.38797 4.46846
+7.20995 7.66784
+3.45388 4.23386
+3.11057 4.35995
+3.29476 4.04676
+2.0519 2.94719
+5.37101 5.38271
+5.99383 6.64188
+7.48444 7.6377
+2.15043 3.05399
+1.54093 1.83799
+5.59223 5.87222
+5.8005 6.08042
+6.1208 7.22563
+1.2938 2.17454
+4.92405 5.0402
+6.91336 7.79688
+1.47978 1.99762
+9.00494 10.8315
+5.84805 6.15303
+4.95368 5.49096
+8.21704 8.31192
+0.715222 2.33517
+0.904183 2.54741
+3.42349 3.74906
+0.627978 2.37092
+8.41477 8.72651
+3.55373 5.58652
+4.12685 4.61533
+0.775274 1.41263
+4.78915 5.08639
+6.35791 8.15015
+2.88242 3.63509
+2.78526 3.07834
+0.39129 1.15933
+3.26615 4.74531
+8.78873 9.8888
+7.25612 7.45972
+4.97452 5.30012
+0.757255 1.35518
+1.29516 2.52446
+4.66838 4.96648
+-0.0720209 0.832726
+2.68276 3.21123
+8.44253 10.0311
+3.40809 4.70506
+1.09617 2.35452
+5.19302 6.73599
+1.25316 1.58101
+6.2056 7.10099
+7.7666 8.52777
+0.301239 1.37275
+0.522829 0.731575
+6.73869 6.96826
+2.41703 3.20567
+4.94617 6.22052
+5.41524 7.68272
+6.0408 6.29938
+0.0642067 0.600878
+6.32122 6.63505
+3.25427 4.70611
+5.88704 6.1678
+8.71533 9.08476
+6.25575 6.88392
+1.54462 1.56366
+3.95938 4.03326
+2.54671 3.66798
+8.48603 9.10156
+3.37369 4.65454
+5.25469 5.64636
+7.02624 7.36449
+8.17061 8.44321
+9.23147 10.1149
+1.45589 2.25886
+6.47702 8.25307
+7.69088 7.91753
+0.442832 0.616926
+8.35355 8.83222
+7.65142 9.58906
+4.04877 5.17345
+0.76012 1.8686
+6.54877 7.40058
+7.41774 7.65429
+8.69655 9.3325
+4.8302 6.25306
+1.77203 1.90284
+3.67485 4.94569
+6.60162 6.72031
+3.05924 3.35235
+0.0823162 1.3486
+8.42991 8.86331
+6.81596 6.83527
+-0.0174808 1.6745
+-0.758131 1.08928
+4.14423 5.46342
+9.26253 9.85714
+7.42749 8.58214
+4.88849 5.86936
+8.99339 9.38141
+8.85301 9.18285
+2.64303 3.45658
+7.1133 8.66473
+3.50745 3.8629
+7.81615 7.83244
+2.94991 3.8741
+7.91822 8.8362
+-0.0553088 1.19059
+7.35558 7.77948
+2.11257 2.20563
+8.57533 9.16338
+2.3515 3.13009
+4.13239 5.38696
+2.20763 2.93941
+7.2451 7.3211
+0.834388 1.57413
+4.47024 6.17855
+4.75947 6.80913
+2.99607 3.54732
+8.15998 8.80718
+8.94688 9.27971
+4.46335 4.9522
+5.30725 5.69786
+7.63989 7.86974
+6.69589 7.69565
+5.34018 6.08115
+8.59515 9.62264
+1.80557 3.22507
+8.62429 8.94242
+1.34532 1.95042
+8.60707 8.80741
+8.03275 9.40327
+4.30357 4.39095
+8.97954 10.7076
+2.18143 3.51825
+3.98695 5.62062
+2.48813 2.60622
+5.56957 6.43776
+5.18249 5.55459
+3.45373 3.64101
+-0.00345662 0.570597
+3.61127 4.69761
+9.37858 10.6205
+7.24635 8.19639
+4.70142 4.80735
+3.30055 5.14257
+0.860415 1.31635
+4.72924 5.46893
+7.47391 7.72644
+6.22287 6.57754
+0.181652 1.01366
+2.14494 2.80736
+2.16406 3.19383
+8.52991 9.22722
+8.74411 9.06935
+0.575831 1.02699
+2.47315 3.0331
+4.2872 4.59813
+5.82293 7.03604
+2.08982 2.25319
+7.3626 8.41994
+1.23867 3.10885
+7.397 7.78026
+6.78837 7.32977
+0.829368 1.56617
+9.23075 9.35172
+6.76562 7.23578
+0.42851 0.839401
+4.83626 5.5852
+0.150032 2.45322
+2.16811 2.47439
+5.60245 5.81188
+7.43707 7.46519
+0.167317 1.44642
+4.9732 7.58343
+8.67391 10.2957
+0.318592 0.639284
+3.365 4.25929
+7.83683 8.88895
+5.20557 5.30114
+0.940347 1.74022
+5.39149 7.13464
+1.10826 1.27913
+1.9147 2.31276
+0.935283 2.49181
+3.67898 4.33336
+5.10125 6.07734
+0.348807 0.839242
+0.310986 0.58381
+2.03594 2.43119
+5.49755 5.94215
+1.94885 3.34409
+9.66806 9.97883
+4.79099 5.45155
+4.81158 5.30001
+5.17667 5.90019
+9.64168 9.99177
+1.14899 1.22792
+0.466236 0.952985
+6.93679 7.72282
+2.97285 3.23931
+9.22517 9.24315
+7.25783 7.46414
+4.37304 4.51815
+4.01069 4.02979
+0.843132 1.80443
+4.78572 6.04237
+6.02471 6.38074
+4.99536 7.76852
+4.97442 5.17384
+0.731231 1.49497
+2.2797 2.90845
+9.13211 10.341
+4.19545 5.08597
+6.13127 7.09817
+2.65124 5.02208
+5.40235 7.12912
+6.86258 6.91991
+8.24317 8.55273
+7.6877 7.69875
+3.33922 3.53776
+0.089484 0.40755
+1.34909 1.68726
+8.43113 8.72899
+4.90038 5.55994
+0.308089 0.490555
+5.42628 7.1433
+2.11647 2.56987
+3.56934 4.1619
+8.35794 9.24416
+8.8645 9.69151
+5.10701 6.0036
+7.66385 7.8412
+2.89952 4.55221
+6.01533 6.38269
+-0.945182 1.07304
+1.79537 1.85576
+-0.0313338 0.501067
+8.85689 8.87522
+1.61143 1.7773
+9.53229 9.84943
+3.51669 3.81091
+-0.448016 1.10903
+3.16889 3.439
+4.30534 4.36372
+6.20158 8.09618
+2.20949 5.23616
+3.29459 4.17079
+3.90101 4.05611
+5.89688 6.85702
+0.734474 1.04471
+7.84341 8.02702
+8.69431 10.1086
+9.73194 9.92195
+7.63516 7.70631
+8.51416 9.33072
+-0.0712911 0.361001
+2.76979 3.22708
+5.34404 7.5165
+5.64429 5.79865
+0.0755012 0.363483
+5.05631 7.27153
+-0.60164 1.09659
+0.457228 0.876186
+4.27092 5.38033
+8.63891 9.04134
+6.29608 7.04242
+8.97795 9.93013
+5.00385 5.57737
+8.48068 9.44885
+7.35543 7.78492
+3.55698 4.01035
+-0.268117 0.649128
+0.633184 0.66254
+4.54216 4.81132
+6.15574 6.35276
+4.3663 6.36286
+1.45231 2.07039
+7.37031 7.9157
+5.30961 6.3506
+5.80757 5.81762
+4.91767 4.97519
+3.45667 3.60965
+1.7934 2.3807
+4.33289 5.41047
+1.16021 1.29979
+3.75172 4.53521
+3.10835 3.1275
+2.68167 3.00314
+4.10639 4.24094
+4.90776 5.74069
+7.30861 7.86666
+3.52822 3.70998
+5.22222 5.28033
+0.00866476 0.326377
+7.73247 8.61481
+4.25231 4.77499
+8.41148 8.54604
+2.95389 3.63497
+7.76126 9.69124
+6.41218 6.69682
+4.86285 6.44503
+1.84783 1.9065
+4.08788 4.11706
+9.17473 9.50133
+5.15091 5.78649
+1.27694 3.33579
+2.92648 3.37855
+9.37392 10.5123
+4.81878 6.34991
+8.38702 8.83716
+5.07771 6.33618
+1.47438 1.75588
+6.20935 7.11166
+1.08286 1.38
+1.40048 2.0157
+6.60355 7.26234
+5.28396 5.90003
+8.9525 9.59216
+-0.0305792 0.544664
+-0.571491 0.735471
+6.287 7.03679
+5.35225 5.4104
+0.095812 0.605976
+4.33523 4.4048
+6.13288 6.80949
+4.14654 5.5505
+-0.213214 0.260592
+7.56188 7.83088
+7.8132 8.65963
+8.02469 9.3254
+0.00641711 0.420562
+7.49269 8.15849
+9.26359 9.4366
+5.74008 7.86317
+8.62729 9.78825
+4.28946 6.20553
+3.19174 4.54991
+4.16992 4.25203
+2.46138 4.11583
+1.92971 2.16701
+3.43028 3.80842
+6.98297 7.28388
+7.51884 7.55947
+7.79102 9.44326
+0.416342 1.32311
+9.35398 9.85201
+8.72997 9.10384
+6.23398 6.88888
+7.46984 7.4875
+5.92603 6.66938
+1.77761 2.58697
+0.835966 2.06139
+9.63284 10.3565
+6.13677 6.42768
+0.151375 0.382404
+8.10315 8.13441
+5.52283 6.28113
+1.00873 2.44226
+2.5239 3.89871
+5.40599 6.72653
+3.43407 4.0068
+1.22444 1.26601
+7.04395 7.80599
+3.75987 3.77123
+6.43597 7.06249
+8.34435 8.87418
+8.25853 9.04009
+0.415321 2.32725
+0.639046 1.75525
+7.83226 8.12538
+9.55429 10.2734
+3.658 4.35867
+1.8588 3.93292
+7.38922 8.16823
+8.53626 9.23024
+0.848152 1.13412
+6.31667 7.2348
+3.81584 4.62621
+9.24748 10.7408
+2.75953 2.95288
+5.70188 6.62278
+4.22202 4.45368
+3.24616 3.88779
+1.05053 2.09846
+8.67718 9.52693
+2.14107 2.71959
+1.10518 2.69689
+5.01476 5.54139
+4.69244 5.20358
+8.88285 9.93012
+2.55228 2.77382
+6.72118 7.50057
+7.58999 8.71573
+1.83763 2.13481
+4.86135 5.27995
+4.39794 5.42117
+1.42512 2.98262
+4.80489 5.34701
+2.7993 5.13702
+7.52122 8.41729
+9.08613 9.37543
+1.1555 1.3935
+7.34071 8.0428
+8.33361 8.40349
+2.514 2.54741
+8.25732 8.41758
+1.65337 2.57964
+4.20527 5.06565
+0.723443 1.06987
+5.85836 6.64701
+7.908 8.07591
+5.01839 7.0105
+3.15908 5.10364
+4.3574 6.67192
+2.06662 2.46437
+7.5595 8.9108
+7.94919 9.20231
+4.11889 5.49714
+7.28151 7.51881
+1.30685 2.09479
+3.08479 4.47364
+4.50916 5.91511
+7.31605 7.63868
+3.14469 4.07035
+8.38431 8.87993
+7.42277 7.64967
+4.22472 4.26323
+8.49871 8.90746
+7.44431 8.09014
+8.35213 8.7504
+3.85634 4.37584
+9.12975 9.77042
+-0.326056 1.17374
+3.53802 4.06211
+6.81775 6.8467
+8.19106 8.64489
+4.20526 5.37727
+2.74081 3.72143
+0.49642 1.10775
+7.76606 8.00524
+4.79825 6.38926
+1.99478 3.20484
+4.69853 6.29508
+5.73058 7.18643
+8.11708 8.64257
+9.62375 9.84838
+5.95271 6.38989
+9.0193 9.93848
+3.91188 4.10834
+6.065 6.60546
+2.62354 3.60072
+8.53665 9.06824
+6.40691 7.44693
+1.62959 2.5825
+9.4128 9.87031
+6.24697 6.62684
+3.31136 3.45626
+4.80347 4.9935
+9.21711 9.53416
+-0.491547 1.72886
+4.75174 4.87217
+0.86329 1.53331
+2.4586 4.2578
+5.10301 6.2815
+5.08302 5.86788
+6.12434 6.78948
+9.68323 10.0973
+3.52576 4.40424
+4.9925 6.89084
+0.846638 1.80782
+1.09709 1.7685
+8.38592 9.03312
+9.56243 10.2682
+5.03592 6.6429
+7.8609 8.04599
+1.21404 1.31975
+7.47824 9.2063
+1.47849 2.68795
+1.2909 2.06381
+5.21288 5.54616
+6.27218 6.99345
+4.77622 5.08494
+3.30665 4.14735
+3.38947 3.55545
+7.71197 8.53162
+1.10565 1.50806
+0.7889 0.984689
+2.88598 3.33244
+5.70958 5.81232
+5.16567 6.24511
+6.91255 7.25784
+-0.401084 0.753156
+4.81138 6.20671
+1.67301 3.58501
+7.19478 8.25624
+1.24428 2.2523
+4.31631 5.33357
+0.589196 1.02017
+5.69207 6.97803
+2.3854 3.25501
+4.1362 4.91135
+8.9932 10.3184
+7.95871 8.45158
+4.03213 5.26347
+3.09506 4.06425
+-0.0310321 0.738171
+7.35733 7.61512
+2.48488 2.96253
+4.72098 5.69867
+5.5395 5.96914
+3.17854 4.283
+6.50012 7.33744
+1.93266 3.00941
+1.49319 2.71826
+9.0187 9.13099
+7.15259 7.40691
+8.71939 8.93257
+1.57203 3.11249
+0.933429 2.16903
+2.99663 3.71667
+2.06144 2.81311
+7.9072 8.2103
+0.490069 0.614737
+7.84111 9.70812
+1.15363 1.6421
+1.15475 1.43307
+8.2228 9.92116
+7.76825 8.40724
+6.15122 7.31322
+7.1427 7.49294
+2.30516 2.7019
+2.03336 4.03387
+8.3918 9.85707
+8.57214 9.59345
+3.8057 4.1119
+8.9223 9.38556
+9.32051 9.60504
+7.13349 7.69154
+1.71855 2.00425
+5.10333 6.0605
+-0.149137 0.80973
+0.466224 3.1698
+4.19165 4.29604
+1.64018 2.3161
+9.40397 9.89211
+5.21738 7.06323
+0.525526 1.0331
+8.06992 8.08704
+9.81539 10.0915
+9.33514 9.50521
+5.95494 6.54519
+9.21466 9.35909
+4.96603 5.18164
+3.89238 5.53056
+5.04546 6.32916
+8.63758 8.65805
+7.03226 7.57074
+0.32029 1.10893
+0.194176 0.992252
+8.79061 9.50848
+0.239137 0.300717
+7.7234 8.43747
+3.43679 4.28954
+8.31382 9.18928
+1.39612 1.67253
+6.95733 7.39846
+1.29129 2.12185
+7.93611 10.2305
+3.67764 4.17562
+1.38149 2.42407
+2.2847 2.48412
+9.28655 10.0661
+2.94115 3.21326
+7.04238 7.91536
+5.06012 5.61526
+8.95611 9.91736
+2.18524 3.44007
+1.0692 1.10987
+4.37019 5.18443
+5.82014 6.441
+1.68642 1.70458
+4.93783 4.9535
+9.42003 10.1196
+-0.356795 1.30987
+1.37778 2.80527
+9.54126 10.1758
+8.67413 10.5984
+0.914291 2.0697
+6.08696 7.09832
+2.82202 3.31103
+4.07818 5.50195
+2.85223 3.67449
+6.03006 7.10863
+8.84655 10.528
+5.08031 6.2001
+1.00272 2.74191
+0.169102 0.223253
+0.025089 1.26534
+-0.203339 0.64667
+0.899666 1.48885
+0.74235 1.49976
+6.28212 6.80412
+5.65159 5.93106
+2.1686 2.7445
+5.02936 5.43091
+8.07124 8.80499
+8.65696 8.95802
+7.68394 8.365
+8.65062 8.69146
+0.058248 1.19535
+5.74545 5.84057
+6.05244 6.52152
+9.3878 10.3328
+7.71379 8.88044
+3.32961 4.54105
+8.51987 8.62854
+4.10821 4.16902
+9.47639 9.78723
+4.72417 4.84793
+2.32867 2.94068
+9.52275 9.57815
+5.32867 6.96127
+4.32462 5.1508
+4.46919 6.45961
+8.62661 10.9533
+0.0244049 0.56156
+1.49207 1.73164
+7.03156 7.81168
+5.88587 5.89732
+8.43632 9.65085
+7.52612 8.06726
+4.82464 5.6193
+3.8062 3.90356
+2.42708 2.51646
+2.06458 2.45877
+0.427218 2.24283
+7.42616 8.11513
+0.617708 1.01833
+8.74218 9.03592
+-0.213346 0.599112
+9.05291 9.59124
+5.20365 5.54277
+2.85289 3.99509
+3.08468 4.58456
+0.136826 0.685254
+3.87191 3.99021
+0.970836 1.49673
+2.44355 2.53584
+8.88615 9.94545
+3.90591 4.52798
+1.52518 2.50658
+7.21268 9.07745
+0.767314 1.23833
+8.62975 9.42367
+6.71524 7.67686
+7.61205 8.48292
+5.312 5.65087
+4.75627 5.96261
+7.90674 8.0753
+7.37887 7.71478
+3.74483 5.52984
+2.7187 2.85544
+4.7902 5.62159
+2.89671 5.19815
+7.37268 8.72506
+7.11916 8.28301
+9.19814 9.75279
+1.2085 2.60113
+-0.632009 0.889734
+7.99858 8.39743
+6.48346 7.10822
+6.30616 7.06648
+5.56514 6.51183
+2.41505 3.56224
+6.83749 8.84447
+9.05111 9.46906
+7.77476 8.4091
+6.11378 6.31232
+4.42882 5.69917
+5.88107 8.052
+3.75437 4.08893
+2.70487 2.77664
+7.26028 9.77257
+1.44621 2.73267
+2.0384 2.60397
+2.95402 3.68949
+6.04766 6.4054
+0.716046 1.77698
+1.5084 1.72988
+2.58426 2.80376
+8.05255 8.59793
+6.06336 6.20709
+3.29813 4.31473
+2.53477 4.92554
+8.78711 9.88634
+9.26627 9.82082
+6.70683 6.81257
+8.25978 8.99788
+7.28054 7.64237
+5.14556 5.20711
+4.20431 5.87866
+8.96592 9.97597
+4.06216 4.41519
+8.49174 11.0491
+5.24547 6.03094
+4.65885 5.95835
+5.09606 6.34846
+6.30463 6.65933
+6.48022 9.56168
+1.38088 2.98143
+0.486911 1.16767
+8.16327 9.34821
+0.768885 0.782616
+4.51699 6.08086
+9.55086 9.70242
+2.86802 3.72489
+1.88496 2.18749
+4.31876 4.33726
+8.38871 9.45631
+8.80634 9.36198
+5.232 6.42399
+9.86919 10.0492
+3.61902 4.53086
+3.13118 4.42364
+2.69395 3.1816
+-0.303144 1.32309
+4.28871 4.36739
+3.8631 4.08745
+4.9291 4.98968
+7.14273 7.25505
+2.56623 2.59122
+6.01753 7.72265
+6.76051 7.53954
+6.76933 8.14741
+0.933137 1.83537
+7.9357 8.57904
+5.55847 5.59984
+4.25563 4.3345
+4.28087 5.21348
+8.88534 9.06554
+1.88575 2.94002
+5.26613 6.04562
+0.514249 1.45538
+0.130644 0.501645
+4.30564 4.86337
+1.57246 2.38451
+0.303814 1.77474
+4.22675 5.02783
+6.75381 6.78634
+5.64096 5.9725
+6.76159 6.98142
+2.35569 2.39119
+3.29794 4.95962
+6.55055 7.03366
+5.31474 5.69404
+9.01335 9.16988
+8.58306 9.37831
+7.06522 7.07778
+1.14695 1.74744
+3.15507 3.22865
+5.5925 7.14168
+2.14679 3.68767
+7.54789 9.71878
+1.5667 2.08742
+-0.604726 1.66718
+0.306012 0.54799
+2.61731 5.08257
+0.80957 1.74655
+8.22035 8.81637
+4.401 5.449
+8.89389 9.01988
+4.80574 4.9322
+2.19895 2.88565
+9.06688 10.8095
+1.23727 1.58699
+7.14836 7.92057
+4.65155 6.15149
+0.563061 2.16535
+7.66764 8.0341
+8.32324 8.42774
+4.54541 5.11069
+8.0237 8.09992
+7.26113 8.09404
+2.55196 3.20317
+8.1236 8.60951
+1.90437 3.23006
+0.888133 2.50365
+1.13618 1.69444
+2.60463 3.01696
+7.2311 7.73229
+5.06501 6.01487
+3.9893 4.10116
+1.45278 1.56937
+2.74601 3.80778
+9.40705 10.3843
+3.02533 3.52213
+8.7097 9.2268
+8.73145 10.5552
+2.56059 3.5742
+6.27328 7.57089
+3.23291 3.30811
+6.33804 7.20304
+7.63648 8.34564
+9.82053 9.93597
+3.14924 4.58629
+5.28253 6.33733
+1.99411 2.04104
+0.305593 0.420302
+5.39668 6.64188
+7.99992 9.37823
+5.25169 5.65987
+0.109291 0.875734
+3.08589 5.50296
+6.51358 6.62588
+5.34687 5.58204
+0.043587 0.932787
+-0.0264143 0.28677
+8.09722 8.37087
+5.46612 6.30285
+2.89146 3.49892
+6.73278 7.11762
+5.03068 5.90176
+1.7459 2.87727
+0.207707 0.448933
+7.00453 7.63105
+6.02789 7.87991
+8.1917 8.95854
+7.49014 8.73215
+8.48402 9.22063
+1.0467 2.4687
+0.241901 1.38802
+2.65867 2.81258
+5.46725 6.59448
+3.40578 3.75607
+4.2495 4.26392
+5.6608 6.213
+2.99705 3.88852
+6.17231 6.72018
+-0.17415 0.492739
+4.89596 6.49895
+4.68876 6.60218
+-0.0510568 1.46013
+8.87099 9.28179
+3.98894 4.5838
+-0.20015 1.59214
+8.80756 9.51828
+7.74921 8.53538
+-0.380041 0.440574
+2.69409 3.91466
+2.42747 4.56745
+6.25881 7.75647
+7.2941 7.77193
+2.60806 2.90251
+0.325028 1.22219
+8.29921 9.01416
+3.85524 5.45451
+5.2612 5.71877
+2.92849 3.73937
+8.6242 8.70808
+7.28153 7.35797
+1.65378 2.87917
+3.46034 4.24143
+3.99989 4.3199
+1.15266 3.60328
+4.8464 6.4887
+4.67021 4.68421
+6.96861 7.31554
+0.00723008 0.817047
+7.59589 8.88352
+5.56725 6.08465
+9.02409 9.19527
+5.81681 6.74193
+1.98221 2.98678
+8.76392 10.7646
+4.3903 4.50531
+1.0186 2.01838
+2.66674 2.74505
+2.41105 3.44579
+8.98295 9.18995
+8.14385 8.98779
+2.69613 3.60144
+0.445704 1.51319
+-0.634889 0.860409
+6.32737 7.10112
+7.88824 8.06838
+3.76271 4.43529
+7.66487 9.30221
+8.73974 9.59191
+3.08965 3.43006
+8.9518 9.96154
+0.727194 1.55228
+6.35214 7.12234
+2.71987 3.22996
+7.12786 7.4379
+-0.346107 0.837469
+8.47103 9.05987
+9.15744 10.628
+8.3237 10.093
+1.15052 1.16223
+6.95959 7.35423
+7.69488 8.44145
+4.21694 5.65913
+3.10562 3.37534
+9.73437 9.78252
+5.0458 5.53479
+7.80485 8.5163
+2.0442 3.75748
+-0.459177 0.498702
+7.38032 8.32195
+0.909659 2.11175
+7.08657 7.56877
+1.84997 3.10206
+4.2517 4.53819
+6.71655 7.04117
+1.06604 1.29153
+2.69273 3.31633
+2.19732 2.84826
+-0.723032 0.774865
+-0.289734 1.44645
+5.87194 7.71917
+1.01576 2.83685
+0.981927 0.998558
+3.07172 3.73201
+-0.112577 1.12642
+3.54063 3.67007
+7.21571 8.53815
+0.109957 0.839052
+6.86046 7.17211
+9.40878 9.69478
+0.989391 1.69046
+8.22287 8.8147
+1.48203 2.83308
+5.86418 8.0993
+0.749797 1.09852
+1.82996 2.50847
+0.28178 0.496017
+2.60694 3.00872
+8.6254 10.1698
+6.11641 6.41537
+7.19529 7.21342
+1.8214 2.17517
+0.991201 1.3788
+2.84924 3.12362
+5.75821 7.13843
+6.7106 7.35932
+6.6055 6.6829
+7.97105 8.58613
+1.56087 1.95845
+6.36782 7.10926
+2.43382 2.74699
+7.40509 8.8029
+8.42459 8.63142
+6.26128 7.55043
+4.6465 5.4431
+2.93214 3.29517
+0.157602 0.545214
+6.05931 6.72188
+1.7908 3.11731
+2.39217 3.58736
+7.07421 7.43852
+8.13419 9.74991
+9.53094 9.65319
+2.35726 3.68679
+-0.108561 0.874853
+6.87136 8.84157
+3.40803 4.58835
+7.50448 7.89932
+4.29762 5.53867
+0.863755 2.30032
+7.24847 7.95342
+2.89618 2.98849
+-0.928261 1.61922
+0.974105 2.91262
+6.99271 7.25856
+3.60995 5.01832
+1.26865 1.79704
+9.62217 9.80719
+1.02656 1.35514
+7.16502 7.32934
+3.12092 3.28857
+2.81374 3.84317
+8.73626 10.7585
+3.36982 3.61446
+5.08437 5.78949
+2.90218 3.0862
+9.2309 10.2523
+5.0967 5.48926
+9.73088 9.92708
+1.54013 2.78301
+6.73707 10.0789
+6.41735 6.838
+2.57935 3.04287
+5.719 6.70352
+5.42474 5.62732
+4.23904 4.69787
+4.16528 4.28736
+7.73477 8.84143
+4.90346 5.87324
+5.1969 6.14087
+3.48793 4.14182
+0.648493 1.07987
+6.88101 6.97932
+7.67342 8.74418
+5.16759 6.3871
+9.16292 9.49569
+8.77422 10.4817
+-0.358149 1.04178
+9.54616 10.3424
+3.12027 4.26504
+3.81223 4.73004
+1.2386 3.32247
+8.21963 8.42629
+9.10312 9.51016
+6.96107 7.43045
+2.98587 3.12365
+0.198165 0.211424
+5.19716 6.10856
+6.10553 6.3327
+3.98176 5.11099
+1.02512 1.04242
+4.27949 5.71947
+-0.457956 0.538807
+7.99877 9.48581
+5.88782 7.73303
+1.21496 2.85825
+8.46962 8.7862
+9.50182 10.1527
+5.85223 7.76234
+2.48368 2.52439
+2.35426 2.77405
+0.397056 0.482679
+0.160423 1.15786
+4.47109 4.8633
+4.74523 5.84196
+5.39177 5.75218
+9.00754 10.3249
+3.74813 4.03273
+3.08633 4.08426
+4.62672 5.29012
+1.92055 3.01442
+3.79279 4.5603
+9.52431 9.68334
+2.8126 3.32592
+-0.313688 0.490785
+9.06695 9.36835
+2.60321 4.14185
+4.40231 4.99535
+9.32205 10.1041
+5.3879 5.44349
+0.308728 1.0956
+9.05758 9.08283
+1.90313 2.50914
+7.1391 7.59459
+7.47357 7.95993
+1.25267 2.34827
+3.33222 4.36522
+8.78126 9.38611
+0.635979 1.62283
+8.3492 8.57545
+-0.572557 1.60517
+8.28855 9.03937
+3.47934 3.90271
+4.64498 5.43501
+0.872177 2.62011
+7.3893 7.58876
+2.14063 2.88063
+1.69361 1.75261
+4.19727 4.86483
+0.814676 1.27639
+8.19899 8.58203
+8.3394 8.99896
+9.31768 10.1694
+4.99218 5.19949
+4.2459 4.75266
+9.6314 9.64249
+4.038 4.75708
+7.92398 8.8579
+4.30747 4.54161
+7.51776 7.78258
+3.77611 5.1385
+3.53275 3.90278
+1.78619 2.12474
+3.18736 3.55159
+8.36759 8.52587
+5.52526 5.7843
+7.64174 8.09773
+4.37925 5.85699
+3.94295 5.31298
+-0.464623 0.795523
+7.02408 7.7048
+0.0690458 1.0008
+1.05445 1.32797
+0.126093 0.712612
+-0.809973 1.33869
+3.45568 3.96532
+0.433875 1.78679
+8.94667 9.65034
+1.98575 2.76936
+6.47974 7.67912
+2.74186 3.34153
+7.82655 9.32112
+4.71441 6.14932
+0.741177 1.76987
+8.05021 8.23239
+0.818503 0.882959
+7.13341 7.43399
+8.45939 8.93395
+4.44558 5.70161
+3.05657 3.86962
+8.75469 8.85537
+1.0922 2.23475
+6.00278 7.51598
+0.0530968 0.582206
+4.01788 5.48223
+1.30808 2.81869
+8.18848 8.59771
+2.43691 2.80685
+8.54045 10.6178
+7.58523 7.91634
+6.70183 7.49962
+5.81501 7.29783
+0.661853 1.58021
+6.50997 7.20411
+0.334292 1.40252
+-0.329585 0.742961
+2.38756 2.48935
+2.78114 3.58788
+7.97227 8.55379
+3.36753 4.57472
+5.14486 5.31457
+3.99691 5.47708
+6.36404 6.8741
+3.22519 4.63321
+1.80583 2.21824
+8.20747 9.42947
+5.90819 6.94368
+6.58559 6.85933
+2.99108 4.03832
+7.20963 9.6252
+3.10244 3.87265
+7.23018 7.91389
+7.18084 9.61063
+6.74145 6.86507
+8.40721 9.5751
+7.12352 9.45614
+2.06653 2.51786
+4.9155 5.04183
+1.34304 2.92777
+0.571315 1.17285
+8.05396 8.28214
+5.29142 6.24974
+8.93797 9.23051
+4.6108 5.45568
+6.46124 7.53124
+3.16695 4.37505
+2.76803 2.82764
+4.1531 4.84927
+8.19433 9.00383
+5.12114 6.22952
+2.2542 4.74849
+0.621192 0.871537
+1.37403 2.28895
+0.305704 1.3287
+8.70471 9.53085
+2.29164 3.56607
+2.42106 3.37382
+1.14309 2.03085
+9.17624 10.3281
+1.88864 2.70161
+0.932647 1.2473
+5.72385 6.55694
+5.25496 5.38675
+5.85771 6.69626
+7.37247 7.93094
+7.73499 7.98782
+4.91417 5.27506
+3.51127 3.84403
+6.96198 7.27686
+6.51176 7.74735
+4.19954 5.08222
+1.58115 1.83842
+2.11889 2.3408
+1.94427 2.00422
+5.59977 6.86555
+9.46942 10.3491
+9.18904 10.1988
+1.71938 3.01547
+4.3515 5.4951
+2.53792 5.85188
+0.3884 1.36228
+5.02469 5.62368
+6.82402 7.72203
+-0.320478 0.821539
+0.0885656 0.248783
+3.01725 3.44385
+6.63776 7.74386
+6.57899 7.9332
+4.82656 5.18327
+3.91909 4.43955
+0.0708319 0.101395
+2.59796 4.22775
+-0.433109 1.26978
+-0.434274 0.624336
+3.22018 4.25282
+4.63351 4.776
+8.889 9.56332
+5.35952 5.46531
+8.73832 9.22756
+2.03432 2.34194
+0.477994 1.43353
+1.2029 2.86844
+5.09945 5.76855
+8.89076 9.01771
+5.30284 6.31732
+1.56375 3.17543
+5.4773 6.36897
+5.30934 5.35073
+7.20096 7.7075
+6.51046 7.12888
+9.37127 10.0531
+-0.0484323 0.348687
+1.83241 2.2143
+8.28633 8.60462
+2.51014 3.65817
+3.27798 3.58685
+1.41567 2.23302
+7.50794 8.10378
+-0.0579575 2.10373
+-0.856005 0.96621
+2.96238 3.48434
+1.36304 1.90594
+2.9997 3.41214
+7.2763 8.087
+1.69207 2.74419
+5.41625 5.83917
+9.22139 9.53794
+1.17477 1.51576
+6.74597 7.90871
+0.678913 1.73759
+5.70863 5.7214
+8.88411 8.93377
+3.44409 4.54586
+0.958963 1.53878
+8.29904 9.3867
+2.52433 3.60238
+8.16257 8.21986
+2.11395 4.23455
+6.85451 7.40364
+0.20286 0.639736
+2.05848 2.49034
+0.547013 0.77336
+7.83609 8.11903
+2.16539 2.29286
+3.94232 4.31368
+8.53475 8.54519
+4.77462 6.4158
+4.08395 4.68214
+1.56902 2.23811
+1.61337 3.11768
+1.51181 1.65521
+0.0821202 2.09269
+4.77622 5.16243
+4.62148 5.75837
+0.613158 0.952696
+1.89128 3.04792
+7.57509 8.92834
+2.70465 4.2941
+4.95906 5.12442
+8.0927 8.17277
+0.796512 1.3215
+5.74134 6.45291
+9.68479 9.78978
+5.89261 6.2292
+6.11377 7.9339
+2.20571 2.67129
+3.46228 4.27058
+5.26723 6.2653
+4.04391 4.26562
+0.380382 0.818995
+7.58108 7.7618
+5.02375 6.13042
+4.20178 4.66297
+2.83039 3.0221
+2.36072 2.45545
+6.68854 9.20726
+2.91388 3.42464
+9.33373 9.73449
+7.75844 7.94625
+2.72414 2.89669
+6.65438 7.96623
+1.00647 1.05385
+2.63018 4.9432
+0.152187 1.60259
+8.86332 10.3631
+2.31523 2.6815
+8.00509 8.61794
+1.69711 1.75938
+8.65442 8.73697
+4.23917 4.32001
+9.66851 10.1925
+6.93943 7.49814
+8.51986 9.03561
+2.10317 2.5175
+0.539549 1.75683
+6.29423 7.93236
+8.64345 9.54556
+1.44069 1.6814
+9.10017 9.77088
+6.16731 7.40496
+0.570043 1.93192
+2.65761 3.88544
+1.46895 1.52688
+-0.369067 0.540647
+2.04868 2.72065
+2.1286 2.27858
+5.90157 6.16431
+1.55581 2.51851
+3.29705 3.81635
+3.4137 4.10991
+8.48699 10.1364
+8.43437 9.4642
+-0.037842 1.47589
+0.541735 1.7805
+0.499576 2.36065
+4.1415 4.72435
+4.77598 6.16872
+3.30388 3.61854
+6.43796 7.85966
+5.27157 5.70871
+0.919258 2.18653
+4.00961 4.07902
+3.78201 4.23596
+4.50464 4.791
+3.70253 5.30916
+8.59228 8.70036
+4.31103 5.69049
+5.31775 5.34378
+2.24198 2.64194
+6.66937 7.41675
+7.21753 8.42057
+4.35399 4.52398
+6.90698 7.30084
+3.44296 5.44378
+3.36719 4.89951
+3.38624 5.33856
+3.44877 3.53693
+5.81398 6.3016
+7.24655 7.33127
+3.86142 4.53134
+3.85894 6.88112
+6.45704 6.95699
+6.90997 8.24088
+5.68813 5.7611
+0.699911 0.824323
+6.73758 8.42517
+9.34644 10.07
+0.289929 1.30554
+8.30644 8.49113
+6.47667 7.16073
+4.28093 4.90236
+8.32678 8.57064
+7.09205 7.92316
+5.55599 5.63919
+1.0104 2.22875
+1.72237 3.53668
+2.54699 3.14823
+-0.668582 1.25485
+1.25582 1.37003
+1.35044 1.57807
+6.17083 6.30811
+0.618816 1.20065
+-0.540992 1.21634
+2.06673 4.28857
+9.03398 10.8112
+8.73735 9.22814
+1.30178 2.7599
+6.0221 7.34889
+8.30124 8.52159
+1.92023 3.34545
+2.99331 4.93358
+3.8412 3.93379
+1.455 2.77005
+0.538664 2.1118
+4.16926 4.26053
+0.699746 0.937609
+6.36024 6.6511
+2.34698 4.84463
+8.11109 8.76496
+4.05425 4.67773
+8.2284 9.78568
+1.64423 1.80353
+5.70109 6.93764
+7.2091 9.67224
+4.47015 5.23311
+4.29326 5.36144
+7.93151 8.96494
+4.61889 4.96487
+5.38473 5.43594
+9.35456 9.66489
+1.23737 3.04121
+1.16077 1.19519
+5.91037 7.55679
+6.88344 7.60181
+6.39705 8.65039
+1.61791 2.93041
+9.68285 10.1396
+9.03129 9.05839
+7.0683 8.29875
+7.19624 7.41696
+7.5266 8.38738
+-0.254571 1.01098
+1.30218 2.03222
+7.6432 7.73031
+4.99495 6.04757
+2.79394 3.29394
+0.31505 3.55963
+7.55382 8.18787
+6.00032 6.27664
+1.49355 1.79767
+5.21191 7.19537
+3.47816 3.75801
+2.10272 2.39494
+1.31887 1.93829
+7.14313 7.63055
+7.3141 7.77239
+6.03409 6.17265
+4.24946 4.53165
+0.0569272 2.56109
+8.44766 11.4872
+4.22879 4.28007
+6.92817 6.98775
+8.08859 9.0206
+-0.0748418 1.48605
+6.56698 7.0488
+4.46624 5.4952
+3.66085 4.05778
+6.44711 8.93943
+2.45735 2.49339
+0.0606673 0.416191
+-0.183838 0.750464
+7.08561 7.67275
+6.65423 6.90808
+0.0598735 0.364072
+5.2228 5.41543
+3.14042 3.19043
+2.40069 3.02829
+1.80441 2.1849
+3.47491 3.95775
+5.49162 6.63934
+2.03332 2.32288
+3.17234 5.25109
+2.58274 2.59951
+9.37994 9.97097
+4.71509 6.77966
+5.18915 6.84982
+6.12508 7.04354
+0.811202 1.98808
+1.46825 3.66984
+2.44386 4.15623
+7.60169 7.68242
+-0.43208 1.22222
+5.40569 5.66153
+0.391742 1.79408
+6.77742 8.43115
+9.12828 9.3851
+6.39541 6.80626
+5.17919 6.29326
+6.57263 8.12999
+3.439 4.62236
+8.40525 9.80086
+7.60986 7.70099
+1.32123 1.44213
+0.526574 1.92338
+9.57195 9.79591
+9.52103 9.63159
+3.79775 4.20608
+4.74446 4.89606
+9.00085 9.60025
+1.26279 2.08363
+4.13639 4.49232
+6.59409 7.18315
+1.0637 1.78425
+5.4213 6.87661
+4.24407 4.30987
+9.79732 10.1204
+4.24597 4.83541
+8.47705 8.5145
+4.34095 4.93842
+5.68168 6.96086
+7.48654 7.91072
+8.32005 8.45111
+5.24065 5.3032
+3.25982 3.94442
+5.58106 6.18764
+4.4243 5.58619
+6.36467 7.07082
+2.70051 3.56014
+5.94534 6.87688
+7.33638 7.7645
+4.57067 5.86652
+7.83993 8.36854
+9.03617 9.11629
+7.44672 7.95614
+6.05876 6.3594
+4.02496 4.97119
+3.01438 4.36109
+7.4932 7.92357
+7.51661 7.53354
+7.60692 8.49678
+1.76088 2.59103
+7.08578 7.39566
+4.83605 5.42933
+-0.186592 0.847663
+1.15879 2.33996
+8.11815 9.35472
+6.02584 7.62549
+0.881084 1.00015
+5.39067 6.27026
+0.910755 0.97444
+5.32174 5.65652
+7.69388 8.24928
+3.40521 3.7615
+5.60321 6.92388
+8.25096 8.34324
+0.00108913 2.16897
+0.508035 0.66573
+-0.0517816 0.0876197
+3.26472 4.30955
+1.99494 2.14903
+2.089 4.32368
+5.17378 5.75964
+2.8779 3.54361
+6.56459 6.90645
+1.43196 2.88337
+1.48917 1.94009
+3.40807 4.25784
+8.0334 8.13458
+8.22254 9.6175
+2.96308 3.14349
+5.04768 5.71252
+3.9977 4.72614
+1.44384 1.60782
+7.78147 8.19817
+7.03854 7.50085
+5.90747 7.06091
+2.89169 4.31831
+2.46167 3.16529
+9.13228 9.1504
+2.57975 3.05313
+5.75976 6.52958
+8.10499 8.98982
+8.43162 8.76377
+0.422917 0.668254
+1.69046 2.09962
+5.50386 6.66954
+0.0897183 0.564514
+3.50103 4.1041
+3.91918 4.52559
+4.39297 6.18876
+3.90396 4.90868
+9.69362 9.85528
+6.27994 6.95062
+8.01563 9.09433
+8.25641 9.72944
+8.22072 8.35423
+1.27059 1.61352
+8.53312 8.96235
+3.49185 3.9042
+5.79579 6.046
+0.489013 1.2147
+4.00074 4.177
+2.66625 2.93036
+7.20267 9.34958
+7.44659 8.54707
+8.99915 10.1143
+7.59922 7.82031
+8.38502 9.03222
+0.160075 0.294398
+4.14549 4.3927
+9.35554 10.248
+-0.159435 0.467922
+2.17272 3.72336
+8.63811 8.79976
+4.23215 4.66461
+6.99516 8.2035
+6.45212 7.88791
+6.20141 6.28633
+7.69396 8.82204
+4.50807 5.96315
+8.51725 8.89286
+0.939492 2.12064
+7.4615 7.62666
+8.46681 9.11769
+3.92828 5.40884
+9.05622 9.40015
+0.229625 0.860838
+2.05694 2.52113
+-0.217927 0.574255
+9.55146 10.3256
+8.31497 8.3417
+3.52833 4.47013
+7.7131 8.52058
+2.15462 2.66777
+5.7674 6.17553
+3.3358 4.10589
+2.06642 3.00412
+2.43387 2.85242
+5.09473 5.84276
+7.3287 7.54846
+4.64254 5.11465
+4.05785 4.93614
+4.25413 5.43513
+2.96476 3.15378
+3.53732 4.48239
+2.34137 4.01272
+2.24879 3.40626
+3.43323 4.49055
+0.871415 1.33068
+0.508929 1.65611
+4.92057 4.94743
+7.03376 7.35193
+5.73043 6.47264
+7.82417 9.93642
+5.24102 5.9178
+2.38528 4.1676
+6.27437 7.19631
+9.29267 9.53262
+4.10098 5.24964
+0.383714 0.833317
+5.97628 7.92987
+8.15799 8.96819
+8.1687 8.29862
+8.16289 10.5149
+7.38205 7.89765
+3.81883 4.15607
+9.46915 9.61755
+1.50756 1.51863
+2.34236 2.84689
+0.398473 1.15027
+1.05302 1.49155
+8.71687 9.35232
+1.0502 1.40395
+7.83685 8.76302
+7.7731 8.46899
+5.56618 5.97458
+2.90035 4.12043
+6.40644 6.68706
+3.95201 4.37075
+7.1831 7.67748
+9.42789 10.0914
+5.45198 7.01256
+8.64609 9.45756
+6.01864 6.31515
+7.64621 8.65533
+5.45654 5.76553
+2.04332 2.75476
+5.49454 5.85693
+6.13688 6.21927
+2.66255 2.7385
+4.8326 6.43772
+9.12704 9.45287
+-0.294488 0.318697
+2.26979 2.35516
+4.12949 5.58506
+3.01416 3.62246
+6.64697 7.10221
+6.44307 6.82985
+4.10484 4.73148
+7.42589 7.6029
+5.33055 5.50395
+2.46474 3.05847
+5.43677 5.59206
+2.13807 2.3988
+-0.38424 1.8121
+0.00916704 0.219304
+8.62621 10.2262
+3.33927 4.51169
+5.45656 7.13165
+5.29253 6.57917
+3.51704 3.9421
+8.63729 9.13361
+3.92626 4.3469
+6.83104 7.52695
+1.22258 2.28191
+0.447646 0.789809
+7.96543 8.54328
+2.24269 2.42571
+4.4161 5.40481
+0.813992 2.21792
+0.694664 0.974182
+6.50017 6.88902
+4.00723 4.65882
+9.05784 9.85062
+6.80276 6.98196
+0.105446 0.379881
+0.416982 0.53336
+9.01269 9.55204
+3.27197 4.23315
+6.7017 6.89704
+4.21512 4.42378
+4.86735 6.90949
+4.52235 5.36878
+2.62205 3.55746
+-0.551048 0.555476
+1.63274 2.71251
+4.26739 4.88085
+8.23129 9.77405
+2.49409 3.96851
+6.66387 6.88886
+7.72383 8.90611
+3.18511 3.27281
+0.73722 1.64435
+7.90329 9.02868
+6.94845 7.06773
+0.509461 1.54928
+4.63885 5.51652
+9.24395 9.5121
+1.00007 1.57161
+5.31349 5.45437
+0.929284 1.71034
+7.05985 7.63288
+7.38418 7.45373
+4.14937 6.5167
+7.49989 8.6081
+9.28313 9.57721
+4.41285 5.1497
+2.96148 3.09221
+1.58256 1.66419
+4.45116 5.43488
+5.70927 7.11699
+3.61105 3.93153
+5.92285 6.63773
+3.50065 4.48453
+7.97338 8.96464
+0.541394 0.965435
+4.46469 5.03925
+7.33695 7.6484
+9.64234 9.6938
+4.16378 4.17886
+7.10741 7.31549
+1.51829 2.62477
+2.1892 2.9684
+9.23767 10.0462
+7.87649 7.97087
+7.05385 7.85952
+6.91232 7.50277
+6.60185 7.81572
+2.27112 3.90211
+5.74452 8.2018
+6.25117 6.26911
+0.525893 1.53447
+0.392956 0.959233
+3.51591 4.71055
+3.10449 5.41156
+7.35964 7.65642
+2.89831 3.54334
+3.42338 3.68259
+4.75496 5.51419
+3.8792 4.48395
+2.18007 4.13236
+3.15798 3.16864
+8.91248 9.21598
+8.54636 9.34037
+7.93697 9.79709
+6.40205 8.9653
+9.67332 10.2252
+4.31771 5.25423
+7.27485 7.3725
+6.22971 7.11411
+1.16538 2.16762
+1.40443 1.6876
+3.14915 4.58847
+7.13761 8.72165
+4.38448 5.88699
+7.98309 9.19449
+8.491 9.05597
+5.55043 6.19359
+2.44006 3.36071
+9.56522 9.79903
+1.86129 2.00225
+1.65239 2.11478
+7.59392 8.4655
+2.44709 2.68538
+6.80932 7.04694
+8.8212 9.4182
+0.276845 0.956468
+8.17008 8.5538
+0.77864 2.06897
+6.78458 7.68692
+0.504907 2.67518
+5.56963 6.9058
+3.42691 3.5414
+2.52065 2.71583
+5.09924 6.26696
+0.223724 0.610039
+3.61258 5.29324
+0.388393 3.11131
+2.87763 4.45415
+8.26438 10.1169
+5.89742 8.17506
+1.89686 2.66651
+5.33662 5.68228
+3.37496 5.67291
+2.25713 2.36127
+0.402185 0.716342
+6.4231 6.79227
+3.22707 4.69314
+7.85092 8.77413
+3.31322 3.72455
+5.43021 7.7167
+8.5883 9.00864
+1.21371 1.71836
+6.35584 7.9706
+5.44438 5.50414
+5.31325 6.11217
+6.08888 6.78794
+7.70604 8.13257
+1.29858 2.48753
+5.54083 6.38817
+8.23948 9.82646
+7.5575 9.0224
+8.00415 9.39763
+0.488455 1.55358
+4.48727 5.20741
+6.46648 7.02349
+0.355939 0.611119
+9.4892 10.2189
+2.61893 2.82832
+0.268193 1.24687
+3.01964 5.19554
+6.29954 7.42795
+8.70796 9.48366
+5.39307 6.64597
+2.47001 2.60746
+5.30949 7.46529
+6.07973 6.16835
+0.764507 1.6144
+7.94123 8.52143
+1.88244 1.96592
+6.42103 7.02205
+7.673 7.73208
+6.66891 7.80675
+6.9305 7.5431
+6.62335 6.93873
+4.34846 5.77621
+0.49878 2.82928
+2.65221 2.80109
+7.45348 7.74372
+4.10129 5.26894
+3.87782 4.19855
+4.62113 5.22658
+2.84558 2.88185
+2.53209 2.86065
+8.94932 9.21967
+6.48046 6.89614
+5.81885 6.66829
+6.49129 6.62015
+8.5663 9.58685
+2.43346 3.89849
+9.36561 9.45886
+1.40232 2.65
+6.66 6.74041
+2.87007 3.49668
+4.71138 6.0184
+5.03638 6.08494
+7.77735 8.14253
+1.0301 1.27179
+2.58337 4.04699
+6.95419 7.89775
+7.81164 8.62551
+3.37669 3.96217
+4.68541 5.58692
+4.79697 6.34841
+3.95334 4.81962
+9.44006 10.0941
+4.91098 5.12386
+8.44273 10.1565
+3.6685 3.73156
+5.07599 5.33357
+-0.138235 0.260923
+2.71154 3.45603
+5.75096 6.16127
+4.4775 4.64308
+6.80557 8.97442
+5.49408 5.76652
+8.31937 9.12886
+3.26479 5.51673
+2.57425 3.03145
+2.42465 3.92714
+7.86505 8.50835
+3.29229 3.43549
+4.08537 4.69709
+7.83885 8.60616
+1.61622 2.72716
+9.10228 9.41907
+8.49325 9.46612
+-0.174644 0.351716
+1.95648 2.14825
+8.28844 8.4428
+4.35888 5.59521
+5.1396 5.22537
+0.330835 0.879566
+6.14972 6.82967
+3.14811 4.89049
+-0.231668 1.08277
+3.13526 4.94545
+8.32674 8.91046
+5.22364 5.48006
+9.84318 9.88416
+-1.07813 1.6965
+1.5095 2.0328
+8.03716 8.2792
+-1.01307 1.46703
+8.22096 9.0055
+8.9917 9.0415
+5.60623 6.74537
+3.15991 3.19314
+3.13863 3.26451
+0.739618 0.896958
+0.67599 1.18486
+3.37355 4.06303
+0.38605 0.410067
+3.03297 3.46387
+3.45867 3.79806
+8.67249 9.53278
+-0.213855 0.787363
+1.52316 2.61117
+8.31846 8.59736
+4.84685 4.94042
+7.41901 7.82623
+4.99029 5.09747
+5.3637 5.37612
+3.22123 4.77749
+3.21668 5.74743
+3.48748 4.59962
+8.00016 8.56269
+1.63631 2.42239
+1.05159 3.72319
+7.22643 7.95706
+5.65694 5.99195
+9.4469 9.66915
+0.857984 1.59867
+4.05869 5.69955
+2.65788 3.07259
+1.8038 3.38748
+3.91934 4.89922
+6.18534 6.70342
+2.85076 3.20176
+8.1897 9.9614
+0.685531 2.05322
+3.31097 4.00809
+8.26537 8.63475
+2.90508 4.07797
+1.25213 2.31285
+3.05752 4.03741
+-0.481913 0.605629
+1.87958 2.19386
+7.28689 7.76316
+4.82075 5.20688
+-0.08115 0.31839
+3.50085 5.89363
+1.31184 3.30269
+4.03137 4.81493
+6.11688 6.13923
+7.93584 8.43321
+4.9838 5.3733
+3.8174 4.11979
+8.56196 9.02824
+2.87809 3.89589
+7.95309 8.05432
+3.47469 3.63716
+6.61009 7.12576
+8.87374 9.79588
+7.31513 7.99089
+5.78084 6.68535
+4.96985 5.59877
+2.20236 2.52473
+0.661014 1.11035
+6.36183 6.58403
+6.67947 6.85093
+-0.242005 0.513902
+0.442966 1.72024
+6.4587 6.74016
+6.67958 8.0837
+8.98524 9.56405
+6.91409 7.59877
+3.73596 3.97705
+5.51193 5.96437
+3.72029 4.50126
+3.09896 3.23616
+8.83312 8.91774
+0.32173 0.486199
+4.21092 4.59955
+2.61616 4.07081
+1.89049 2.65559
+4.96401 5.00629
+9.33156 9.70914
+3.72455 4.61054
+8.91265 9.6563
+7.12401 8.04324
+6.65393 7.25572
+1.04032 1.24927
+3.0174 5.56006
+1.47645 2.26867
+3.49833 4.37416
+6.16877 6.34452
+6.47417 6.90595
+4.27056 4.92535
+7.60439 9.35352
+0.426219 0.754405
+8.5291 8.68579
+5.84717 6.64632
+1.99513 2.5284
+5.10669 7.83064
+6.99006 7.37272
+0.871836 1.5934
+3.6572 4.38875
+0.154617 0.290737
+5.91634 6.50415
+5.33982 5.45293
+6.92602 6.94691
+0.349512 1.61427
+8.02048 8.99943
+5.75598 7.34946
+5.86948 6.51327
+5.11707 5.6181
+6.27656 7.10043
+8.48922 9.73833
+8.35863 8.69746
+6.67829 7.07852
+8.51257 9.50383
+3.76636 4.33757
+4.82804 5.57166
+5.17892 5.61254
+1.35188 1.94069
+6.04969 6.06833
+5.34181 5.82455
+5.71714 6.71234
+0.966462 2.56278
+7.95169 8.15951
+6.53583 6.89673
+6.73246 8.34493
+8.71111 9.76467
+7.53215 9.56537
+0.619041 0.736713
+9.24399 9.50151
+8.57184 9.88538
+2.82682 3.77294
+4.2649 4.84602
+8.6621 8.96426
+8.04469 8.3189
+7.81877 8.42944
+2.78031 5.16589
+1.23076 1.43577
+8.35385 8.49632
+3.27901 3.66774
+0.595941 1.41354
+3.37123 5.16685
+9.11003 9.95515
+-0.25959 0.32069
+1.44153 1.70148
+1.61595 1.70799
+7.8201 8.53423
+8.5402 9.36947
+8.39125 9.8221
+6.2909 6.35773
+0.000933745 0.920054
+-0.21358 0.491025
+4.00874 4.03866
+3.43552 3.55874
+7.85942 7.98987
+7.6681 8.06748
+6.19541 7.14765
+8.53891 8.96393
+2.38789 3.26866
+-0.0162847 1.18379
+1.04764 1.52755
+0.400798 0.55475
+6.32001 6.94897
+5.9692 6.2012
+1.20784 2.67873
+3.58247 4.46372
+-0.229647 0.559407
+5.65979 5.73489
+2.32795 2.78462
+0.706144 1.55147
+4.56527 4.6636
+5.98901 7.20908
+9.27329 9.95152
+1.31296 1.70529
+5.82933 6.41329
+4.17452 5.29881
+4.15885 5.25117
+0.35549 1.3511
+1.0591 2.4463
+8.87597 9.55625
+6.66826 8.57255
+0.355945 1.40613
+5.39729 6.10218
+3.78791 4.37501
+9.53885 9.87184
+2.67568 2.82552
+4.44836 4.52939
+5.96764 7.40168
+6.35578 6.98546
+0.636857 1.19517
+3.3986 5.55448
+1.46493 2.66884
+-0.0676901 1.80921
+7.83396 8.53452
+8.3508 9.04561
+4.03407 6.0066
+0.997538 3.30635
+7.83064 8.03466
+4.57652 4.97461
+3.85952 4.15471
+0.960261 2.1069
+0.522458 1.52989
+8.81627 9.00768
+0.172256 1.29455
+5.69294 6.15752
+6.86391 7.75307
+2.32429 2.95415
+1.83191 1.90364
+0.400855 0.705649
+5.23264 5.39972
+5.19047 5.79842
+2.40804 2.89401
+0.462887 1.43874
+6.70213 7.90229
+4.37985 4.95797
+3.73768 4.30645
+0.756797 2.11146
+0.458724 0.472099
+3.93098 6.47147
+5.5294 6.00365
+2.97106 3.42174
+5.75875 5.80235
+7.96799 9.02105
+5.36254 7.22823
+6.56124 7.39973
+9.49234 9.57879
+2.87576 3.59509
+3.49182 4.28124
+8.68021 9.94486
+9.60199 10.1276
+9.70115 9.81776
+3.09609 3.98732
+5.00113 8.15031
+5.21248 5.74835
+9.23337 9.5696
+2.92777 3.56297
+2.52044 3.04905
+4.79908 5.05762
+1.98626 3.69659
+4.78726 6.20637
+7.39711 7.42831
+4.44319 4.78716
+9.28452 10.0832
+8.00774 8.85707
+9.22947 10.0523
+4.38653 4.86012
+5.15285 5.23106
+8.95413 9.75947
+2.90286 3.32407
+0.348694 1.39738
+-0.0660432 0.293424
+4.09079 4.2922
+6.0407 7.23031
+2.83771 3.72237
+8.54697 9.38898
+2.16742 3.45018
+8.83255 9.30343
+3.59112 3.6531
+7.53452 7.81898
+7.11781 7.19773
+8.2892 10.0259
+4.91072 5.06031
+5.8232 7.25924
+7.0641 8.31604
+9.477 9.63892
+5.8003 6.58306
+9.63988 10.2754
+0.654364 1.02398
+5.9488 6.85043
+7.86867 8.99891
+9.202 9.46902
+4.17932 4.20271
+6.50328 6.71085
+7.19848 8.15579
+5.62459 5.75449
+-0.159668 0.791409
+7.55683 8.7315
+1.03278 1.423
+0.751457 0.808785
+6.2203 6.50634
+1.64418 2.98238
+6.87468 7.00652
+6.36966 6.7117
+7.69893 8.89535
+0.419794 1.05032
+2.73928 4.31548
+0.409245 1.55228
+6.03905 6.39323
+0.409695 0.789834
+4.39148 4.40935
+1.14673 3.23607
+5.85562 6.44503
+6.87394 6.88742
+3.761 4.35136
+7.2208 8.01436
+6.49839 6.54002
+4.70791 5.91886
+4.24906 5.96619
+2.53482 3.91496
+-0.369254 0.69193
+4.81351 6.31088
+9.76066 10.0736
+1.4413 1.55942
+7.21917 8.88908
+6.03521 7.56826
+1.25568 1.42024
+5.47575 6.04431
+1.43099 1.99979
+5.1004 6.04088
+6.54798 6.56118
+1.0142 3.1564
+1.75267 2.1453
+1.28133 1.36044
+9.60996 10.0563
+1.14397 1.50247
+6.86688 7.08724
+8.38287 9.18041
+0.132076 1.27657
+6.52553 6.9301
+0.223917 1.41325
+1.18902 1.79753
+1.40084 1.75678
+1.94524 2.51929
+1.98276 2.62875
+0.763281 1.05483
+7.97952 8.51249
+1.059 3.05463
+5.33401 5.85094
+8.37442 8.64374
+6.62865 6.67315
+1.01707 1.64386
+0.113335 2.23523
+6.71906 8.00216
+-0.886574 1.29366
+4.20078 4.85294
+8.43336 9.06988
+3.55413 4.40768
+6.69076 9.01132
+6.18982 7.14109
+7.14381 7.7046
+8.63195 9.47031
+8.88052 9.84886
+3.34443 3.62637
+4.5862 4.72832
+4.95757 5.23571
+2.85993 4.04966
+1.43846 2.27425
+5.43112 6.30496
+-0.452609 1.55525
+7.17706 7.71287
+5.78537 5.79579
+8.51102 8.9466
+-0.472904 0.810489
+3.83688 4.24045
+8.04432 9.04582
+1.57259 3.37136
+1.22231 1.33582
+5.73006 6.26477
+2.90855 4.22125
+9.39717 9.4287
+3.63873 4.16094
+0.442035 2.08889
+0.294491 1.31124
+3.14755 3.86305
+6.57634 9.44898
+2.19051 2.41878
+4.99277 5.12569
+4.10425 4.9423
+4.83547 5.62769
+5.73879 5.78179
+8.90329 9.81905
+5.60168 6.17538
+5.83843 6.66128
+1.84271 2.57406
+3.01047 3.33662
+2.85037 3.79158
+3.49007 4.46877
+8.58942 9.51529
+0.613753 1.12824
+8.23757 9.54707
+9.27134 9.4196
+6.27126 6.56417
+2.17206 2.33018
+3.53588 5.17162
+8.6312 10.0868
+5.76342 6.66164
+9.01501 9.90984
+3.22004 4.18954
+4.37918 4.68595
+2.00928 3.49815
+6.64229 7.06693
+2.85962 4.58794
+8.45587 9.8897
+2.8481 3.65956
+8.65849 8.67336
+6.48486 6.58637
+5.82336 7.45254
+4.02267 4.59696
+2.24997 2.83815
+8.16201 8.55518
+7.40645 9.07085
+1.43137 1.50333
+8.7212 10.9419
+1.50523 2.44124
+1.92455 2.85819
+4.50866 4.53052
+5.75781 5.81275
+1.71013 2.0282
+9.31592 9.9015
+6.14972 8.18798
+1.85705 2.20068
+4.80971 5.10509
+3.31201 3.58168
+8.61824 9.31861
+7.19497 7.86933
+3.25381 4.53472
+5.62799 6.29537
+9.00659 10.021
+9.15156 9.74827
+2.0324 2.80741
+0.714403 1.00476
+1.26522 1.80417
+-0.362995 0.41758
+7.08785 7.71544
+5.55685 5.74045
+0.428866 3.03773
+7.61574 8.94894
+9.07256 9.69772
+4.49537 5.06822
+5.66388 6.48899
+1.69126 2.69607
+9.90539 10.0783
+6.56455 8.27128
+6.61988 7.86616
+7.42012 7.64493
+2.99922 3.35282
+4.69379 5.18947
+0.87894 1.30518
+9.47632 9.61234
+0.665754 0.855958
+-0.422778 2.11197
+3.38786 4.15441
+7.57236 8.75855
+1.89832 3.50224
+-0.185929 1.0777
+3.32911 5.53465
+6.91111 8.69247
+6.97456 7.86905
+4.75518 5.0948
+4.23733 5.83368
+8.52456 8.56086
+0.0978267 0.136564
+7.4668 7.99757
+5.52851 5.80858
+8.5833 8.88589
+5.10603 6.41348
+4.70682 6.59981
+8.60265 9.19477
+5.04514 6.24014
+4.49041 4.88669
+7.40925 9.15624
+0.80364 1.35315
+7.11604 8.01153
+0.267749 0.714089
+0.121521 0.822226
+9.30556 9.81307
+2.11398 2.92567
+5.97722 6.08022
+7.13483 7.22211
+8.00161 9.27274
+4.87681 5.51654
+3.11843 3.84311
+5.17747 5.98482
+3.6077 4.46306
+1.37454 2.2443
+4.93385 5.96357
+2.92184 4.0964
+4.88767 5.56353
+2.87394 3.76336
+0.326521 0.622872
+2.42056 2.45007
+-0.527891 0.827211
+6.73151 7.20155
+1.82048 2.54905
+1.35563 1.88701
+3.64202 4.10669
+5.22846 5.23953
+6.06271 6.46993
+2.71418 3.2081
+6.41179 7.57176
+7.45823 7.79609
+1.01227 1.39137
+9.0872 9.20132
+5.083 5.64038
+5.63236 5.97945
+-0.317645 0.822313
+0.865396 2.65587
+5.71839 5.98983
+1.50978 2.08611
+2.95824 3.70996
+0.264301 1.02233
+8.22351 8.98589
+4.87805 5.24127
+2.31329 3.46752
+6.19539 6.69676
+5.18643 5.40947
+7.15453 7.66643
+1.20694 2.25111
+7.87378 7.89093
+5.16514 5.604
+8.68354 9.01395
+7.33753 9.37499
+2.94627 4.06036
+8.64337 8.85727
+0.0353092 1.0128
+6.98437 7.35718
+6.77073 6.79959
+3.13559 3.70735
+7.40139 8.27017
+4.01174 4.39788
+3.22281 5.11647
+7.79256 8.58737
+0.642233 1.39694
+7.18603 8.69453
+3.37803 3.59355
+0.762287 0.84262
+4.21823 4.52565
+0.894924 1.35434
+0.844327 1.19938
+5.57958 7.05431
+-0.631066 1.55134
+3.78962 4.17935
+9.15329 10.4824
+5.47536 5.52975
+8.81243 9.16088
+4.45989 4.94123
+8.68235 9.45112
+8.04719 10.3938
+8.87349 9.40483
+0.502543 0.570283
+2.08512 2.47652
+-0.654512 0.804355
+3.68569 5.21711
+5.33017 5.80226
+3.44991 5.31415
+-0.00417763 2.95077
+7.17784 7.9318
+1.2721 1.31642
+5.24415 5.64173
+2.79434 3.28746
+4.54991 6.49276
+4.74707 5.12555
+7.36365 8.15777
+0.913049 1.79828
+1.47498 1.83425
+2.64271 3.38567
+4.78159 5.44718
+7.6087 7.66442
+-0.484393 0.909893
+3.16824 3.23757
+4.43021 5.90284
+4.25954 4.74995
+6.58742 7.24125
+1.86151 2.27069
+3.16459 4.5945
+1.06471 2.08965
+3.31028 3.83029
+1.52593 2.47521
+0.703789 1.42451
+1.47969 1.68923
+2.92352 4.24089
+9.84088 9.93485
+3.18205 4.27817
+7.39345 7.78945
+3.78808 5.41572
+4.38624 6.75693
+6.93065 7.16977
+1.01289 2.19807
+3.37006 3.54196
+5.50238 5.58285
+-0.225113 1.99347
+1.67796 1.86943
+6.1999 6.35102
+3.80494 4.74814
+1.13294 2.02639
+1.1965 2.6548
+-0.284453 0.856092
+4.26565 5.02196
+9.66948 9.88874
+6.20287 6.25528
+4.38154 6.65806
+3.77411 4.3075
+5.77177 6.78486
+9.16311 9.816
+3.22861 3.42009
+3.36573 4.34724
+6.76951 7.58025
+4.83813 5.23042
+3.87192 4.37372
+5.56859 5.90066
+-0.368163 1.4593
+5.44031 7.81671
+2.66342 2.99253
+6.11846 7.69499
+4.98811 5.17531
+4.45078 4.67513
+4.88206 4.94128
+2.51813 3.0268
+0.461292 1.15264
+2.34766 4.48652
+0.198819 2.23425
+6.85634 6.98248
+0.912438 1.81872
+4.84933 6.34912
+5.15613 5.82891
+0.172772 0.994083
+3.37381 3.64549
+1.98836 3.2697
+1.64344 2.06049
+0.766585 3.09305
+7.8979 8.28046
+4.34856 5.01341
+6.69809 7.24239
+5.19034 7.04959
+5.3747 6.92123
+7.8893 10.1251
+6.11207 6.99125
+5.37115 6.84111
+9.04786 9.11002
+6.45326 6.64415
+-0.76294 0.92832
+0.980411 1.8166
+3.05536 3.50031
+6.10827 7.55786
+6.57848 9.06264
+7.66855 8.861
+4.80276 4.82283
+1.99932 3.2877
+9.45229 9.80653
+0.457474 0.778684
+5.44444 5.95239
+5.60974 8.05169
+7.64656 7.79632
+6.78372 7.65134
+6.93878 7.82023
+9.08292 9.55308
+9.16329 9.25802
+1.4909 2.38688
+4.31881 5.3564
+5.12535 5.60119
+2.44591 2.54637
+7.36929 7.80452
+2.13707 2.97655
+9.73557 9.94588
+1.96637 3.36097
+0.857068 2.29643
+5.58224 5.91142
+8.90714 9.0255
+9.77988 10.0711
+0.41121 0.970955
+-0.518356 0.91447
+7.58725 7.71255
+8.1435 8.78712
+6.5487 7.17991
+4.94961 5.50283
+8.14086 9.03281
+3.51281 5.24806
+3.5786 3.84066
+6.27435 8.37735
+8.65263 9.5555
+2.87484 3.56117
+5.57707 6.55879
+-0.111276 0.264178
+3.60894 4.15477
+2.82322 3.64397
+8.40669 9.1127
+8.43089 10.5298
+1.38472 2.2453
+1.74464 2.00472
+4.01588 4.67572
+0.408869 0.938602
+2.06155 3.46067
+4.4871 5.08963
+2.4435 3.87355
+1.32864 2.55801
+4.78579 5.26122
+7.43027 7.57749
+6.90971 7.32716
+8.01095 9.46872
+9.41627 10.524
+8.83143 10.4474
+0.631816 1.75513
+1.72965 2.17123
+-0.513239 1.1886
+6.75616 6.7984
+2.49278 4.26493
+0.230011 0.966298
+3.78506 4.95013
+2.03886 3.14808
+7.87309 10.5637
+3.54564 3.58055
+1.91974 2.9194
+4.8503 4.98668
+4.66494 4.83558
+7.57916 8.24358
+4.78743 5.38547
+2.81034 3.34534
+1.00297 2.0138
+6.87593 7.17736
+3.93157 5.0655
+3.10361 4.05519
+8.22876 8.38326
+7.48377 8.31026
+2.23106 3.4905
+0.130934 0.606709
+1.22344 2.55898
+7.55829 7.92597
+4.10977 4.86263
+0.122756 0.264176
+3.8357 4.15854
+1.28414 2.13031
+0.280029 0.805504
+2.88245 4.1704
+5.57936 6.94781
+6.22719 6.33201
+-0.761013 1.16475
+6.16636 7.12566
+2.98935 3.192
+2.23263 2.34362
+3.9082 4.11692
+2.66865 3.5275
+1.87676 2.43966
+4.60035 5.39332
+2.74287 3.73097
+2.81953 3.96666
+5.73644 6.04042
+4.02179 4.52419
+3.26438 4.07346
+1.22509 2.13719
+7.91885 9.71846
+1.28152 1.48079
+7.97918 9.26344
+8.75682 9.8677
+7.25678 7.45362
+8.16161 8.87066
+1.21873 2.37224
+7.76739 9.06346
+3.89932 5.03406
+3.53901 4.37006
+2.93795 4.04333
+6.36543 6.72985
+4.72622 4.98804
+1.86205 1.99008
+0.784581 2.05264
+0.978519 2.91723
+3.9067 6.47195
+0.735425 2.38151
+8.37394 8.41609
+6.91804 7.23374
+9.39259 10.1026
+7.28732 7.43466
+4.75982 5.44264
+6.71504 7.53933
+2.17125 2.54358
+0.703562 1.39087
+-0.221711 0.541965
+9.22839 9.39159
+9.53465 9.97585
+1.44304 2.53666
+7.886 8.85051
+9.33174 10.1632
+2.60898 3.42889
+1.73658 2.02589
+6.31651 6.77762
+7.26755 8.34499
+9.01312 10.9837
+7.47361 8.96251
+7.98365 8.02586
+1.40065 3.44891
+9.44617 9.55391
+8.24265 9.34849
+9.366 10.4216
+0.375354 1.17522
+3.37114 3.38278
+-0.742469 1.07634
+4.29988 4.81879
+4.18605 7.21928
+7.41047 8.29198
+6.68173 7.60225
+3.24292 3.30695
+1.8951 3.42167
+3.97359 4.2857
+4.72621 5.80575
+4.75014 5.02239
+6.43454 6.94568
+7.16601 8.10355
+2.16685 2.23666
+6.70852 8.63284
+8.16988 8.95848
+0.277002 1.30648
+1.5803 2.28632
+2.22634 2.34679
+0.200623 0.814959
+5.27457 6.51651
+2.49533 2.90705
+6.48922 6.69528
+8.18879 8.63551
+2.75159 3.633
+0.884853 1.56434
+1.87488 3.98951
+4.24783 5.17713
+6.22499 6.56095
+5.68238 5.99272
+3.75553 3.85012
+4.87543 5.39966
+6.62671 8.72493
+3.50262 4.05131
+5.38952 5.4974
+7.84971 7.94051
+5.39123 6.66564
+5.43986 6.17256
+7.48968 7.7677
+4.2685 4.57296
+1.75169 4.11058
+5.03634 5.16102
+4.68003 4.84715
+8.36249 9.98761
+8.94297 10.6969
+6.21572 6.24305
+7.90303 8.0672
+7.90426 8.41244
+5.98512 7.93187
+5.13297 5.27136
+6.58367 7.4971
+4.72663 5.22956
+7.99667 8.59246
+4.3303 5.92188
+1.3132 1.80875
+7.70104 9.20947
+1.78862 2.00473
+9.63678 9.65571
+-0.264416 0.318054
+2.70004 3.40777
+2.74642 3.73608
+3.6494 3.6743
+8.03113 9.22851
+1.07526 1.3116
+4.05436 5.33291
+4.60907 6.03605
+7.83426 9.10358
+2.27997 2.77309
+5.63139 6.92616
+4.40717 5.25214
+1.98986 3.5062
+2.42393 2.9584
+1.94336 3.08456
+1.20185 3.01827
+0.641733 2.10095
+7.25046 8.29391
+0.640392 1.26451
+3.9588 4.85492
+6.83036 7.41101
+6.48581 7.08757
+6.48734 8.47856
+9.55084 10.3774
+-0.173137 1.26574
+2.32702 2.58775
+2.7463 3.13914
+7.86951 8.62807
+5.96916 7.92759
+0.217046 1.70373
+1.04207 1.05755
+4.79058 5.07902
+4.19024 5.35395
+9.00175 9.83715
+8.37554 9.275
+4.5204 4.82999
+3.49936 4.75519
+7.07916 7.74619
+6.66726 7.35282
+7.39513 8.55523
+7.50381 9.60708
+1.39304 2.26927
+2.84101 4.76376
+1.21779 1.59353
+4.7893 5.70143
+9.12195 9.57131
+5.40461 6.15443
+2.86445 4.26837
+8.01324 10.9082
+2.96659 3.8042
+2.4897 4.59323
+6.37887 7.15878
+7.00143 7.6419
+3.22491 3.41843
+1.22852 3.31783
+2.09881 2.56121
+4.43205 4.67051
+4.39328 4.66715
+2.38355 3.39058
+0.638802 1.59399
+5.32717 5.81376
+8.00353 9.72007
+8.77281 9.81649
+8.95552 9.86609
+2.90915 3.96556
+3.88176 4.93124
+6.45945 7.69942
+-0.108577 1.57424
+0.304992 0.320561
+6.47789 6.5515
+1.98211 2.05312
+6.2741 7.35626
+9.45057 9.67918
+5.2916 5.48037
+0.158802 0.712187
+6.42002 6.84323
+9.11085 9.13063
+9.42446 9.95882
+6.03624 6.96469
+9.2473 9.6286
+7.10342 8.71163
+3.34072 3.35187
+7.4602 8.58506
+8.7963 8.81873
+0.323615 2.22687
+0.326746 1.76681
+2.20062 2.76862
+7.55181 7.85006
+0.941035 1.28117
+8.76643 9.60019
+9.19731 9.33092
+6.0479 6.57293
+6.12725 6.24356
+7.53078 8.92488
+3.1841 3.48283
+1.85544 2.01888
+7.3849 9.29183
+5.03915 5.27721
+4.77142 5.46282
+-0.291696 1.14641
+1.61367 2.20867
+5.31853 6.69431
+2.52731 3.13139
+4.86677 5.18106
+4.50183 4.60969
+5.95881 6.09964
+2.41939 4.42026
+6.92003 7.17891
+4.29584 5.48557
+8.02803 9.06315
+2.82326 3.49599
+5.8647 5.87561
+2.38814 3.62688
+6.32418 7.17662
+5.99907 6.5059
+3.84698 4.14446
+9.80728 9.82132
+5.2366 6.30871
+9.81878 9.91004
+1.53024 1.83525
+2.98035 3.68531
+4.5418 6.98786
+5.19561 5.9846
+0.946068 1.46672
+3.26948 4.71928
+6.13476 7.68682
+8.36934 9.65072
+6.40074 7.14762
+1.01349 1.80493
+8.4514 10.25
+-0.180382 0.682704
+1.03041 1.63565
+5.64642 6.96069
+2.73598 3.67485
+5.8705 6.66157
+4.68343 4.7176
+5.83787 7.6818
+1.42529 2.234
+3.73726 4.19241
+5.38341 5.81884
+1.13088 1.69073
+0.968034 1.98828
+1.06007 1.11039
+3.50129 4.51807
+5.83133 6.77904
+-0.334945 1.29129
+0.326706 1.16015
+9.15028 10.4391
+5.13047 6.79712
+1.06952 1.38997
+5.79345 6.49898
+7.88149 8.5143
+8.00404 8.09794
+8.22725 8.28904
+6.38406 6.61356
+6.32166 6.73458
+7.17066 7.32049
+1.64338 3.79327
+7.92135 8.55568
+7.15578 7.42231
+6.70701 7.65427
+5.76608 7.63064
+3.54163 4.08662
+3.81402 6.76906
+4.5998 4.61865
+9.01471 9.18718
+5.21234 5.73335
+0.946018 1.39917
+6.99714 8.29739
+5.64458 6.93965
+3.39809 5.70907
+6.32284 6.83604
+8.50347 8.53097
+3.90118 4.85721
+9.41198 9.62076
+4.41514 5.55152
+7.69979 7.81249
+5.34434 5.37105
+7.25274 7.76114
+7.67383 7.92718
+5.82851 6.29417
+0.935651 1.2842
+0.639586 0.786771
+6.39823 8.31226
+3.67546 4.89035
+9.20323 9.57287
+2.33896 2.99576
+8.51933 8.80243
+0.983098 1.11084
+8.48215 9.42998
+7.29586 7.3914
+2.00695 2.89046
+2.60909 2.62433
+2.04118 2.92033
+7.60386 9.01419
+7.32896 7.73342
+9.51693 9.54891
+5.1323 5.24962
+6.35326 7.18302
+2.50952 3.51872
+3.4149 3.57431
+9.18412 10.4976
+5.68123 6.42697
+5.87758 6.0124
+6.3202 6.64588
+8.2547 9.98176
+5.50949 5.7854
+0.0824268 0.128178
+2.17292 3.76233
+7.22786 7.68214
+5.09326 6.4151
+4.30171 4.86688
+2.39206 3.47399
+7.95152 8.35556
+2.40133 2.936
+2.77819 3.87516
+3.252 4.33376
+9.54269 9.7513
+6.6747 6.73043
+0.611474 1.97158
+7.65864 8.53689
+1.58345 1.8017
+2.56917 2.8152
+8.5424 8.8301
+4.98159 5.44499
+5.82482 6.03578
+3.55509 4.90785
+5.77028 5.94747
+0.163965 1.1379
+2.85039 2.94261
+4.24343 4.67273
+3.22636 4.06084
+6.03662 6.21018
+4.55495 5.07697
+1.91173 2.51739
+6.54894 7.24036
+5.55502 6.92676
+0.245707 0.586188
+2.28044 3.29563
+4.71378 5.25198
+8.28953 8.44891
+9.42282 10.179
+5.0548 5.73614
+6.3203 6.43659
+6.54178 8.82077
+3.67181 4.17365
+8.51445 8.96445
+1.69648 2.84524
+0.194222 0.920147
+2.48533 2.59803
+1.66002 1.6739
+4.79833 4.95404
+1.09801 1.11009
+6.62529 7.4066
+8.0099 8.37262
+3.55429 4.11824
+6.2666 7.12137
+7.83222 8.01342
+9.37156 9.72961
+1.1647 4.04434
+4.50719 5.09068
+3.25175 3.75482
+8.28659 9.30848
+7.30009 8.60755
+-1.12073 1.21016
+0.310087 0.725712
+8.3746 9.13511
+9.11925 10.2234
+9.68703 9.7137
+0.603098 0.844291
+5.88373 6.99327
+0.852802 1.43297
+3.7463 5.82283
+7.69639 8.25446
+-0.337322 0.977113
+8.76606 9.16618
+3.43527 3.6616
+3.93587 5.39471
+5.66569 7.20462
+5.34999 5.7193
+3.25589 3.706
+1.52012 2.55985
+4.74228 5.43725
+5.15323 5.51652
+7.77237 8.33717
+-0.0514419 0.914127
+9.27182 9.59476
+8.14192 9.74859
+6.42702 7.20331
+7.51351 7.68358
+7.0947 7.46059
+7.97635 8.59449
+2.39931 2.66008
+5.79481 5.94673
+4.41054 4.81613
+2.72202 3.61239
+2.86039 3.44719
+1.81115 3.28151
+-0.566995 0.734214
+9.61998 9.72024
+7.4163 7.61821
+0.42522 0.552659
+3.17617 4.36942
+0.740294 1.36953
+7.13755 8.39966
+0.219186 0.892588
+3.78307 5.2905
+0.783026 1.76155
+3.01893 3.33055
+3.12143 3.5713
+-0.792679 0.92539
+0.668572 1.12961
+3.88619 4.30545
+7.59276 8.1776
+4.71509 5.05622
+6.53406 7.04242
+1.581 2.21984
+4.7144 5.51372
+2.76338 3.50211
+0.16364 0.293599
+5.92365 6.10636
+3.11174 4.29165
+5.49295 6.48717
+-0.503239 0.795707
+7.30558 8.12408
+2.10674 4.13456
+7.11985 8.01932
+1.34672 1.48739
+4.05778 5.69084
+2.83686 2.9115
+6.4471 6.53909
+0.467374 1.84371
+2.76467 2.94177
+4.87867 5.33932
+0.892878 1.96273
+1.13934 2.27205
+7.76918 8.39409
+6.72181 7.43901
+7.0836 8.68472
+7.12924 7.56332
+0.689172 1.62922
+9.41146 9.91043
+0.398265 1.27579
+6.29966 7.4874
+5.09438 5.65334
+6.04623 6.4687
+5.75305 6.89731
+0.308118 0.459501
+3.63692 4.30501
+3.1755 3.71009
+7.32787 7.52785
+2.23235 4.09978
+2.71191 2.91513
+0.209457 0.840713
+7.31489 7.38296
+6.21245 6.91111
+5.75983 5.96049
+5.92056 8.24518
+-0.354452 0.489638
+4.05894 5.34828
+1.56299 1.57414
+2.85083 3.27455
+8.78323 10.0012
+0.208502 1.26471
+6.10824 6.79285
+5.55114 8.03968
+6.13077 6.32342
+7.34865 7.82592
+3.94835 4.75016
+7.8268 8.72249
+4.85131 5.07903
+5.40398 6.0134
+2.85971 3.85293
+0.126379 1.45545
+3.15768 4.28388
+9.64566 9.70016
+4.47514 6.31064
+6.44995 7.2894
+4.70992 6.13777
+3.91128 4.22263
+7.35627 8.07739
+2.49215 2.68749
+8.09946 9.16929
+0.925679 1.92784
+8.48437 8.63892
+7.2255 9.18109
+-0.00840282 0.0168954
+5.91933 6.6274
+4.16086 4.64302
+8.27009 8.47868
+1.73372 2.93094
+8.17421 9.17705
+9.19136 9.43222
+0.0653594 0.648416
+8.69 8.96184
+8.99355 9.40832
+6.25088 6.26945
+6.72391 7.38424
+9.59708 10.3496
+6.00971 6.18818
+4.64468 5.75797
+3.64832 5.30079
+5.99378 7.8792
+6.5388 6.99379
+7.31694 8.43802
+3.66227 4.92638
+9.55964 10.3796
+-0.14433 0.29095
+3.56716 3.71252
+3.82062 4.27788
+8.10405 9.35275
+7.17891 7.46539
+1.17698 1.29602
+4.48829 5.03134
+7.18025 8.13852
+9.42388 10.3634
+5.2158 6.17469
+5.22926 6.52397
+5.16731 6.40625
+6.53348 7.269
+2.07834 2.39172
+9.65044 10.1519
+8.64551 10.1294
+9.29006 10.5993
+1.50639 2.83173
+5.71675 5.99216
+3.0783 3.35571
+0.115401 1.31431
+8.03988 8.11942
+3.11917 4.53956
+1.14552 1.1646
+5.34782 6.43017
+0.0701702 1.0368
+0.183335 0.440704
+6.33438 7.71607
+2.11533 2.64323
+7.12104 7.13366
+7.21548 8.26968
+3.13445 4.13568
+4.57452 4.74602
+2.60889 3.69846
+7.21184 7.47573
+6.87651 7.03405
+2.65431 3.94352
+1.50006 1.70087
+6.16344 7.54429
+7.02057 7.73067
+8.27833 9.01489
+0.500833 0.597845
+8.34751 9.88925
+2.80242 2.91837
+5.29424 6.079
+8.36276 9.10074
+0.216887 0.268335
+1.30798 3.16393
+3.93851 4.22658
+2.58028 3.14744
+9.31131 10.3451
+7.37262 8.84852
+4.45306 5.6723
+3.74535 4.0721
+4.90174 5.63875
+3.41847 4.65199
+3.10265 3.82548
+6.56126 6.97557
+2.57449 2.95098
+7.97418 9.06301
+9.2203 9.66829
+4.64922 4.96305
+8.83034 10.115
+6.6685 6.89847
+7.36585 7.48669
+8.66761 9.39287
+0.562216 0.961875
+7.56292 7.81006
+8.50715 8.95572
+0.572825 2.24755
+5.9367 6.06766
+-0.769578 0.776163
+4.48224 4.9553
+8.21069 9.29643
+8.57206 9.47175
+1.10032 1.21371
+3.76306 3.87152
+6.46197 8.18457
+6.96501 9.70727
+3.42357 3.93484
+0.818601 2.42743
+-0.119739 0.397938
+-0.378761 0.523892
+8.03394 9.35409
+3.60283 3.98864
+2.21789 2.70607
+-0.255329 0.319063
+6.20806 6.22609
+7.1283 8.04391
+3.73565 4.03638
+8.5374 9.10987
+5.22675 5.35072
+7.51777 7.58439
+9.12636 10.4159
+9.15003 9.40672
+0.217863 1.19883
+9.42416 9.9178
+2.55337 3.8088
+7.03655 7.98242
+9.17171 9.8047
+0.110162 0.722738
+3.16467 3.58897
+6.47244 7.12961
+1.0456 1.65614
+1.58456 1.62844
+1.79039 1.84035
+6.24286 7.07838
+9.08631 9.11684
+3.05068 3.40838
+2.81212 4.03665
+2.52011 3.09841
+8.06001 8.16356
+7.07649 7.52685
+2.47666 2.86548
+8.66241 8.95103
+-0.298116 0.662697
+0.822443 2.46125
+2.07619 2.33674
+4.84135 6.21034
+7.49625 8.13026
+7.85854 8.29618
+3.01722 3.37062
+6.54393 7.30306
+2.21113 2.30166
+8.32138 8.57349
+6.2995 6.33514
+3.0018 3.56886
+4.63378 5.52214
+6.71908 8.96715
+2.29809 2.95581
+8.34947 8.71096
+4.96902 5.32075
+9.51051 9.72733
+3.311 4.77789
+3.50233 3.66309
+4.95177 5.76002
+6.12876 7.22391
+6.27743 6.79393
+3.60638 3.6833
+5.20305 5.50848
+7.16065 8.88358
+9.45049 10.2539
+6.16892 7.0314
+8.08479 9.74516
+0.0717867 0.669987
+2.17569 3.34098
+4.81716 5.7509
+7.63999 8.01157
+5.87228 6.60363
+3.39621 4.35575
+4.96079 5.07901
+7.57639 8.82003
+8.27285 8.52609
+0.665858 1.64782
+1.74256 2.07126
+6.19512 6.4258
+0.664592 1.30896
+0.180682 1.43746
+6.46752 6.81303
+2.55562 3.08708
+9.33695 9.63312
+6.33821 6.77092
+7.88252 8.55026
+8.17937 8.45385
+-0.415294 0.793096
+5.22077 5.54553
+8.67808 9.10041
+1.72096 1.92024
+0.492778 1.48076
+2.29514 2.88531
+0.0934389 1.37614
+8.40297 9.11121
+3.66605 3.91717
+-0.274468 0.867811
+9.41428 9.56659
+1.22657 2.12792
+8.71336 9.85384
+5.09347 5.42905
+2.02877 2.36652
+5.99112 7.40703
+0.911618 3.48138
+4.84352 5.11131
+1.16309 2.08613
+5.58561 5.84805
+0.663543 1.08921
+1.83189 3.93269
+4.07731 4.38879
+4.04789 4.9989
+2.09457 3.61279
+2.00982 2.94396
+7.37537 7.66574
+5.08648 5.80122
+9.19959 10.2263
+4.26136 4.86194
+6.67875 7.61134
+1.27462 2.48399
+7.2237 7.82324
+-0.0141009 0.0441377
+8.32069 8.36192
+2.82562 3.0717
+-0.528918 1.25301
+1.90486 3.04714
+1.34489 1.75301
+3.14332 4.03322
+8.55351 10.8681
+9.09824 10.3828
+0.496868 0.622499
+7.11112 7.62765
+0.335233 0.528962
+6.71335 7.13937
+6.78574 7.71172
+9.13568 9.22251
+7.10299 7.64765
+3.64747 4.06685
+8.64041 9.40111
+2.43515 2.93081
+2.95476 3.68588
+0.0863751 0.777976
+6.5891 8.18165
+8.80986 10.0735
+0.568868 1.63785
+4.41677 5.42049
+8.72857 9.88426
+3.67467 4.25442
+8.98168 10.1087
+5.08611 5.50098
+1.28982 2.34422
+-0.914176 0.969847
+4.35042 4.42735
+4.02282 5.08164
+9.00566 9.4791
+2.71821 3.24065
+3.20252 3.24988
+8.61559 9.6733
+3.15157 4.7685
+3.59348 4.67872
+0.286864 0.36279
+8.40374 10.528
+7.53647 8.13523
+6.81591 6.90226
+7.68111 9.10704
+8.37958 8.73818
+3.25808 4.40893
+1.50348 3.00641
+0.20803 1.40949
+3.93771 4.84177
+2.79232 3.35329
+4.2666 4.63588
+0.341784 1.46241
+1.53063 2.06724
+8.58212 8.86194
+8.95411 9.70651
+8.71591 9.26292
+6.66088 6.7009
+3.95881 5.93917
+8.5823 8.76007
+-0.308958 0.34174
+1.03188 1.37677
+7.52675 9.84031
+4.27952 4.32984
+1.83465 2.27607
+8.12096 8.64922
+2.22605 4.40067
+0.00929139 0.871342
+0.376531 1.29354
+3.5257 4.30165
+1.95846 4.09589
+-0.200922 0.799272
+0.24432 1.76673
+4.73477 5.06514
+8.97059 9.2276
+2.89618 2.93969
+0.168256 1.03325
+3.44522 3.83622
+2.74889 2.76042
+6.07155 6.7979
+9.06484 9.09804
+7.56658 9.29215
+4.3084 5.45621
+-0.0786996 1.12809
+8.48249 9.74107
+6.4196 6.61469
+1.57119 1.87612
+3.15463 3.86251
+2.0089 2.57741
+6.53618 7.12035
+7.07901 7.29396
+0.114756 0.887413
+8.90806 9.65731
+4.0921 5.23407
+2.63441 2.92344
+4.31769 4.98832
+8.90336 9.26837
+8.25313 8.91204
+2.87758 4.00212
+-0.708243 0.789072
+3.28656 4.55872
+5.73177 5.80293
+5.40596 5.5844
+4.09318 4.57774
+6.16178 7.00613
+8.5514 10.5495
+6.83987 7.3056
+1.06341 1.97923
+7.82153 9.00722
+0.923069 1.42337
+1.83408 2.82331
+5.75305 7.23576
+0.241909 0.96721
+1.16645 2.10491
+5.41819 6.09839
+7.49242 7.69495
+0.347233 0.383681
+2.33245 2.53467
+4.91249 5.27759
+8.11182 9.2758
+0.0955456 0.548659
+-0.359909 0.48055
+1.64759 3.47097
+6.37855 7.40015
+0.423283 2.08857
+4.10068 4.46856
+2.58389 2.69626
+0.848483 2.72258
+8.67321 8.88903
+2.07607 3.42398
+3.11033 3.80741
+2.24735 3.48626
+8.11883 8.7687
+0.29959 1.41603
+4.84924 5.13641
+1.44102 1.74592
+1.13437 2.50296
+1.75876 3.09859
+4.75363 5.90838
+7.36423 8.20074
+5.51578 6.42652
+0.915633 1.86015
+9.44679 10.3479
+2.61691 3.60215
+6.26524 7.2538
+2.74326 3.12649
+5.83934 6.98592
+9.1111 10.4891
+2.27066 2.82709
+8.19359 8.67233
+0.834236 1.7066
+6.19288 7.21392
+-0.249843 0.891821
+2.5652 3.25132
+5.25356 5.88905
+3.99545 4.18918
+1.93186 2.51527
+4.44621 4.82421
+5.89181 7.36963
+2.77321 3.60627
+2.76444 3.88016
+2.50062 2.66105
+1.14846 1.66146
+2.951 4.81656
+3.81976 4.01061
+4.75674 5.59916
+6.74092 7.08289
+2.09989 2.32514
+0.220723 0.865303
+5.48107 5.71875
+1.48372 2.88941
+0.484577 1.12051
+8.93618 9.7185
+1.89769 3.65655
+2.0129 3.55214
+9.23173 10.3694
+0.286189 1.22753
+0.453785 1.55541
+2.24068 2.6541
+8.80917 10.4969
+7.12801 7.15222
+9.25745 9.9103
+5.73429 6.76901
+7.54454 8.47157
+1.96008 3.74997
+8.00837 9.25665
+1.66384 2.07613
+5.53014 5.97461
+-1.32495 1.33319
+4.58479 5.2263
+7.92048 8.75668
+6.87595 7.02522
+0.157713 0.389585
+7.48277 7.51261
+8.10714 8.38399
+0.0802723 0.587088
+1.13024 1.71135
+5.71769 6.84757
+3.08261 4.31054
+2.95952 5.09762
+6.62815 7.44256
+5.0805 5.8499
+3.38489 3.73265
+1.10644 2.18331
+4.70493 7.31686
+2.2253 2.6338
+0.778359 1.6265
+6.94211 7.2149
+4.20976 4.99342
+7.47792 7.67881
+7.06219 8.76137
+4.97677 6.12206
+6.30829 6.69361
+6.19977 6.76781
+9.67636 10.2172
+3.41958 3.69137
+0.374486 0.943711
+4.00837 4.80107
+8.85401 10.1325
+6.0938 7.8919
+1.51055 3.08998
+8.94594 10.3139
+1.06714 2.65511
+0.703202 0.850595
+4.87735 6.00659
+8.3067 8.39924
+7.78071 8.3155
+1.98737 2.81116
+6.86323 8.07974
+1.03479 1.34584
+0.490512 0.670211
+5.82122 6.1901
+5.50836 6.63385
+7.9192 8.9606
+0.913719 2.18983
+4.97151 5.70909
+4.19907 4.37712
+2.01188 2.63318
+7.84813 9.3771
+5.32667 7.48502
+8.50951 10.1006
+-0.551637 0.930509
+1.06511 2.23353
+1.91111 3.42663
+9.37528 9.55327
+7.27975 7.38741
+3.46676 4.83165
+7.36137 8.70333
+-0.295762 0.623228
+8.48558 8.81076
+2.71689 3.41873
+6.49265 8.11042
+5.25516 5.57336
+6.10462 7.05991
+8.76997 9.15164
+7.86196 8.30651
+7.82765 9.24604
+5.98573 6.34182
+6.45367 7.47857
+3.27018 5.10835
+1.3079 2.37423
+-0.261387 0.338113
+7.60683 8.81791
+4.7346 7.41988
+5.25597 5.28517
+3.76704 4.52226
+3.91774 6.66976
+5.69618 8.92667
+1.86148 3.07531
+5.57404 6.51438
+9.39049 9.77921
+2.38692 4.21416
+6.84909 7.23633
+7.2379 7.58761
+4.73485 6.11606
+7.80013 8.08105
+1.72701 3.40244
+2.44475 4.4072
+9.72565 9.77726
+3.35288 4.06493
+8.91215 9.92325
+8.67991 9.65865
+0.253195 0.764339
+4.23564 5.59497
+1.84752 2.14986
+-0.502957 0.528737
+1.32656 2.11347
+9.81563 10.0213
+7.60114 8.05035
+8.51797 8.83342
+-0.394604 1.41267
+7.71614 8.63514
+0.530249 0.968898
+2.90463 3.01675
+7.58098 8.71658
+-0.253747 1.28827
+1.832 2.39006
+7.2268 7.27225
+3.84076 4.66703
+2.2564 2.73185
+7.31508 8.46008
+4.99387 5.64948
+7.21239 7.79983
+7.60231 7.8473
+0.555482 1.41892
+1.25539 1.73665
+8.41561 8.96404
+5.06771 5.17664
+0.0655744 2.10718
+8.00222 8.65909
+7.48841 7.83609
+6.30909 6.89448
+9.1697 9.55942
+1.36259 2.22582
+-0.923854 0.994771
+3.43724 4.64053
+8.09411 8.19574
+4.84869 5.52805
+2.69802 3.4119
+9.0613 9.29405
+0.565216 0.687165
+5.93495 6.57426
+1.86925 2.75493
+1.41068 2.00824
+1.60612 1.62471
+3.11499 5.89909
+2.69806 3.90538
+3.76301 4.22135
+3.30065 4.70725
+5.56461 7.02137
+8.35335 8.99287
+4.79259 4.88508
+6.7911 7.52912
+8.14843 8.28583
+3.67629 5.06406
+5.71462 7.04747
+9.06721 9.99733
+4.87932 6.8586
+8.00814 9.57664
+7.03069 7.51623
+9.0989 9.57644
+2.70873 3.91296
+1.64425 1.7007
+6.53716 6.99033
+8.29874 8.74509
+1.88941 2.57626
+4.65337 5.23247
+9.04723 9.06665
+3.52258 3.61496
+1.1207 1.80143
+0.680601 1.98384
+2.94593 5.38692
+2.65685 2.67932
+9.00469 10.2054
+6.44318 7.2657
+4.66656 5.33893
+3.41719 4.72453
+3.12403 4.21748
+6.67973 6.81775
+3.54347 4.14978
+3.02554 3.50812
+3.91883 3.93657
+7.31721 7.89895
+1.86275 2.85473
+6.23266 6.4449
+7.59855 9.38013
+9.07084 9.49309
+0.557656 2.6851
+6.899 7.37693
+4.23162 5.84314
+8.54108 9.37672
+3.9513 4.79746
+7.299 8.29678
+5.58879 5.88551
+9.14992 9.22385
+9.1914 9.31788
+4.95663 5.56316
+2.16516 2.39538
+0.722262 1.89664
+7.76447 7.80026
+2.77772 3.39136
+9.59513 9.78635
+1.02728 1.2181
+7.32631 7.56611
+7.37389 7.46163
+6.87949 8.18689
+8.95602 9.81169
+5.85364 6.63434
+0.129136 2.13484
+7.09608 7.71167
+7.1487 8.34258
+7.48738 8.3172
+8.77247 9.95985
+7.6706 9.56828
+8.14268 8.61726
+6.5455 7.90871
+4.57866 4.78453
+3.63937 4.42349
+5.18905 5.36516
+4.68884 5.62995
+5.88338 7.83824
+-0.002979 0.145818
+4.42981 4.77141
+0.558593 1.07999
+6.91713 7.36159
+5.13948 6.20805
+3.34368 4.07112
+7.27365 7.8383
+9.6898 9.9514
+6.14332 6.75102
+2.16534 2.78843
+2.8007 4.37952
+7.67047 7.72955
+8.77377 9.85092
+1.26087 1.55193
+6.29788 6.58511
+7.68178 9.05777
+0.383336 1.21247
+2.55185 4.30874
+8.91971 9.21836
+3.67638 4.68596
+8.13843 9.13684
+-0.424353 1.97502
+2.71499 2.93977
+0.104447 0.387901
+4.09592 4.67009
+0.808593 0.920798
+5.01258 6.30662
+4.97668 6.57412
+8.44135 9.03816
+2.78932 3.72809
+6.71337 7.15128
+4.27234 4.50127
+6.78266 9.70351
+6.48026 7.51491
+7.36296 8.42283
+4.80339 7.3704
+6.24735 7.3132
+0.134626 0.364187
+2.73854 4.09422
+0.809997 1.19657
+6.41154 6.50244
+7.16847 8.56485
+1.53582 3.33985
+1.92874 2.86427
+6.95941 7.01378
+5.8592 6.54917
+2.51802 2.75622
+3.3894 3.6957
+2.2547 2.64693
+8.62054 9.1951
+8.86378 10.0003
+1.87892 2.28732
+3.83146 4.21484
+1.53262 1.99692
+7.86048 7.93125
+1.79437 2.68269
+3.92781 4.24119
+5.43044 5.47935
+0.322904 0.618854
+3.42383 5.18531
+4.00989 5.83612
+7.06304 8.76582
+5.88039 6.77654
+8.638 8.9479
+1.73391 2.09002
+1.04861 2.84779
+-0.313019 0.557659
+3.35245 4.1308
+9.05373 9.57205
+5.85684 6.49193
+6.00719 6.86421
+4.25244 4.65772
+5.15865 5.61529
+8.78498 9.77544
+8.33803 9.26452
+3.42915 4.92279
+8.29884 8.94035
+5.10232 5.35924
+4.33571 4.86695
+7.86184 7.90029
+7.34345 7.36214
+0.201624 0.800371
+9.05882 10.5503
+4.32188 5.03154
+-0.0456982 1.22298
+2.90921 3.60013
+1.69306 2.36564
+7.79029 9.15059
+4.65205 5.06538
+6.34552 8.32176
+7.92695 9.32585
+7.17903 8.09903
+9.53561 9.60287
+0.365723 1.23929
+0.542889 0.849053
+8.15061 8.93512
+6.40042 6.41053
+5.82666 6.5488
+1.00893 1.83717
+1.76021 2.11893
+7.61076 8.6242
+2.32513 3.4856
+4.39023 6.01094
+-0.11754 0.421848
+6.76371 6.94513
+4.67607 5.58732
+-0.201992 0.765553
+7.42926 7.44429
+2.57485 2.85339
+2.74138 4.13421
+8.21645 9.18107
+6.28184 6.4996
+7.129 7.74678
+7.76842 8.74924
+3.5359 4.35892
+3.04103 3.24376
+2.29389 2.92164
+6.96306 7.64415
+8.82053 9.04584
+1.19911 2.06167
+5.91357 7.6773
+0.150241 1.23291
+4.48681 5.41762
+6.89156 8.13443
+5.37828 5.79944
+2.13694 2.91102
+1.35932 2.08272
+6.14309 6.23278
+4.03202 5.88521
+7.23417 7.43704
+1.2501 2.60793
+2.12334 3.65727
+7.05722 8.77078
+0.437873 0.585933
+6.33338 9.16643
+2.44724 4.40234
+2.92012 3.64047
+1.2039 3.25195
+8.6611 10.0398
+8.0088 9.13622
+5.96562 7.08515
+5.45181 6.65246
+0.742546 2.38958
+4.12919 4.93571
+0.428823 0.84483
+1.45226 2.5869
+9.50727 10.0211
+7.69194 8.66273
+1.25706 2.44554
+5.23247 5.47762
+0.499178 1.70722
+7.26569 8.72467
+3.59815 5.50022
+1.03601 2.43445
+0.092414 0.927635
+3.7917 3.995
+6.21977 8.40398
+3.1513 3.81188
+9.80482 10.0951
+8.65564 9.33687
+2.06164 3.49152
+2.09754 2.34929
+0.66126 2.31888
+5.34832 6.82603
+7.91038 8.59105
+0.695523 0.800961
+2.33406 2.71629
+8.37774 10.9253
+9.7682 10.106
+9.44382 9.5743
+8.78009 9.47645
+1.87309 3.04127
+1.86724 2.13913
+3.30049 3.52416
+7.18508 7.6648
+1.3736 2.12153
+2.41879 5.06716
+1.87815 2.29743
+1.76646 2.06335
+9.73034 9.95475
+0.497489 0.686102
+6.96908 7.17338
+9.23111 10.0148
+3.30981 4.21787
+9.53311 10.3734
+-0.067709 0.147251
+8.44557 8.82047
+7.10407 7.47639
+0.834352 1.36908
+9.1598 10.6508
+4.22018 4.38279
+3.8295 3.95462
+3.97302 4.97247
+1.55856 2.31013
+0.0217962 0.486978
+1.69845 2.65786
+-0.489562 0.582187
+5.10621 5.6055
+9.8478 9.85919
+6.15389 6.92324
+7.11469 8.0418
+3.20625 3.78209
+5.93389 7.66892
+1.15134 1.18023
+6.84797 7.4239
+2.9483 3.22279
+-0.43205 0.764755
+7.17846 7.33313
+5.4729 8.26894
+6.19512 7.32132
+0.591934 0.767568
+0.49266 1.80691
+9.08272 9.72242
+5.85683 6.36905
+5.27625 7.13913
+3.60853 3.98155
+0.642811 1.10253
+1.27117 1.5329
+8.76096 9.61776
+4.9498 5.12847
+7.53282 7.80438
+1.40487 1.65657
+3.45329 3.84307
+3.25698 3.49614
+2.38651 2.89802
+8.23114 8.99016
+9.58516 10.4145
+5.5185 6.27733
+0.583068 0.892249
+1.93142 2.35084
+7.94845 9.22667
+2.47963 3.9005
+3.46106 3.86301
+7.77744 8.43735
+1.41072 1.73969
+9.12904 10.4307
+3.52227 3.66861
+5.4743 5.86487
+-0.51727 1.63657
+5.09861 7.03162
+5.14763 5.93411
+3.23526 3.47376
+0.9702 1.74063
+9.28366 10.3322
+1.80257 1.92265
+8.63597 9.08467
+4.16006 4.97753
+6.37418 6.39374
+5.82376 6.62429
+7.74751 8.68962
+1.63821 2.53399
+4.9864 6.40969
+0.680772 0.995608
+3.74344 3.83319
+0.898055 1.8593
+2.36839 2.39307
+7.21046 7.51006
+0.60893 2.91523
+3.15017 4.30412
+5.02219 6.28886
+4.60541 4.73379
+8.41196 8.58978
+8.84706 10.8198
+6.95807 7.54952
+5.54729 6.9315
+4.62574 4.73423
+3.35252 3.59865
+1.02207 1.71791
+3.16408 3.73993
+0.639222 1.69519
+7.57978 8.05813
+2.41371 2.77174
+8.65544 10.093
+6.31988 6.70758
+6.5301 8.39328
+0.578825 1.20331
+1.1243 2.07824
+5.86555 6.72397
+6.37103 6.81736
+1.12086 3.46541
+2.59503 3.44073
+5.27128 5.3616
+2.87331 3.4352
+5.48408 6.67916
+3.36016 4.09125
+0.813671 0.9811
+0.812162 3.22209
+6.85104 6.86306
+0.671311 0.979685
+2.75962 2.82659
+2.42186 2.49827
+7.82974 9.59669
+3.48851 3.60085
+8.47775 10.9574
+8.6863 10.6155
+0.196484 1.07469
+1.19293 1.45012
+5.79166 6.18466
+6.51597 6.6793
+9.78341 10.1992
+8.17879 9.59257
+6.96178 8.73165
+4.09161 4.31908
+3.19514 3.4072
+5.5101 6.32978
+0.188435 1.84481
+9.41738 10.0379
+1.46994 1.6294
+4.21915 5.39529
+5.46567 5.86638
+8.19414 9.201
+4.38616 4.55193
+2.31105 2.73345
+6.05897 6.12297
+8.84135 9.74232
+9.44943 10.2225
+3.27501 3.66059
+0.524904 1.74374
+7.7228 8.43799
+5.13274 5.82863
+8.2787 8.94491
+1.61463 2.03499
+7.04346 8.69977
+0.938308 2.38676
+0.00208037 0.0186158
+1.98744 2.05864
+7.05787 8.16211
+1.68383 2.04684
+2.24812 2.28257
+0.685061 1.2947
+2.25379 2.92827
+6.0052 6.24797
+7.06213 7.86344
+0.751849 2.96376
+0.0977921 0.513746
+8.43792 9.10545
+2.80769 3.09276
+9.19308 9.59741
+4.74365 4.99708
+8.41385 8.58422
+4.28093 5.9281
+4.26205 4.75417
+1.48035 1.61363
+1.4264 1.80922
+3.48365 4.52935
+1.78396 2.96351
+8.4134 8.96536
+8.65646 9.34781
+1.88027 2.97804
+8.92531 9.02743
+6.91815 7.88895
+5.68023 7.37521
+3.93105 4.6123
+0.385874 1.30785
+1.80151 2.24385
+8.43781 9.33927
+6.69643 8.001
+6.12062 6.673
+4.8316 6.63067
+9.00443 9.08204
+1.5651 2.65023
+3.57517 4.40231
+5.85127 8.02219
+8.02586 10.018
+2.00514 2.75138
+6.32104 7.84285
+8.90914 9.78319
+4.91325 6.27817
+3.87406 4.80327
+8.57887 9.30685
+1.40351 1.71079
+-0.217977 0.224497
+8.37711 9.56393
+5.54644 5.77714
+8.18206 8.36015
+0.774967 1.97899
+9.10434 10.1721
+9.39621 10.1135
+4.80108 4.90605
+9.45978 9.96227
+2.85412 4.05215
+5.71985 7.16735
+2.35081 2.82214
+9.34881 10.5899
+7.13014 7.82872
+4.54931 4.89725
+9.41397 9.9131
+8.90226 9.55276
+8.27995 9.83651
+9.2767 9.6053
+0.388751 1.40317
+5.01478 5.88869
+6.41521 7.21754
+1.22552 1.39067
+3.75771 3.81571
+4.39362 6.04592
+8.82639 8.84544
+4.59289 4.89208
+1.52235 1.64285
+1.85893 4.52056
+1.91781 2.78253
+3.34677 4.54987
+9.26905 10.6019
+7.10958 8.02083
+0.765257 1.66957
+2.17169 2.70214
+4.2293 6.38089
+1.41111 2.45992
+5.76864 6.85715
+2.19944 2.93182
+9.03727 9.6454
+3.82652 4.35225
+2.52642 3.09725
+7.77868 9.35844
+0.337665 1.00787
+1.92021 2.04418
+4.41862 5.95486
+9.47606 9.62386
+1.12113 1.55658
+5.26701 7.09712
+8.81478 9.34863
+6.29447 7.43847
+2.82379 3.57268
+7.9735 8.79936
+3.30176 5.50666
+6.36009 6.8864
+4.13583 5.00627
+0.510514 0.882245
+6.93864 7.78543
+2.04039 2.4298
+3.18337 3.19424
+4.20059 4.67088
+0.316687 0.707377
+0.169106 1.68194
+8.26665 10.2362
+1.1124 1.78306
+2.84603 3.33142
+9.48756 9.96651
+9.4301 9.7316
+0.234674 1.23981
+0.493232 0.522565
+1.342 1.41739
+2.57196 4.08221
+1.54201 2.52284
+5.32049 6.00052
+8.54218 8.59452
+-0.030524 1.64476
+2.31645 2.72528
+4.71898 4.92827
+0.0872997 1.74969
+0.994278 1.76964
+1.34411 2.77952
+0.156817 2.10245
+5.78094 6.34389
+3.09336 3.10563
+8.14245 9.0928
+9.34202 9.75484
+9.78415 10.0211
+4.68383 5.19384
+6.09441 7.90512
+6.74941 6.76118
+1.78693 1.91697
+2.34369 2.62141
+-0.20756 0.829082
+3.57681 5.11448
+2.44234 4.45153
+4.84521 5.31902
+1.80487 3.64498
+2.46125 3.02549
+-0.334514 0.64288
+8.06406 8.49886
+1.74559 2.54474
+6.05883 6.46529
+9.00014 10.2271
+8.00064 8.5061
+0.909467 0.980765
+8.65862 8.69736
+8.11457 8.77049
+3.93237 5.02485
+4.64507 5.34852
+3.92405 4.19449
+5.02381 5.21722
+3.76203 3.78396
+6.74925 7.34781
+8.2556 8.63585
+3.92521 3.99739
+1.44641 2.31509
+0.23516 0.917239
+4.4614 6.35489
+3.33221 3.95247
+1.73289 2.07919
+6.92385 7.55052
+8.74351 9.41125
+9.41451 10.1785
+7.4001 8.81081
+2.97038 3.12524
+7.26043 7.77569
+5.56625 5.59344
+5.70977 6.33362
+7.61443 8.43218
+1.05308 1.82947
+0.377602 1.57633
+6.42483 7.51505
+4.73011 5.43693
+7.72 8.09098
+9.20063 9.82287
+6.88273 7.35327
+6.88423 7.68356
+3.55293 3.6227
+0.947096 1.76021
+3.66411 5.67117
+9.31422 10.1035
+6.84847 6.98956
+2.16221 4.45806
+0.853284 3.15932
+2.48673 2.89793
+3.37633 3.90938
+1.6141 1.66363
+1.6658 3.01723
+0.419408 1.01736
+0.712239 0.791538
+2.25249 3.62425
+8.09772 10.2367
+1.46651 1.48148
+1.73233 2.0489
+7.42679 9.23232
+7.97446 9.53281
+2.74677 4.03955
+-0.169412 0.872795
+4.90663 5.40277
+7.62122 9.49334
+6.55971 7.34259
+3.71957 5.03775
+3.33226 4.06459
+0.634912 1.52603
+3.65506 4.09318
+4.31463 4.60534
+8.58287 9.85385
+0.334759 0.7232
+2.14027 2.866
+6.06611 6.3625
+2.53013 3.18764
+4.30913 4.89247
+6.53234 6.92328
+7.66419 8.61762
+1.37598 2.26754
+8.06279 8.80692
+5.28688 5.70608
+0.509396 1.34606
+8.80589 9.29765
+9.3801 10.3988
+0.402662 0.597735
+5.87213 6.63371
+2.79136 3.763
+6.20615 7.25189
+7.54065 9.62156
+4.12107 5.04454
+5.60294 6.69246
+1.20845 1.49272
+1.75679 2.56397
+2.83939 3.85147
+6.21362 6.71341
+9.01824 9.2388
+4.66617 5.04944
+1.48766 2.55674
+8.89442 9.42175
+5.29411 5.39531
+6.66271 8.68733
+0.730461 1.42466
+6.22927 6.55086
+0.566776 1.17299
+3.06104 4.17775
+5.28026 5.73966
+5.76071 7.61585
+7.83786 9.58106
+6.32199 6.46961
+8.89555 9.17429
+3.85772 4.97805
+6.63352 8.79211
+7.87234 7.94131
+6.53479 7.87979
+3.90293 4.50376
+6.21371 7.31788
+1.00497 1.75003
+6.90351 8.02435
+2.29142 3.9809
+6.26632 6.45283
+-0.0354471 1.31727
+8.80046 9.20169
+7.86905 8.36819
+0.848737 1.82393
+7.98136 9.40712
+3.97765 4.95399
+8.70252 9.26275
+3.13412 4.29389
+2.06446 3.55839
+7.67918 8.44509
+5.96082 6.40336
+1.20461 2.36924
+4.76741 5.74978
+9.41217 9.94305
+7.36736 8.07119
+3.44102 3.56957
+3.59893 4.52751
+4.2613 6.41628
+1.65321 3.02235
+3.70067 3.86657
+0.0176327 1.1215
+4.13592 4.88595
+8.73668 9.0834
+1.80944 2.95584
+6.05721 6.93009
+5.08206 5.38626
+1.86749 1.89392
+3.58284 4.10506
+0.0885586 1.47709
+5.46502 5.93066
+8.45338 8.47878
+3.46789 4.02317
+0.975506 1.15814
+7.12758 7.60073
+7.99582 8.56746
+3.11435 3.83805
+4.51166 4.52472
+8.39096 8.75934
+8.42208 9.66019
+2.48498 4.73703
+3.50301 4.81264
+6.40196 7.0733
+8.52138 8.82265
+1.49822 1.74634
+7.08547 7.93508
+3.47832 4.42948
+6.08646 6.20865
+4.46334 4.65278
+3.80008 4.08214
+3.4853 5.44308
+5.48109 6.18681
+6.59161 8.04307
+7.36554 7.38201
+5.2144 5.31725
+4.62607 7.25804
+1.24345 1.81263
+5.49248 8.16867
+6.4056 8.26316
+7.67828 8.56923
+2.46187 2.56974
+2.22942 3.27248
+7.14933 8.06682
+2.3236 2.95462
+4.18028 4.80535
+4.981 5.54215
+7.23261 7.34863
+4.96309 6.06396
+4.24402 4.44364
+0.917707 1.32687
+1.19806 1.65106
+3.7725 5.31412
+9.70021 9.84203
+5.99824 7.77474
+3.32636 3.84266
+8.59841 9.07653
+7.9916 9.14415
+0.786519 1.84655
+0.166394 1.47834
+2.87633 3.52808
+7.53804 9.56807
+6.14406 6.16189
+1.63428 3.96845
+1.10307 1.58897
+1.30032 2.85313
+7.89803 8.32723
+8.77593 8.90136
+1.68804 2.69447
+4.5956 4.6743
+7.39643 8.29839
+6.93629 7.82243
+6.10289 7.677
+1.83835 2.34295
+1.04506 1.91684
+8.95277 9.43817
+0.36153 0.643665
+1.02408 3.18963
+4.02972 4.40301
+2.80428 2.82552
+6.51718 6.64956
+0.185341 1.56607
+6.1658 7.59364
+4.09288 4.11687
+6.90205 7.16338
+5.0755 5.39478
+4.5614 4.83286
+5.8489 8.76295
+9.70079 10.0431
+8.44334 8.54714
+3.00139 3.66327
+5.34458 6.38895
+7.11481 7.96865
+4.66776 5.15678
+0.390138 0.53352
+2.01116 3.32839
+6.78761 6.97068
+4.57477 5.0724
+1.14098 1.36134
+7.4559 8.30327
+0.700932 2.40437
+1.90469 1.99046
+4.30064 5.11485
+7.84433 8.48543
+5.96212 7.49882
+3.93055 3.96317
+0.546327 1.04814
+8.96011 9.0404
+7.89255 8.06149
+0.669924 2.6944
+-0.00972314 0.837474
+6.07199 6.37467
+2.73659 3.19833
+5.9576 7.10966
+9.1316 9.14737
+5.26101 6.59184
+5.77697 8.08876
+0.68623 0.782805
+0.842619 1.39893
+5.82075 6.15957
+4.36394 4.88479
+7.1828 7.90107
+3.3331 4.39923
+6.54243 7.24966
+2.809 2.96491
+4.18514 4.61948
+4.95453 5.33929
+8.33288 9.52867
+9.05785 10.4276
+2.58917 4.74403
+1.34279 1.89014
+4.93626 5.75424
+7.75031 7.92788
+9.00904 9.02402
+3.91286 5.15124
+6.98486 7.34688
+-0.173169 0.415019
+0.652242 1.51556
+3.50184 5.30486
+3.72563 4.09022
+4.60463 6.58985
+3.34219 4.31833
+2.55445 2.58651
+6.14573 6.3669
+4.52336 6.37342
+9.37606 9.76836
+2.4198 3.36929
+2.89109 3.66974
+5.62463 6.05989
+0.674219 1.84165
+0.590017 1.71153
+1.54622 2.10277
+6.48003 6.55663
+3.56355 3.98573
+0.743671 1.87049
+3.27833 6.0722
+4.76267 6.9967
+2.80188 4.03037
+0.372694 0.482111
+5.73987 5.9529
+8.84732 9.49033
+0.833944 1.8157
+4.06126 4.36615
+0.884619 2.34622
+6.86723 6.99141
+8.07737 9.05193
+8.35903 9.00761
+8.84777 9.74001
+8.58058 9.05479
+8.28076 8.44566
+4.55155 5.65475
+2.44314 3.38966
+3.22172 4.50395
+7.1808 7.90376
+0.639636 1.72606
+5.46807 5.94322
+9.02146 9.87864
+-0.628472 0.655557
+4.29775 5.9553
+6.77525 7.38152
+6.51827 6.93542
+8.95252 9.52939
+0.755406 1.19973
+7.69455 7.86912
+0.170143 1.12949
+7.69254 8.08221
+2.08238 3.27051
+1.28662 1.78628
+1.21208 2.79391
+-0.155739 1.7071
+8.28833 9.10011
+5.77789 6.6954
+1.98395 2.35216
+5.77469 6.05177
+2.77565 5.81092
+-1.53416 2.30576
+6.93529 8.04506
+3.91553 4.55593
+5.57201 6.29071
+1.54149 1.86613
+4.09163 4.31234
+8.47834 11.1229
+5.70376 7.02981
+2.24683 3.79925
+5.4793 6.41036
+5.27644 6.81729
+0.13273 0.371437
+1.22959 1.41618
+0.551957 1.03276
+2.01269 2.4018
+8.77113 9.09395
+8.11753 8.46262
+0.39406 0.783705
+5.35964 5.48227
+7.24727 8.23233
+7.74525 8.85748
+0.0115736 0.882607
+1.78575 2.19684
+8.32514 9.0503
+3.11074 3.34975
+0.847464 2.13237
+0.310898 0.393528
+8.68841 10.518
+1.10032 1.83755
+2.42286 3.02554
+1.16364 2.80986
+1.46419 2.11421
+7.46021 7.90273
+6.86556 7.62542
+1.91466 3.79843
+3.1056 3.83969
+3.41591 4.26565
+0.285122 1.21372
+3.75441 5.52385
+1.07643 2.63403
+6.17341 7.67244
+9.13122 9.5132
+4.39696 6.15885
+3.7207 4.07729
+6.80782 7.1958
+6.65933 6.67105
+8.51535 8.7263
+5.98305 7.17759
+2.19609 2.46108
+8.21186 8.96908
+2.94729 3.60562
+3.31907 3.9297
+0.463492 0.626603
+2.62143 3.55089
+5.76898 6.79002
+1.45502 1.56525
+4.80797 5.62389
+5.87337 6.70588
+2.92765 3.50929
+0.412987 0.951057
+3.64594 4.40269
+-0.043401 0.502176
+4.54802 5.44613
+1.20218 1.8732
+2.75547 2.96745
+7.10348 7.7945
+9.74845 9.98835
+4.83718 6.4836
+2.30563 2.5903
+4.74016 6.30789
+6.42192 6.93329
+5.37294 6.73938
+2.4365 3.05787
+1.08283 3.79193
+4.90426 5.93563
+3.8874 4.83301
+0.13909 0.983027
+4.07407 5.61421
+8.62875 10.6851
+8.10233 8.29952
+2.23047 2.4691
+7.34617 7.39475
+1.66309 2.3032
+7.11207 10.0686
+4.52412 6.38666
+2.48323 2.96878
+7.47877 8.86547
+2.67607 4.33436
+6.83659 8.21075
+2.87313 3.39011
+2.81911 4.07729
+0.227877 0.657898
+6.57843 7.14311
+-0.591405 1.56925
+7.08018 7.59
+9.09558 9.3923
+9.48544 9.79474
+0.740233 2.33129
+8.51111 11.134
+7.79219 8.0281
+1.73821 1.89316
+9.21077 9.29488
+5.38354 6.46025
+4.30403 4.5472
+0.0893758 0.919238
+7.94464 8.51053
+5.27119 6.3741
+5.22476 6.00588
diff --git a/bottleneck/tests/data/test_013_A b/bottleneck/tests/data/test_013_A
new file mode 100644
index 0000000..51cff1c
--- /dev/null
+++ b/bottleneck/tests/data/test_013_A
@@ -0,0 +1,5 @@
+7.50638 7.78005
+0.991758 2.12178
+5.18481 6.61702
+6.14703 7.08581
+4.09936 4.83024
diff --git a/bottleneck/tests/data/test_013_B b/bottleneck/tests/data/test_013_B
new file mode 100644
index 0000000..be62ed3
--- /dev/null
+++ b/bottleneck/tests/data/test_013_B
@@ -0,0 +1,5 @@
+5.8232 6.36308
+2.16066 2.48668
+2.38754 4.91418
+4.77403 5.43982
+0.291412 1.11147
diff --git a/bottleneck/tests/data/test_014_A b/bottleneck/tests/data/test_014_A
new file mode 100644
index 0000000..f7f90ff
--- /dev/null
+++ b/bottleneck/tests/data/test_014_A
@@ -0,0 +1 @@
+1.0 1.0
diff --git a/bottleneck/tests/data/test_014_B b/bottleneck/tests/data/test_014_B
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/bottleneck/tests/data/test_014_B
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/bottleneck/tests/data/test_015_A b/bottleneck/tests/data/test_015_A
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/bottleneck/tests/data/test_015_A
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/bottleneck/tests/data/test_015_B b/bottleneck/tests/data/test_015_B
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/bottleneck/tests/data/test_015_B
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/bottleneck/tests/data/test_016_A b/bottleneck/tests/data/test_016_A
new file mode 100644
index 0000000..151d4b1
--- /dev/null
+++ b/bottleneck/tests/data/test_016_A
@@ -0,0 +1,220 @@
+1.391781911475341 1.391781911475341
+1.395142124726278 1.395142124726278
+1.514181227875788 1.514181227875788
+1.528291566797427 1.528291566797427
+1.585389310674157 1.585389310674157
+1.629232116709072 1.629232116709072
+1.641428662445941 1.641428662445941
+1.646998748860116 1.646998748860116
+1.652915988616469 1.652915988616469
+1.69199679556404 1.69199679556404
+1.705727462482595 1.705727462482595
+1.706819293048617 1.706819293048617
+1.720175733750729 1.720175733750729
+1.728031840308488 1.728031840308488
+1.73797421040929 1.73797421040929
+1.739519744204842 1.739519744204842
+1.76132425248022 1.76132425248022
+1.767766952966369 1.767766952966369
+1.792444271021371 1.792444271021371
+1.831487552809192 1.831487552809192
+1.837086616049901 1.837086616049901
+1.851186504948943 1.851186504948943
+1.860502132730509 1.860502132730509
+1.8619433117852 1.8619433117852
+1.878229072834972 1.878229072834972
+1.880655074837347 1.880655074837347
+1.883647832802556 1.883647832802556
+1.884127769927503 1.884127769927503
+1.892969784466709 1.892969784466709
+1.916936460787894 1.916936460787894
+1.931545068229315 1.931545068229315
+1.937626522143119 1.937626522143119
+1.942267721488891 1.942267721488891
+1.963295334827521 1.963295334827521
+1.975655395743736 1.975655395743736
+1.981448090925679 1.981448090925679
+1.986220565173897 1.986220565173897
+1.98709020812351 1.98709020812351
+1.989420269013254 1.989420269013254
+2.007874648480185 2.007874648480185
+2.012179388983059 2.012179388983059
+2.019051972834053 2.019051972834053
+2.023278848058142 2.023278848058142
+2.026190677562545 2.026190677562545
+2.041594763633561 2.041594763633561
+2.042508934597344 2.042508934597344
+2.04305394648524 2.04305394648524
+2.052514683218775 2.052514683218775
+2.059038785694094 2.059038785694094
+2.062577320792516 2.062577320792516
+2.063488177732052 2.063488177732052
+2.067806664626417 2.067806664626417
+2.073013782498534 2.073013782498534
+2.08646120854976 2.08646120854976
+2.098476357223667 2.098476357223667
+2.101378199886176 2.101378199886176
+2.101927506425904 2.101927506425904
+2.12671744783454 2.12671744783454
+2.143966150630584 2.143966150630584
+2.145312642688415 2.145312642688415
+2.148704396208969 2.148704396208969
+2.153092682531471 2.153092682531471
+2.157553654759374 2.157553654759374
+2.176659075756566 2.176659075756566
+2.177260578806816 2.177260578806816
+2.179141269427014 2.179141269427014
+2.201895416482074 2.201895416482074
+2.202563945779844 2.202563945779844
+2.205113735193028 2.205113735193028
+2.207345865351049 2.207345865351049
+2.208922099676958 2.208922099676958
+2.218057898922937 2.218057898922937
+2.228610453267036 2.228610453267036
+2.241314066596301 2.241314066596301
+2.242145210071643 2.242145210071643
+2.253976266568437 2.253976266568437
+2.255324860119305 2.255324860119305
+2.271300972641221 2.271300972641221
+2.279438361991067 2.279438361991067
+2.286592331830957 2.286592331830957
+2.287159411646074 2.287159411646074
+2.296653147995115 2.296653147995115
+2.301754785182811 2.301754785182811
+2.30409930499031 2.30409930499031
+2.32141477565108 2.32141477565108
+2.347789281926012 2.347789281926012
+2.347827987256373 2.347827987256373
+2.349391321950732 2.349391321950732
+2.350129292983257 2.350129292983257
+2.358679083392328 2.358679083392328
+2.372845273125388 2.372845273125388
+2.385040766846267 2.385040766846267
+2.42114588843816 2.42114588843816
+2.425116524931602 2.425116524931602
+2.426518521893022 2.426518521893022
+2.43211651886311 2.43211651886311
+2.441302771998711 2.441302771998711
+2.446429340510857 2.446429340510857
+2.446547553904861 2.446547553904861
+2.45764765793376 2.45764765793376
+2.461222149682938 2.461222149682938
+2.467900747394114 2.467900747394114
+2.473214152160872 2.473214152160872
+2.5 2.5
+2.503557913626332 2.503557913626332
+2.504315621146863 2.504315621146863
+2.515634290122204 2.515634290122204
+2.516231935083851 2.516231935083851
+2.517558892374071 2.517558892374071
+2.526325773757754 2.526325773757754
+2.531164001388939 2.531164001388939
+2.53128061055404 2.53128061055404
+2.539387277827314 2.539387277827314
+2.540864599180268 2.540864599180268
+2.548084457784768 2.548084457784768
+2.548923292215475 2.548923292215475
+2.551730202825644 2.551730202825644
+2.553178578801818 2.553178578801818
+2.560295747947446 2.560295747947446
+2.566321603108612 2.566321603108612
+2.568932286976676 2.568932286976676
+2.574887688783916 2.574887688783916
+2.581809142325336 2.581809142325336
+2.584541960262555 2.584541960262555
+2.585511915815223 2.585511915815223
+2.592970592044868 2.592970592044868
+2.596055336381078 2.596055336381078
+2.598560573626668 2.598560573626668
+2.614019084614256 2.614019084614256
+2.618463725327216 2.618463725327216
+2.622883674481145 2.622883674481145
+2.627791161528314 2.627791161528314
+2.63535653879261 2.63535653879261
+2.654825898255443 2.654825898255443
+2.660423271276714 2.660423271276714
+2.667148030102869 2.667148030102869
+2.67012591760915 2.67012591760915
+2.698712599567882 2.698712599567882
+2.72180967799905 2.72180967799905
+2.732466204434637 2.732466204434637
+2.734187392905275 2.734187392905275
+2.737296308103857 2.737296308103857
+2.745724923243991 2.745724923243991
+2.749541709159369 2.749541709159369
+2.752925621447035 2.752925621447035
+2.754183973113479 2.754183973113479
+2.763972022430258 2.763972022430258
+2.766941997926879 2.766941997926879
+2.773850925522978 2.773850925522978
+2.777506755238121 2.777506755238121
+2.780333194223143 2.780333194223143
+2.783060349483276 2.783060349483276
+2.78679029681548 2.78679029681548
+2.786792895521339 2.786792895521339
+2.795170825459034 2.795170825459034
+2.801104989227437 2.801104989227437
+2.80525433080833 2.80525433080833
+2.805376738133109 2.805376738133109
+2.806844454092663 2.806844454092663
+2.811611818684648 2.811611818684648
+2.811994908451803 2.811994908451803
+2.816002798930236 2.816002798930236
+2.816814002472584 2.816814002472584
+2.818569391261086 2.818569391261086
+2.821660827076439 2.821660827076439
+2.822317588351085 2.822317588351085
+2.824910409962511 2.824910409962511
+2.829322097471409 2.829322097471409
+2.833852169620359 2.833852169620359
+2.839287537694811 2.839287537694811
+2.841714730677953 2.841714730677953
+2.841715058318205 2.841715058318205
+2.851653306950001 2.851653306950001
+2.853639002902003 2.853639002902003
+2.85515962291442 2.85515962291442
+2.855333736885793 2.855333736885793
+2.872540314564304 2.872540314564304
+2.879449214478037 2.879449214478037
+2.881003856158217 2.881003856158217
+2.881074731438092 2.881074731438092
+2.893589165559115 2.893589165559115
+2.898664743213686 2.898664743213686
+2.90387832180792 2.90387832180792
+2.919095859678745 2.919095859678745
+2.924945175440496 2.924945175440496
+2.931795145696962 2.931795145696962
+2.932285006979528 2.932285006979528
+2.934606807227626 2.934606807227626
+2.936392671567475 2.936392671567475
+2.953794710898493 2.953794710898493
+2.958055395706548 2.958055395706548
+2.960407744013656 2.960407744013656
+2.960759715914242 2.960759715914242
+2.969702548922556 2.969702548922556
+2.970149844982665 2.970149844982665
+2.978953970679893 2.978953970679893
+2.979075864664287 2.979075864664287
+2.984665519558418 2.984665519558418
+3.04548240149063 3.04548240149063
+3.050688336416719 3.050688336416719
+3.05773927378742 3.05773927378742
+3.059596740753369 3.059596740753369
+3.059762479996741 3.059762479996741
+3.088543279751235 3.088543279751235
+3.093580813520995 3.093580813520995
+3.104787362108069 3.104787362108069
+3.173380191779681 3.173380191779681
+3.583124637167399 3.583124637167399
+3.630658112409034 3.630658112409034
+3.631421639368965 3.631421639368965
+3.751087101339956 3.751087101339956
+3.800845709568037 3.800845709568037
+3.846558940956666 3.846558940956666
+4 4
+4 4
+4.076238038291317 4.076238038291317
+4.455547086147983 4.455547086147983
+5.356087357608394 5.356087357608394
+5.54364842773721 5.54364842773721
+7.587654388717225 7.587654388717225
diff --git a/bottleneck/tests/data/test_016_B b/bottleneck/tests/data/test_016_B
new file mode 100644
index 0000000..bb8655a
--- /dev/null
+++ b/bottleneck/tests/data/test_016_B
@@ -0,0 +1,193 @@
+1.167089173446239 1.167089173446239
+1.256234452640111 1.256234452640111
+1.303693422257498 1.303693422257498
+1.413255970488646 1.413255970488646
+1.697910382446573 1.697910382446573
+1.718844728805093 1.718844728805093
+1.734124820632724 1.734124820632724
+1.749572938304276 1.749572938304276
+1.770320424526358 1.770320424526358
+1.786344763036807 1.786344763036807
+1.810054737907635 1.810054737907635
+1.815127306170105 1.815127306170105
+1.837806648681218 1.837806648681218
+1.870552189043019 1.870552189043019
+1.897240351979503 1.897240351979503
+1.935562152643027 1.935562152643027
+1.952562418976663 1.952562418976663
+1.959552126104175 1.959552126104175
+1.979899732318601 1.979899732318601
+2.00044500769347 2.00044500769347
+2.028951227523087 2.028951227523087
+2.037678749316724 2.037678749316724
+2.047911420446857 2.047911420446857
+2.075181804515723 2.075181804515723
+2.077245386452578 2.077245386452578
+2.084751316684838 2.084751316684838
+2.084860886126203 2.084860886126203
+2.103286477421968 2.103286477421968
+2.106856827309345 2.106856827309345
+2.113139266068691 2.113139266068691
+2.114594962503455 2.114594962503455
+2.115917727493158 2.115917727493158
+2.122335878797089 2.122335878797089
+2.127359082726206 2.127359082726206
+2.131673381033273 2.131673381033273
+2.155015793320908 2.155015793320908
+2.162480684365264 2.162480684365264
+2.195207236194009 2.195207236194009
+2.203279931784429 2.203279931784429
+2.205567995563669 2.205567995563669
+2.212933962936773 2.212933962936773
+2.215081271089993 2.215081271089993
+2.225989037578865 2.225989037578865
+2.24218929203347 2.24218929203347
+2.246321319993257 2.246321319993257
+2.280059407166517 2.280059407166517
+2.284117669032543 2.284117669032543
+2.293233992770926 2.293233992770926
+2.298815356955373 2.298815356955373
+2.300542634724628 2.300542634724628
+2.326408290042679 2.326408290042679
+2.328797162040625 2.328797162040625
+2.36025798094028 2.36025798094028
+2.365031313604634 2.365031313604634
+2.372266311053883 2.372266311053883
+2.400053902049271 2.400053902049271
+2.409134054334209 2.409134054334209
+2.411368235895246 2.411368235895246
+2.415934766378347 2.415934766378347
+2.420989857074179 2.420989857074179
+2.422520269961376 2.422520269961376
+2.43377629944218 2.43377629944218
+2.449308615746858 2.449308615746858
+2.452936540056068 2.452936540056068
+2.453698388060092 2.453698388060092
+2.454711357943602 2.454711357943602
+2.459202673400056 2.459202673400056
+2.493778305287384 2.493778305287384
+2.537394117473177 2.537394117473177
+2.544674753106669 2.544674753106669
+2.558904304820755 2.558904304820755
+2.563089994365716 2.563089994365716
+2.565476194422898 2.565476194422898
+2.599756049189921 2.599756049189921
+2.603619661709009 2.603619661709009
+2.609775379385211 2.609775379385211
+2.622552038976658 2.622552038976658
+2.623798471910885 2.623798471910885
+2.635711198661633 2.635711198661633
+2.644229304223612 2.644229304223612
+2.661919064427223 2.661919064427223
+2.666783921498494 2.666783921498494
+2.675503310152301 2.675503310152301
+2.684228699964661 2.684228699964661
+2.696854617267681 2.696854617267681
+2.700538654666735 2.700538654666735
+2.744886611436907 2.744886611436907
+2.748618547996708 2.748618547996708
+2.757981496641135 2.757981496641135
+2.774766825791652 2.774766825791652
+2.784491736143893 2.784491736143893
+2.796482184304273 2.796482184304273
+2.800849254751463 2.800849254751463
+2.816963410000067 2.816963410000067
+2.825207379914743 2.825207379914743
+2.831286409028398 2.831286409028398
+2.844827082550712 2.844827082550712
+2.853558438121966 2.853558438121966
+2.859806035663089 2.859806035663089
+2.878956033959891 2.878956033959891
+2.886422825109222 2.886422825109222
+2.891566924618832 2.891566924618832
+2.892028419188578 2.892028419188578
+2.893138900330932 2.893138900330932
+2.894250936382814 2.894250936382814
+2.90112201577666 2.90112201577666
+2.902172795370005 2.902172795370005
+2.90967533504119 2.90967533504119
+2.919687125962211 2.919687125962211
+2.923711238894001 2.923711238894001
+2.929041907338841 2.929041907338841
+2.938734873084349 2.938734873084349
+2.939642428979572 2.939642428979572
+2.943010909640486 2.943010909640486
+2.944210926048103 2.944210926048103
+2.951091358234723 2.951091358234723
+2.953950275008233 2.953950275008233
+2.966943157369611 2.966943157369611
+2.982522008227535 2.982522008227535
+2.992174049247434 2.992174049247434
+2.993098995839607 2.993098995839607
+2.995311055519335 2.995311055519335
+2.996708164866609 2.996708164866609
+2.999922110096644 2.999922110096644
+3 3
+3.000364533251431 3.000364533251431
+3.003840990677832 3.003840990677832
+3.006672301312824 3.006672301312824
+3.016489409140306 3.016489409140306
+3.021123787004333 3.021123787004333
+3.039117818612596 3.039117818612596
+3.039555193616473 3.039555193616473
+3.049952247267922 3.049952247267922
+3.057673482371216 3.057673482371216
+3.06920083507411 3.06920083507411
+3.075505231082782 3.075505231082782
+3.079038628197304 3.079038628197304
+3.084265889701239 3.084265889701239
+3.086837468106297 3.086837468106297
+3.103873984398081 3.103873984398081
+3.11528125482979 3.11528125482979
+3.119720021802376 3.119720021802376
+3.132543753577128 3.132543753577128
+3.141822873359038 3.141822873359038
+3.143502053175705 3.143502053175705
+3.153232877003746 3.153232877003746
+3.157586960809866 3.157586960809866
+3.157966892275408 3.157966892275408
+3.163583225161638 3.163583225161638
+3.178188125342772 3.178188125342772
+3.178475867931057 3.178475867931057
+3.179372297765929 3.179372297765929
+3.186437137237586 3.186437137237586
+3.188053957464282 3.188053957464282
+3.199351610026191 3.199351610026191
+3.204566427513051 3.204566427513051
+3.22885278850648 3.22885278850648
+3.229088648916556 3.229088648916556
+3.236685523936269 3.236685523936269
+3.239854786600373 3.239854786600373
+3.255809161351669 3.255809161351669
+3.287718056143732 3.287718056143732
+3.294038308299402 3.294038308299402
+3.313688277153076 3.313688277153076
+3.325783245946608 3.325783245946608
+3.331072954808429 3.331072954808429
+3.354962852285211 3.354962852285211
+3.357502741262644 3.357502741262644
+3.373668509804576 3.373668509804576
+3.408653045775418 3.408653045775418
+3.416281541503763 3.416281541503763
+3.443144279972986 3.443144279972986
+3.492970564191033 3.492970564191033
+3.493767805580122 3.493767805580122
+3.559084134799019 3.559084134799019
+3.559898699300211 3.559898699300211
+3.833585501974904 3.833585501974904
+4.099502076836052 4.099502076836052
+4.484082147277348 4.484082147277348
+4.505718324707756 4.505718324707756
+4.891723119528026 4.891723119528026
+5.065300494905414 5.065300494905414
+5.188599238535201 5.188599238535201
+5.36134479630535 5.36134479630535
+5.609786508140671 5.609786508140671
+7.08640314680382 7.08640314680382
+7.113765883549079 7.113765883549079
+7.328944131981744 7.328944131981744
+7.63625182217108 7.63625182217108
+7.716743341311718 7.716743341311718
+7.938093404092351 7.938093404092351
+8.112783377863046 8.112783377863046
+8.131485096731454 8.131485096731454
diff --git a/bottleneck/tests/data/test_100_A b/bottleneck/tests/data/test_100_A
new file mode 100644
index 0000000..e02a950
--- /dev/null
+++ b/bottleneck/tests/data/test_100_A
@@ -0,0 +1,2 @@
+0 3
+6 12
diff --git a/bottleneck/tests/data/test_100_B b/bottleneck/tests/data/test_100_B
new file mode 100644
index 0000000..f757173
--- /dev/null
+++ b/bottleneck/tests/data/test_100_B
@@ -0,0 +1,2 @@
+3 5
+5 13
diff --git a/bottleneck/tests/data/test_101_A b/bottleneck/tests/data/test_101_A
new file mode 100644
index 0000000..5fe22b1
--- /dev/null
+++ b/bottleneck/tests/data/test_101_A
@@ -0,0 +1,2 @@
+8 11
+9 11
diff --git a/bottleneck/tests/data/test_101_B b/bottleneck/tests/data/test_101_B
new file mode 100644
index 0000000..ea19ef6
--- /dev/null
+++ b/bottleneck/tests/data/test_101_B
@@ -0,0 +1,2 @@
+3 6
+5 8
diff --git a/bottleneck/tests/data/test_102_A b/bottleneck/tests/data/test_102_A
new file mode 100644
index 0000000..1cd65e9
--- /dev/null
+++ b/bottleneck/tests/data/test_102_A
@@ -0,0 +1,2 @@
+7 8
+9 16
diff --git a/bottleneck/tests/data/test_102_B b/bottleneck/tests/data/test_102_B
new file mode 100644
index 0000000..3ffa9cb
--- /dev/null
+++ b/bottleneck/tests/data/test_102_B
@@ -0,0 +1,2 @@
+1 10
+9 12
diff --git a/bottleneck/tests/data/test_103_A b/bottleneck/tests/data/test_103_A
new file mode 100644
index 0000000..d4c86c9
--- /dev/null
+++ b/bottleneck/tests/data/test_103_A
@@ -0,0 +1,2 @@
+5 7
+10 15
diff --git a/bottleneck/tests/data/test_103_B b/bottleneck/tests/data/test_103_B
new file mode 100644
index 0000000..c9a898a
--- /dev/null
+++ b/bottleneck/tests/data/test_103_B
@@ -0,0 +1,2 @@
+1 2
+1 7
diff --git a/bottleneck/tests/data/test_104_A b/bottleneck/tests/data/test_104_A
new file mode 100644
index 0000000..373ae44
--- /dev/null
+++ b/bottleneck/tests/data/test_104_A
@@ -0,0 +1,2 @@
+6 11
+3 6
diff --git a/bottleneck/tests/data/test_104_B b/bottleneck/tests/data/test_104_B
new file mode 100644
index 0000000..e382a3b
--- /dev/null
+++ b/bottleneck/tests/data/test_104_B
@@ -0,0 +1,2 @@
+3 9
+10 17
diff --git a/bottleneck/tests/data/test_105_A b/bottleneck/tests/data/test_105_A
new file mode 100644
index 0000000..21b1cc4
--- /dev/null
+++ b/bottleneck/tests/data/test_105_A
@@ -0,0 +1,2 @@
+5 14
+2 7
diff --git a/bottleneck/tests/data/test_105_B b/bottleneck/tests/data/test_105_B
new file mode 100644
index 0000000..3ab6543
--- /dev/null
+++ b/bottleneck/tests/data/test_105_B
@@ -0,0 +1,2 @@
+5 12
+3 12
diff --git a/bottleneck/tests/data/test_106_A b/bottleneck/tests/data/test_106_A
new file mode 100644
index 0000000..8d3ffb8
--- /dev/null
+++ b/bottleneck/tests/data/test_106_A
@@ -0,0 +1,2 @@
+7 11
+7 15
diff --git a/bottleneck/tests/data/test_106_B b/bottleneck/tests/data/test_106_B
new file mode 100644
index 0000000..760ada5
--- /dev/null
+++ b/bottleneck/tests/data/test_106_B
@@ -0,0 +1,2 @@
+4 12
+6 13
diff --git a/bottleneck/tests/data/test_107_A b/bottleneck/tests/data/test_107_A
new file mode 100644
index 0000000..79a621d
--- /dev/null
+++ b/bottleneck/tests/data/test_107_A
@@ -0,0 +1,2 @@
+9 19
+1 7
diff --git a/bottleneck/tests/data/test_107_B b/bottleneck/tests/data/test_107_B
new file mode 100644
index 0000000..43e4294
--- /dev/null
+++ b/bottleneck/tests/data/test_107_B
@@ -0,0 +1,2 @@
+0 1
+1 3
diff --git a/bottleneck/tests/data/test_108_A b/bottleneck/tests/data/test_108_A
new file mode 100644
index 0000000..c2035e5
--- /dev/null
+++ b/bottleneck/tests/data/test_108_A
@@ -0,0 +1,2 @@
+9 19
+7 16
diff --git a/bottleneck/tests/data/test_108_B b/bottleneck/tests/data/test_108_B
new file mode 100644
index 0000000..618c2c8
--- /dev/null
+++ b/bottleneck/tests/data/test_108_B
@@ -0,0 +1,2 @@
+5 13
+0 9
diff --git a/bottleneck/tests/data/test_109_A b/bottleneck/tests/data/test_109_A
new file mode 100644
index 0000000..d16f551
--- /dev/null
+++ b/bottleneck/tests/data/test_109_A
@@ -0,0 +1,2 @@
+8 9
+3 10
diff --git a/bottleneck/tests/data/test_109_B b/bottleneck/tests/data/test_109_B
new file mode 100644
index 0000000..02f9518
--- /dev/null
+++ b/bottleneck/tests/data/test_109_B
@@ -0,0 +1,2 @@
+4 9
+6 13
diff --git a/bottleneck/tests/data/test_110_A b/bottleneck/tests/data/test_110_A
new file mode 100644
index 0000000..f013fd8
--- /dev/null
+++ b/bottleneck/tests/data/test_110_A
@@ -0,0 +1,2 @@
+3 5
+1 10
diff --git a/bottleneck/tests/data/test_110_B b/bottleneck/tests/data/test_110_B
new file mode 100644
index 0000000..f443b07
--- /dev/null
+++ b/bottleneck/tests/data/test_110_B
@@ -0,0 +1,2 @@
+7 10
+3 5
diff --git a/bottleneck/tests/data/test_111_A b/bottleneck/tests/data/test_111_A
new file mode 100644
index 0000000..fcadd44
--- /dev/null
+++ b/bottleneck/tests/data/test_111_A
@@ -0,0 +1,2 @@
+10 19
+3 4
diff --git a/bottleneck/tests/data/test_111_B b/bottleneck/tests/data/test_111_B
new file mode 100644
index 0000000..569a5d5
--- /dev/null
+++ b/bottleneck/tests/data/test_111_B
@@ -0,0 +1,2 @@
+5 6
+10 15
diff --git a/bottleneck/tests/data/test_112_A b/bottleneck/tests/data/test_112_A
new file mode 100644
index 0000000..7d421ec
--- /dev/null
+++ b/bottleneck/tests/data/test_112_A
@@ -0,0 +1,2 @@
+1 5
+7 8
diff --git a/bottleneck/tests/data/test_112_B b/bottleneck/tests/data/test_112_B
new file mode 100644
index 0000000..ec7a9a1
--- /dev/null
+++ b/bottleneck/tests/data/test_112_B
@@ -0,0 +1,2 @@
+4 11
+9 17
diff --git a/bottleneck/tests/data/test_113_A b/bottleneck/tests/data/test_113_A
new file mode 100644
index 0000000..c3b3312
--- /dev/null
+++ b/bottleneck/tests/data/test_113_A
@@ -0,0 +1,2 @@
+5 12
+0 3
diff --git a/bottleneck/tests/data/test_113_B b/bottleneck/tests/data/test_113_B
new file mode 100644
index 0000000..ca287ff
--- /dev/null
+++ b/bottleneck/tests/data/test_113_B
@@ -0,0 +1,2 @@
+3 13
+6 11
diff --git a/bottleneck/tests/data/test_114_A b/bottleneck/tests/data/test_114_A
new file mode 100644
index 0000000..112e9d3
--- /dev/null
+++ b/bottleneck/tests/data/test_114_A
@@ -0,0 +1,2 @@
+6 15
+2 6
diff --git a/bottleneck/tests/data/test_114_B b/bottleneck/tests/data/test_114_B
new file mode 100644
index 0000000..dabf69d
--- /dev/null
+++ b/bottleneck/tests/data/test_114_B
@@ -0,0 +1,2 @@
+6 7
+1 4
diff --git a/bottleneck/tests/data/test_115_A b/bottleneck/tests/data/test_115_A
new file mode 100644
index 0000000..c467eae
--- /dev/null
+++ b/bottleneck/tests/data/test_115_A
@@ -0,0 +1,2 @@
+10 18
+0 1
diff --git a/bottleneck/tests/data/test_115_B b/bottleneck/tests/data/test_115_B
new file mode 100644
index 0000000..e14dd59
--- /dev/null
+++ b/bottleneck/tests/data/test_115_B
@@ -0,0 +1,2 @@
+2 3
+4 8
diff --git a/bottleneck/tests/data/test_116_A b/bottleneck/tests/data/test_116_A
new file mode 100644
index 0000000..1828c98
--- /dev/null
+++ b/bottleneck/tests/data/test_116_A
@@ -0,0 +1,2 @@
+8 9
+9 14
diff --git a/bottleneck/tests/data/test_116_B b/bottleneck/tests/data/test_116_B
new file mode 100644
index 0000000..f63039f
--- /dev/null
+++ b/bottleneck/tests/data/test_116_B
@@ -0,0 +1,2 @@
+5 13
+9 18
diff --git a/bottleneck/tests/data/test_117_A b/bottleneck/tests/data/test_117_A
new file mode 100644
index 0000000..280d9bc
--- /dev/null
+++ b/bottleneck/tests/data/test_117_A
@@ -0,0 +1,2 @@
+10 15
+9 14
diff --git a/bottleneck/tests/data/test_117_B b/bottleneck/tests/data/test_117_B
new file mode 100644
index 0000000..595260c
--- /dev/null
+++ b/bottleneck/tests/data/test_117_B
@@ -0,0 +1,2 @@
+9 15
+6 11
diff --git a/bottleneck/tests/data/test_118_A b/bottleneck/tests/data/test_118_A
new file mode 100644
index 0000000..2ecae80
--- /dev/null
+++ b/bottleneck/tests/data/test_118_A
@@ -0,0 +1,2 @@
+9 10
+4 11
diff --git a/bottleneck/tests/data/test_118_B b/bottleneck/tests/data/test_118_B
new file mode 100644
index 0000000..13fc15b
--- /dev/null
+++ b/bottleneck/tests/data/test_118_B
@@ -0,0 +1,2 @@
+5 14
+7 13
diff --git a/bottleneck/tests/data/test_119_A b/bottleneck/tests/data/test_119_A
new file mode 100644
index 0000000..db12f3c
--- /dev/null
+++ b/bottleneck/tests/data/test_119_A
@@ -0,0 +1,2 @@
+2 12
+2 5
diff --git a/bottleneck/tests/data/test_119_B b/bottleneck/tests/data/test_119_B
new file mode 100644
index 0000000..79ccbdd
--- /dev/null
+++ b/bottleneck/tests/data/test_119_B
@@ -0,0 +1,2 @@
+2 7
+2 3
diff --git a/bottleneck/tests/data/test_120_A b/bottleneck/tests/data/test_120_A
new file mode 100644
index 0000000..cd31ead
--- /dev/null
+++ b/bottleneck/tests/data/test_120_A
@@ -0,0 +1,3 @@
+5 13
+9 10
+3 4
diff --git a/bottleneck/tests/data/test_120_B b/bottleneck/tests/data/test_120_B
new file mode 100644
index 0000000..148cbca
--- /dev/null
+++ b/bottleneck/tests/data/test_120_B
@@ -0,0 +1,3 @@
+2 6
+5 6
+3 12
diff --git a/bottleneck/tests/data/test_121_A b/bottleneck/tests/data/test_121_A
new file mode 100644
index 0000000..864cde5
--- /dev/null
+++ b/bottleneck/tests/data/test_121_A
@@ -0,0 +1,3 @@
+10 16
+7 14
+5 8
diff --git a/bottleneck/tests/data/test_121_B b/bottleneck/tests/data/test_121_B
new file mode 100644
index 0000000..cc2c1dc
--- /dev/null
+++ b/bottleneck/tests/data/test_121_B
@@ -0,0 +1,3 @@
+9 15
+5 10
+0 3
diff --git a/bottleneck/tests/data/test_122_A b/bottleneck/tests/data/test_122_A
new file mode 100644
index 0000000..681d074
--- /dev/null
+++ b/bottleneck/tests/data/test_122_A
@@ -0,0 +1,3 @@
+5 6
+8 9
+5 11
diff --git a/bottleneck/tests/data/test_122_B b/bottleneck/tests/data/test_122_B
new file mode 100644
index 0000000..e8681e6
--- /dev/null
+++ b/bottleneck/tests/data/test_122_B
@@ -0,0 +1,3 @@
+7 8
+0 1
+6 12
diff --git a/bottleneck/tests/data/test_123_A b/bottleneck/tests/data/test_123_A
new file mode 100644
index 0000000..2c53b51
--- /dev/null
+++ b/bottleneck/tests/data/test_123_A
@@ -0,0 +1,3 @@
+5 8
+4 6
+9 10
diff --git a/bottleneck/tests/data/test_123_B b/bottleneck/tests/data/test_123_B
new file mode 100644
index 0000000..0acdfb7
--- /dev/null
+++ b/bottleneck/tests/data/test_123_B
@@ -0,0 +1,3 @@
+9 14
+5 14
+4 5
diff --git a/bottleneck/tests/data/test_124_A b/bottleneck/tests/data/test_124_A
new file mode 100644
index 0000000..f43cb9a
--- /dev/null
+++ b/bottleneck/tests/data/test_124_A
@@ -0,0 +1,3 @@
+0 1
+8 16
+4 7
diff --git a/bottleneck/tests/data/test_124_B b/bottleneck/tests/data/test_124_B
new file mode 100644
index 0000000..51dd494
--- /dev/null
+++ b/bottleneck/tests/data/test_124_B
@@ -0,0 +1,3 @@
+7 8
+0 1
+4 6
diff --git a/bottleneck/tests/data/test_125_A b/bottleneck/tests/data/test_125_A
new file mode 100644
index 0000000..e0b6720
--- /dev/null
+++ b/bottleneck/tests/data/test_125_A
@@ -0,0 +1,3 @@
+9 11
+6 13
+1 10
diff --git a/bottleneck/tests/data/test_125_B b/bottleneck/tests/data/test_125_B
new file mode 100644
index 0000000..cf4f98c
--- /dev/null
+++ b/bottleneck/tests/data/test_125_B
@@ -0,0 +1,3 @@
+7 16
+10 11
+7 16
diff --git a/bottleneck/tests/data/test_126_A b/bottleneck/tests/data/test_126_A
new file mode 100644
index 0000000..f504606
--- /dev/null
+++ b/bottleneck/tests/data/test_126_A
@@ -0,0 +1,3 @@
+4 8
+5 14
+1 6
diff --git a/bottleneck/tests/data/test_126_B b/bottleneck/tests/data/test_126_B
new file mode 100644
index 0000000..f5b5fda
--- /dev/null
+++ b/bottleneck/tests/data/test_126_B
@@ -0,0 +1,3 @@
+1 2
+8 12
+7 8
diff --git a/bottleneck/tests/data/test_127_A b/bottleneck/tests/data/test_127_A
new file mode 100644
index 0000000..20f8541
--- /dev/null
+++ b/bottleneck/tests/data/test_127_A
@@ -0,0 +1,3 @@
+7 8
+10 15
+3 4
diff --git a/bottleneck/tests/data/test_127_B b/bottleneck/tests/data/test_127_B
new file mode 100644
index 0000000..36f6cf3
--- /dev/null
+++ b/bottleneck/tests/data/test_127_B
@@ -0,0 +1,3 @@
+0 1
+8 11
+2 3
diff --git a/bottleneck/tests/data/test_128_A b/bottleneck/tests/data/test_128_A
new file mode 100644
index 0000000..9e2c50e
--- /dev/null
+++ b/bottleneck/tests/data/test_128_A
@@ -0,0 +1,3 @@
+9 17
+0 4
+0 3
diff --git a/bottleneck/tests/data/test_128_B b/bottleneck/tests/data/test_128_B
new file mode 100644
index 0000000..0fdae08
--- /dev/null
+++ b/bottleneck/tests/data/test_128_B
@@ -0,0 +1,3 @@
+10 18
+7 10
+1 2
diff --git a/bottleneck/tests/data/test_129_A b/bottleneck/tests/data/test_129_A
new file mode 100644
index 0000000..dc289de
--- /dev/null
+++ b/bottleneck/tests/data/test_129_A
@@ -0,0 +1,3 @@
+8 17
+5 10
+9 16
diff --git a/bottleneck/tests/data/test_129_B b/bottleneck/tests/data/test_129_B
new file mode 100644
index 0000000..3216111
--- /dev/null
+++ b/bottleneck/tests/data/test_129_B
@@ -0,0 +1,3 @@
+10 19
+8 17
+2 11
diff --git a/bottleneck/tests/data/test_130_A b/bottleneck/tests/data/test_130_A
new file mode 100644
index 0000000..db70054
--- /dev/null
+++ b/bottleneck/tests/data/test_130_A
@@ -0,0 +1,3 @@
+10 11
+10 19
+4 6
diff --git a/bottleneck/tests/data/test_130_B b/bottleneck/tests/data/test_130_B
new file mode 100644
index 0000000..80c5a30
--- /dev/null
+++ b/bottleneck/tests/data/test_130_B
@@ -0,0 +1,3 @@
+4 14
+0 8
+3 9
diff --git a/bottleneck/tests/data/test_131_A b/bottleneck/tests/data/test_131_A
new file mode 100644
index 0000000..720cdb3
--- /dev/null
+++ b/bottleneck/tests/data/test_131_A
@@ -0,0 +1,3 @@
+9 15
+3 4
+2 5
diff --git a/bottleneck/tests/data/test_131_B b/bottleneck/tests/data/test_131_B
new file mode 100644
index 0000000..55bb437
--- /dev/null
+++ b/bottleneck/tests/data/test_131_B
@@ -0,0 +1,3 @@
+10 20
+10 15
+7 10
diff --git a/bottleneck/tests/data/test_132_A b/bottleneck/tests/data/test_132_A
new file mode 100644
index 0000000..dec8f13
--- /dev/null
+++ b/bottleneck/tests/data/test_132_A
@@ -0,0 +1,3 @@
+6 16
+2 4
+10 11
diff --git a/bottleneck/tests/data/test_132_B b/bottleneck/tests/data/test_132_B
new file mode 100644
index 0000000..8844484
--- /dev/null
+++ b/bottleneck/tests/data/test_132_B
@@ -0,0 +1,3 @@
+6 8
+5 14
+3 4
diff --git a/bottleneck/tests/data/test_133_A b/bottleneck/tests/data/test_133_A
new file mode 100644
index 0000000..b46cb4f
--- /dev/null
+++ b/bottleneck/tests/data/test_133_A
@@ -0,0 +1,3 @@
+4 10
+9 15
+1 7
diff --git a/bottleneck/tests/data/test_133_B b/bottleneck/tests/data/test_133_B
new file mode 100644
index 0000000..7a5d26a
--- /dev/null
+++ b/bottleneck/tests/data/test_133_B
@@ -0,0 +1,3 @@
+4 5
+3 6
+1 10
diff --git a/bottleneck/tests/data/test_134_A b/bottleneck/tests/data/test_134_A
new file mode 100644
index 0000000..4abd1e5
--- /dev/null
+++ b/bottleneck/tests/data/test_134_A
@@ -0,0 +1,3 @@
+1 4
+6 13
+10 15
diff --git a/bottleneck/tests/data/test_134_B b/bottleneck/tests/data/test_134_B
new file mode 100644
index 0000000..aed169c
--- /dev/null
+++ b/bottleneck/tests/data/test_134_B
@@ -0,0 +1,3 @@
+8 17
+8 16
+7 12
diff --git a/bottleneck/tests/data/test_135_A b/bottleneck/tests/data/test_135_A
new file mode 100644
index 0000000..bbe9e95
--- /dev/null
+++ b/bottleneck/tests/data/test_135_A
@@ -0,0 +1,3 @@
+7 15
+1 4
+2 6
diff --git a/bottleneck/tests/data/test_135_B b/bottleneck/tests/data/test_135_B
new file mode 100644
index 0000000..3c84c03
--- /dev/null
+++ b/bottleneck/tests/data/test_135_B
@@ -0,0 +1,3 @@
+6 10
+2 8
+1 7
diff --git a/bottleneck/tests/data/test_136_A b/bottleneck/tests/data/test_136_A
new file mode 100644
index 0000000..a68856e
--- /dev/null
+++ b/bottleneck/tests/data/test_136_A
@@ -0,0 +1,3 @@
+0 1
+9 14
+7 11
diff --git a/bottleneck/tests/data/test_136_B b/bottleneck/tests/data/test_136_B
new file mode 100644
index 0000000..c03df54
--- /dev/null
+++ b/bottleneck/tests/data/test_136_B
@@ -0,0 +1,3 @@
+4 6
+3 4
+8 12
diff --git a/bottleneck/tests/data/test_137_A b/bottleneck/tests/data/test_137_A
new file mode 100644
index 0000000..179d357
--- /dev/null
+++ b/bottleneck/tests/data/test_137_A
@@ -0,0 +1,3 @@
+5 6
+7 14
+5 9
diff --git a/bottleneck/tests/data/test_137_B b/bottleneck/tests/data/test_137_B
new file mode 100644
index 0000000..42541ae
--- /dev/null
+++ b/bottleneck/tests/data/test_137_B
@@ -0,0 +1,3 @@
+10 16
+1 3
+6 7
diff --git a/bottleneck/tests/data/test_138_A b/bottleneck/tests/data/test_138_A
new file mode 100644
index 0000000..9c39dfb
--- /dev/null
+++ b/bottleneck/tests/data/test_138_A
@@ -0,0 +1,3 @@
+0 4
+9 14
+10 20
diff --git a/bottleneck/tests/data/test_138_B b/bottleneck/tests/data/test_138_B
new file mode 100644
index 0000000..826d759
--- /dev/null
+++ b/bottleneck/tests/data/test_138_B
@@ -0,0 +1,3 @@
+8 13
+7 8
+10 18
diff --git a/bottleneck/tests/data/test_139_A b/bottleneck/tests/data/test_139_A
new file mode 100644
index 0000000..7f74c9f
--- /dev/null
+++ b/bottleneck/tests/data/test_139_A
@@ -0,0 +1,3 @@
+6 7
+9 14
+4 5
diff --git a/bottleneck/tests/data/test_139_B b/bottleneck/tests/data/test_139_B
new file mode 100644
index 0000000..ba4ab64
--- /dev/null
+++ b/bottleneck/tests/data/test_139_B
@@ -0,0 +1,3 @@
+9 11
+7 11
+9 10
diff --git a/bottleneck/tests/data/test_140_A b/bottleneck/tests/data/test_140_A
new file mode 100644
index 0000000..fec44cc
--- /dev/null
+++ b/bottleneck/tests/data/test_140_A
@@ -0,0 +1,4 @@
+9 11
+6 7
+4 12
+1 8
diff --git a/bottleneck/tests/data/test_140_B b/bottleneck/tests/data/test_140_B
new file mode 100644
index 0000000..af8aa1c
--- /dev/null
+++ b/bottleneck/tests/data/test_140_B
@@ -0,0 +1,4 @@
+9 10
+1 2
+2 10
+2 8
diff --git a/bottleneck/tests/data/test_141_A b/bottleneck/tests/data/test_141_A
new file mode 100644
index 0000000..db65086
--- /dev/null
+++ b/bottleneck/tests/data/test_141_A
@@ -0,0 +1,4 @@
+7 13
+2 12
+5 13
+6 8
diff --git a/bottleneck/tests/data/test_141_B b/bottleneck/tests/data/test_141_B
new file mode 100644
index 0000000..022c192
--- /dev/null
+++ b/bottleneck/tests/data/test_141_B
@@ -0,0 +1,4 @@
+5 10
+9 12
+10 18
+8 11
diff --git a/bottleneck/tests/data/test_142_A b/bottleneck/tests/data/test_142_A
new file mode 100644
index 0000000..10bbe2d
--- /dev/null
+++ b/bottleneck/tests/data/test_142_A
@@ -0,0 +1,4 @@
+6 15
+4 5
+6 9
+8 17
diff --git a/bottleneck/tests/data/test_142_B b/bottleneck/tests/data/test_142_B
new file mode 100644
index 0000000..82b6b28
--- /dev/null
+++ b/bottleneck/tests/data/test_142_B
@@ -0,0 +1,4 @@
+8 12
+8 11
+3 5
+8 17
diff --git a/bottleneck/tests/data/test_143_A b/bottleneck/tests/data/test_143_A
new file mode 100644
index 0000000..1db8047
--- /dev/null
+++ b/bottleneck/tests/data/test_143_A
@@ -0,0 +1,4 @@
+5 6
+0 2
+5 10
+6 10
diff --git a/bottleneck/tests/data/test_143_B b/bottleneck/tests/data/test_143_B
new file mode 100644
index 0000000..5c5a6a7
--- /dev/null
+++ b/bottleneck/tests/data/test_143_B
@@ -0,0 +1,4 @@
+8 14
+5 7
+1 11
+4 10
diff --git a/bottleneck/tests/data/test_144_A b/bottleneck/tests/data/test_144_A
new file mode 100644
index 0000000..594f4c4
--- /dev/null
+++ b/bottleneck/tests/data/test_144_A
@@ -0,0 +1,4 @@
+10 15
+6 13
+1 2
+1 6
diff --git a/bottleneck/tests/data/test_144_B b/bottleneck/tests/data/test_144_B
new file mode 100644
index 0000000..aa3cd6d
--- /dev/null
+++ b/bottleneck/tests/data/test_144_B
@@ -0,0 +1,4 @@
+0 8
+10 13
+9 18
+8 11
diff --git a/bottleneck/tests/data/test_145_A b/bottleneck/tests/data/test_145_A
new file mode 100644
index 0000000..41ea529
--- /dev/null
+++ b/bottleneck/tests/data/test_145_A
@@ -0,0 +1,4 @@
+2 10
+3 11
+10 17
+3 8
diff --git a/bottleneck/tests/data/test_145_B b/bottleneck/tests/data/test_145_B
new file mode 100644
index 0000000..5bcbaf0
--- /dev/null
+++ b/bottleneck/tests/data/test_145_B
@@ -0,0 +1,4 @@
+6 13
+10 15
+7 15
+6 10
diff --git a/bottleneck/tests/data/test_146_A b/bottleneck/tests/data/test_146_A
new file mode 100644
index 0000000..18c1b4a
--- /dev/null
+++ b/bottleneck/tests/data/test_146_A
@@ -0,0 +1,4 @@
+3 5
+6 11
+1 8
+2 5
diff --git a/bottleneck/tests/data/test_146_B b/bottleneck/tests/data/test_146_B
new file mode 100644
index 0000000..24e5821
--- /dev/null
+++ b/bottleneck/tests/data/test_146_B
@@ -0,0 +1,4 @@
+5 12
+4 10
+5 11
+2 7
diff --git a/bottleneck/tests/data/test_147_A b/bottleneck/tests/data/test_147_A
new file mode 100644
index 0000000..bce747d
--- /dev/null
+++ b/bottleneck/tests/data/test_147_A
@@ -0,0 +1,4 @@
+9 11
+1 2
+10 12
+10 15
diff --git a/bottleneck/tests/data/test_147_B b/bottleneck/tests/data/test_147_B
new file mode 100644
index 0000000..c545851
--- /dev/null
+++ b/bottleneck/tests/data/test_147_B
@@ -0,0 +1,4 @@
+4 6
+7 14
+4 12
+7 10
diff --git a/bottleneck/tests/data/test_148_A b/bottleneck/tests/data/test_148_A
new file mode 100644
index 0000000..cd7482f
--- /dev/null
+++ b/bottleneck/tests/data/test_148_A
@@ -0,0 +1,4 @@
+5 9
+0 7
+7 11
+7 13
diff --git a/bottleneck/tests/data/test_148_B b/bottleneck/tests/data/test_148_B
new file mode 100644
index 0000000..a761bd3
--- /dev/null
+++ b/bottleneck/tests/data/test_148_B
@@ -0,0 +1,4 @@
+7 9
+2 8
+1 2
+4 11
diff --git a/bottleneck/tests/data/test_149_A b/bottleneck/tests/data/test_149_A
new file mode 100644
index 0000000..81fff07
--- /dev/null
+++ b/bottleneck/tests/data/test_149_A
@@ -0,0 +1,4 @@
+2 4
+1 9
+7 13
+4 14
diff --git a/bottleneck/tests/data/test_149_B b/bottleneck/tests/data/test_149_B
new file mode 100644
index 0000000..1acd048
--- /dev/null
+++ b/bottleneck/tests/data/test_149_B
@@ -0,0 +1,4 @@
+9 12
+0 6
+4 10
+0 4
diff --git a/bottleneck/tests/data/test_150_A b/bottleneck/tests/data/test_150_A
new file mode 100644
index 0000000..8f4862d
--- /dev/null
+++ b/bottleneck/tests/data/test_150_A
@@ -0,0 +1,4 @@
+9 11
+7 16
+0 1
+0 3
diff --git a/bottleneck/tests/data/test_150_B b/bottleneck/tests/data/test_150_B
new file mode 100644
index 0000000..d55101f
--- /dev/null
+++ b/bottleneck/tests/data/test_150_B
@@ -0,0 +1,4 @@
+7 14
+4 5
+7 16
+8 14
diff --git a/bottleneck/tests/data/test_151_A b/bottleneck/tests/data/test_151_A
new file mode 100644
index 0000000..1915b6a
--- /dev/null
+++ b/bottleneck/tests/data/test_151_A
@@ -0,0 +1,4 @@
+3 13
+10 11
+7 14
+2 11
diff --git a/bottleneck/tests/data/test_151_B b/bottleneck/tests/data/test_151_B
new file mode 100644
index 0000000..065a2c7
--- /dev/null
+++ b/bottleneck/tests/data/test_151_B
@@ -0,0 +1,4 @@
+6 9
+10 15
+7 8
+7 12
diff --git a/bottleneck/tests/data/test_152_A b/bottleneck/tests/data/test_152_A
new file mode 100644
index 0000000..43ed98e
--- /dev/null
+++ b/bottleneck/tests/data/test_152_A
@@ -0,0 +1,4 @@
+10 11
+2 5
+2 5
+0 3
diff --git a/bottleneck/tests/data/test_152_B b/bottleneck/tests/data/test_152_B
new file mode 100644
index 0000000..5e179b7
--- /dev/null
+++ b/bottleneck/tests/data/test_152_B
@@ -0,0 +1,4 @@
+4 8
+5 12
+6 8
+3 5
diff --git a/bottleneck/tests/data/test_153_A b/bottleneck/tests/data/test_153_A
new file mode 100644
index 0000000..16f5a34
--- /dev/null
+++ b/bottleneck/tests/data/test_153_A
@@ -0,0 +1,4 @@
+0 9
+10 11
+10 16
+1 9
diff --git a/bottleneck/tests/data/test_153_B b/bottleneck/tests/data/test_153_B
new file mode 100644
index 0000000..a82ae69
--- /dev/null
+++ b/bottleneck/tests/data/test_153_B
@@ -0,0 +1,4 @@
+0 3
+3 10
+6 14
+4 7
diff --git a/bottleneck/tests/data/test_154_A b/bottleneck/tests/data/test_154_A
new file mode 100644
index 0000000..73246c1
--- /dev/null
+++ b/bottleneck/tests/data/test_154_A
@@ -0,0 +1,4 @@
+2 5
+5 15
+2 5
+3 7
diff --git a/bottleneck/tests/data/test_154_B b/bottleneck/tests/data/test_154_B
new file mode 100644
index 0000000..6650b45
--- /dev/null
+++ b/bottleneck/tests/data/test_154_B
@@ -0,0 +1,4 @@
+3 4
+9 16
+5 12
+1 6
diff --git a/bottleneck/tests/data/test_155_A b/bottleneck/tests/data/test_155_A
new file mode 100644
index 0000000..9ce2859
--- /dev/null
+++ b/bottleneck/tests/data/test_155_A
@@ -0,0 +1,4 @@
+10 14
+7 10
+9 10
+4 12
diff --git a/bottleneck/tests/data/test_155_B b/bottleneck/tests/data/test_155_B
new file mode 100644
index 0000000..c852368
--- /dev/null
+++ b/bottleneck/tests/data/test_155_B
@@ -0,0 +1,4 @@
+6 10
+2 8
+4 8
+1 11
diff --git a/bottleneck/tests/data/test_156_A b/bottleneck/tests/data/test_156_A
new file mode 100644
index 0000000..e79fcd1
--- /dev/null
+++ b/bottleneck/tests/data/test_156_A
@@ -0,0 +1,4 @@
+2 4
+6 12
+1 9
+4 14
diff --git a/bottleneck/tests/data/test_156_B b/bottleneck/tests/data/test_156_B
new file mode 100644
index 0000000..05cd916
--- /dev/null
+++ b/bottleneck/tests/data/test_156_B
@@ -0,0 +1,4 @@
+2 12
+7 12
+7 11
+2 4
diff --git a/bottleneck/tests/data/test_157_A b/bottleneck/tests/data/test_157_A
new file mode 100644
index 0000000..257f007
--- /dev/null
+++ b/bottleneck/tests/data/test_157_A
@@ -0,0 +1,4 @@
+8 17
+7 9
+10 16
+1 9
diff --git a/bottleneck/tests/data/test_157_B b/bottleneck/tests/data/test_157_B
new file mode 100644
index 0000000..da76a0c
--- /dev/null
+++ b/bottleneck/tests/data/test_157_B
@@ -0,0 +1,4 @@
+9 11
+3 6
+0 3
+2 3
diff --git a/bottleneck/tests/data/test_158_A b/bottleneck/tests/data/test_158_A
new file mode 100644
index 0000000..ec64dab
--- /dev/null
+++ b/bottleneck/tests/data/test_158_A
@@ -0,0 +1,4 @@
+2 4
+9 15
+8 16
+8 11
diff --git a/bottleneck/tests/data/test_158_B b/bottleneck/tests/data/test_158_B
new file mode 100644
index 0000000..407c843
--- /dev/null
+++ b/bottleneck/tests/data/test_158_B
@@ -0,0 +1,4 @@
+10 17
+10 15
+1 8
+10 17
diff --git a/bottleneck/tests/data/test_159_A b/bottleneck/tests/data/test_159_A
new file mode 100644
index 0000000..bbf8d13
--- /dev/null
+++ b/bottleneck/tests/data/test_159_A
@@ -0,0 +1,4 @@
+9 13
+5 6
+3 6
+5 7
diff --git a/bottleneck/tests/data/test_159_B b/bottleneck/tests/data/test_159_B
new file mode 100644
index 0000000..fbe6d45
--- /dev/null
+++ b/bottleneck/tests/data/test_159_B
@@ -0,0 +1,4 @@
+2 5
+4 5
+9 14
+10 11
diff --git a/bottleneck/tests/data/test_160_A b/bottleneck/tests/data/test_160_A
new file mode 100644
index 0000000..c712c5a
--- /dev/null
+++ b/bottleneck/tests/data/test_160_A
@@ -0,0 +1,5 @@
+3 10
+1 10
+5 15
+0 9
+8 9
diff --git a/bottleneck/tests/data/test_160_B b/bottleneck/tests/data/test_160_B
new file mode 100644
index 0000000..90edf6f
--- /dev/null
+++ b/bottleneck/tests/data/test_160_B
@@ -0,0 +1,5 @@
+3 11
+0 8
+0 3
+4 7
+1 11
diff --git a/bottleneck/tests/data/test_161_A b/bottleneck/tests/data/test_161_A
new file mode 100644
index 0000000..4cbae18
--- /dev/null
+++ b/bottleneck/tests/data/test_161_A
@@ -0,0 +1,5 @@
+9 11
+8 10
+3 6
+4 14
+5 10
diff --git a/bottleneck/tests/data/test_161_B b/bottleneck/tests/data/test_161_B
new file mode 100644
index 0000000..e166afb
--- /dev/null
+++ b/bottleneck/tests/data/test_161_B
@@ -0,0 +1,5 @@
+0 3
+8 14
+8 13
+0 2
+1 2
diff --git a/bottleneck/tests/data/test_162_A b/bottleneck/tests/data/test_162_A
new file mode 100644
index 0000000..e16e9a3
--- /dev/null
+++ b/bottleneck/tests/data/test_162_A
@@ -0,0 +1,5 @@
+4 5
+7 17
+4 8
+10 16
+4 7
diff --git a/bottleneck/tests/data/test_162_B b/bottleneck/tests/data/test_162_B
new file mode 100644
index 0000000..78ab6a3
--- /dev/null
+++ b/bottleneck/tests/data/test_162_B
@@ -0,0 +1,5 @@
+6 14
+9 10
+1 9
+7 17
+7 8
diff --git a/bottleneck/tests/data/test_163_A b/bottleneck/tests/data/test_163_A
new file mode 100644
index 0000000..6836e59
--- /dev/null
+++ b/bottleneck/tests/data/test_163_A
@@ -0,0 +1,5 @@
+6 12
+6 11
+7 15
+9 11
+1 6
diff --git a/bottleneck/tests/data/test_163_B b/bottleneck/tests/data/test_163_B
new file mode 100644
index 0000000..9d9e6e2
--- /dev/null
+++ b/bottleneck/tests/data/test_163_B
@@ -0,0 +1,5 @@
+0 6
+1 11
+2 3
+7 14
+7 10
diff --git a/bottleneck/tests/data/test_164_A b/bottleneck/tests/data/test_164_A
new file mode 100644
index 0000000..a4187bd
--- /dev/null
+++ b/bottleneck/tests/data/test_164_A
@@ -0,0 +1,5 @@
+0 2
+6 14
+7 16
+9 10
+2 6
diff --git a/bottleneck/tests/data/test_164_B b/bottleneck/tests/data/test_164_B
new file mode 100644
index 0000000..8597409
--- /dev/null
+++ b/bottleneck/tests/data/test_164_B
@@ -0,0 +1,5 @@
+2 10
+5 13
+4 13
+4 6
+8 16
diff --git a/bottleneck/tests/data/test_165_A b/bottleneck/tests/data/test_165_A
new file mode 100644
index 0000000..15b9f15
--- /dev/null
+++ b/bottleneck/tests/data/test_165_A
@@ -0,0 +1,5 @@
+1 9
+6 15
+6 7
+10 18
+6 7
diff --git a/bottleneck/tests/data/test_165_B b/bottleneck/tests/data/test_165_B
new file mode 100644
index 0000000..8056eab
--- /dev/null
+++ b/bottleneck/tests/data/test_165_B
@@ -0,0 +1,5 @@
+8 15
+3 13
+8 17
+1 9
+9 18
diff --git a/bottleneck/tests/data/test_166_A b/bottleneck/tests/data/test_166_A
new file mode 100644
index 0000000..8257649
--- /dev/null
+++ b/bottleneck/tests/data/test_166_A
@@ -0,0 +1,5 @@
+2 10
+4 12
+0 4
+10 18
+3 11
diff --git a/bottleneck/tests/data/test_166_B b/bottleneck/tests/data/test_166_B
new file mode 100644
index 0000000..02499eb
--- /dev/null
+++ b/bottleneck/tests/data/test_166_B
@@ -0,0 +1,5 @@
+0 6
+6 16
+3 11
+10 19
+5 15
diff --git a/bottleneck/tests/data/test_167_A b/bottleneck/tests/data/test_167_A
new file mode 100644
index 0000000..416f645
--- /dev/null
+++ b/bottleneck/tests/data/test_167_A
@@ -0,0 +1,5 @@
+4 7
+0 5
+1 9
+7 8
+4 10
diff --git a/bottleneck/tests/data/test_167_B b/bottleneck/tests/data/test_167_B
new file mode 100644
index 0000000..2ab78e5
--- /dev/null
+++ b/bottleneck/tests/data/test_167_B
@@ -0,0 +1,5 @@
+3 13
+3 13
+4 12
+4 13
+3 10
diff --git a/bottleneck/tests/data/test_168_A b/bottleneck/tests/data/test_168_A
new file mode 100644
index 0000000..57f9e66
--- /dev/null
+++ b/bottleneck/tests/data/test_168_A
@@ -0,0 +1,5 @@
+9 10
+3 8
+7 17
+10 11
+5 7
diff --git a/bottleneck/tests/data/test_168_B b/bottleneck/tests/data/test_168_B
new file mode 100644
index 0000000..6d5d9c5
--- /dev/null
+++ b/bottleneck/tests/data/test_168_B
@@ -0,0 +1,5 @@
+10 18
+1 9
+4 9
+4 14
+8 14
diff --git a/bottleneck/tests/data/test_169_A b/bottleneck/tests/data/test_169_A
new file mode 100644
index 0000000..7db2396
--- /dev/null
+++ b/bottleneck/tests/data/test_169_A
@@ -0,0 +1,5 @@
+9 12
+10 14
+10 17
+5 6
+4 5
diff --git a/bottleneck/tests/data/test_169_B b/bottleneck/tests/data/test_169_B
new file mode 100644
index 0000000..58d7cec
--- /dev/null
+++ b/bottleneck/tests/data/test_169_B
@@ -0,0 +1,5 @@
+0 2
+9 10
+4 11
+10 13
+2 5
diff --git a/bottleneck/tests/data/test_170_A b/bottleneck/tests/data/test_170_A
new file mode 100644
index 0000000..7d30592
--- /dev/null
+++ b/bottleneck/tests/data/test_170_A
@@ -0,0 +1,5 @@
+5 11
+8 14
+6 13
+1 11
+6 15
diff --git a/bottleneck/tests/data/test_170_B b/bottleneck/tests/data/test_170_B
new file mode 100644
index 0000000..86d8ccc
--- /dev/null
+++ b/bottleneck/tests/data/test_170_B
@@ -0,0 +1,5 @@
+1 3
+1 3
+4 7
+7 15
+5 13
diff --git a/bottleneck/tests/data/test_171_A b/bottleneck/tests/data/test_171_A
new file mode 100644
index 0000000..30ce17c
--- /dev/null
+++ b/bottleneck/tests/data/test_171_A
@@ -0,0 +1,5 @@
+0 7
+3 5
+4 14
+8 14
+3 12
diff --git a/bottleneck/tests/data/test_171_B b/bottleneck/tests/data/test_171_B
new file mode 100644
index 0000000..487dcb5
--- /dev/null
+++ b/bottleneck/tests/data/test_171_B
@@ -0,0 +1,5 @@
+7 13
+3 7
+0 5
+4 14
+5 12
diff --git a/bottleneck/tests/data/test_172_A b/bottleneck/tests/data/test_172_A
new file mode 100644
index 0000000..69232cf
--- /dev/null
+++ b/bottleneck/tests/data/test_172_A
@@ -0,0 +1,5 @@
+3 4
+7 10
+8 14
+9 11
+2 12
diff --git a/bottleneck/tests/data/test_172_B b/bottleneck/tests/data/test_172_B
new file mode 100644
index 0000000..1ab31ab
--- /dev/null
+++ b/bottleneck/tests/data/test_172_B
@@ -0,0 +1,5 @@
+7 9
+8 10
+9 13
+3 9
+3 7
diff --git a/bottleneck/tests/data/test_173_A b/bottleneck/tests/data/test_173_A
new file mode 100644
index 0000000..d88d368
--- /dev/null
+++ b/bottleneck/tests/data/test_173_A
@@ -0,0 +1,5 @@
+5 8
+7 9
+7 11
+1 9
+5 6
diff --git a/bottleneck/tests/data/test_173_B b/bottleneck/tests/data/test_173_B
new file mode 100644
index 0000000..a331c9c
--- /dev/null
+++ b/bottleneck/tests/data/test_173_B
@@ -0,0 +1,5 @@
+1 5
+6 9
+2 5
+1 4
+6 10
diff --git a/bottleneck/tests/data/test_174_A b/bottleneck/tests/data/test_174_A
new file mode 100644
index 0000000..a97b65b
--- /dev/null
+++ b/bottleneck/tests/data/test_174_A
@@ -0,0 +1,5 @@
+4 14
+2 7
+9 19
+6 9
+0 2
diff --git a/bottleneck/tests/data/test_174_B b/bottleneck/tests/data/test_174_B
new file mode 100644
index 0000000..98da402
--- /dev/null
+++ b/bottleneck/tests/data/test_174_B
@@ -0,0 +1,5 @@
+4 11
+10 17
+7 8
+0 8
+3 9
diff --git a/bottleneck/tests/data/test_175_A b/bottleneck/tests/data/test_175_A
new file mode 100644
index 0000000..dc8bedd
--- /dev/null
+++ b/bottleneck/tests/data/test_175_A
@@ -0,0 +1,5 @@
+8 11
+5 11
+7 13
+8 14
+4 12
diff --git a/bottleneck/tests/data/test_175_B b/bottleneck/tests/data/test_175_B
new file mode 100644
index 0000000..b5bd41f
--- /dev/null
+++ b/bottleneck/tests/data/test_175_B
@@ -0,0 +1,5 @@
+4 12
+10 20
+10 20
+3 13
+9 16
diff --git a/bottleneck/tests/data/test_176_A b/bottleneck/tests/data/test_176_A
new file mode 100644
index 0000000..dff782a
--- /dev/null
+++ b/bottleneck/tests/data/test_176_A
@@ -0,0 +1,5 @@
+10 13
+9 10
+8 15
+5 9
+5 13
diff --git a/bottleneck/tests/data/test_176_B b/bottleneck/tests/data/test_176_B
new file mode 100644
index 0000000..8724366
--- /dev/null
+++ b/bottleneck/tests/data/test_176_B
@@ -0,0 +1,5 @@
+2 8
+6 7
+0 9
+5 11
+4 12
diff --git a/bottleneck/tests/data/test_177_A b/bottleneck/tests/data/test_177_A
new file mode 100644
index 0000000..556caf8
--- /dev/null
+++ b/bottleneck/tests/data/test_177_A
@@ -0,0 +1,5 @@
+4 7
+2 3
+6 7
+2 4
+0 7
diff --git a/bottleneck/tests/data/test_177_B b/bottleneck/tests/data/test_177_B
new file mode 100644
index 0000000..91583a5
--- /dev/null
+++ b/bottleneck/tests/data/test_177_B
@@ -0,0 +1,5 @@
+8 17
+10 13
+4 6
+3 8
+0 5
diff --git a/bottleneck/tests/data/test_178_A b/bottleneck/tests/data/test_178_A
new file mode 100644
index 0000000..e223edb
--- /dev/null
+++ b/bottleneck/tests/data/test_178_A
@@ -0,0 +1,5 @@
+2 3
+9 15
+8 10
+7 15
+5 11
diff --git a/bottleneck/tests/data/test_178_B b/bottleneck/tests/data/test_178_B
new file mode 100644
index 0000000..2ab0b73
--- /dev/null
+++ b/bottleneck/tests/data/test_178_B
@@ -0,0 +1,5 @@
+10 17
+2 9
+0 9
+8 12
+4 14
diff --git a/bottleneck/tests/data/test_179_A b/bottleneck/tests/data/test_179_A
new file mode 100644
index 0000000..7b11730
--- /dev/null
+++ b/bottleneck/tests/data/test_179_A
@@ -0,0 +1,5 @@
+3 13
+5 14
+7 14
+3 11
+10 15
diff --git a/bottleneck/tests/data/test_179_B b/bottleneck/tests/data/test_179_B
new file mode 100644
index 0000000..e160b9f
--- /dev/null
+++ b/bottleneck/tests/data/test_179_B
@@ -0,0 +1,5 @@
+2 9
+2 10
+1 4
+3 6
+0 7
diff --git a/bottleneck/tests/data/test_180_A b/bottleneck/tests/data/test_180_A
new file mode 100644
index 0000000..a830fb1
--- /dev/null
+++ b/bottleneck/tests/data/test_180_A
@@ -0,0 +1,6 @@
+9 19
+6 7
+9 17
+0 3
+7 8
+8 14
diff --git a/bottleneck/tests/data/test_180_B b/bottleneck/tests/data/test_180_B
new file mode 100644
index 0000000..0ed2108
--- /dev/null
+++ b/bottleneck/tests/data/test_180_B
@@ -0,0 +1,6 @@
+0 10
+1 11
+10 12
+5 6
+10 16
+5 14
diff --git a/bottleneck/tests/data/test_181_A b/bottleneck/tests/data/test_181_A
new file mode 100644
index 0000000..e29de9c
--- /dev/null
+++ b/bottleneck/tests/data/test_181_A
@@ -0,0 +1,6 @@
+1 4
+1 2
+9 19
+3 6
+8 11
+4 8
diff --git a/bottleneck/tests/data/test_181_B b/bottleneck/tests/data/test_181_B
new file mode 100644
index 0000000..dacaa51
--- /dev/null
+++ b/bottleneck/tests/data/test_181_B
@@ -0,0 +1,6 @@
+6 11
+8 15
+8 12
+10 11
+4 7
+5 10
diff --git a/bottleneck/tests/data/test_182_A b/bottleneck/tests/data/test_182_A
new file mode 100644
index 0000000..e545af0
--- /dev/null
+++ b/bottleneck/tests/data/test_182_A
@@ -0,0 +1,6 @@
+8 10
+2 6
+6 14
+5 6
+6 7
+0 2
diff --git a/bottleneck/tests/data/test_182_B b/bottleneck/tests/data/test_182_B
new file mode 100644
index 0000000..ffee041
--- /dev/null
+++ b/bottleneck/tests/data/test_182_B
@@ -0,0 +1,6 @@
+8 11
+6 8
+0 5
+7 13
+6 9
+10 19
diff --git a/bottleneck/tests/data/test_183_A b/bottleneck/tests/data/test_183_A
new file mode 100644
index 0000000..0681b8d
--- /dev/null
+++ b/bottleneck/tests/data/test_183_A
@@ -0,0 +1,6 @@
+8 13
+5 7
+1 5
+5 11
+3 7
+0 3
diff --git a/bottleneck/tests/data/test_183_B b/bottleneck/tests/data/test_183_B
new file mode 100644
index 0000000..da3af74
--- /dev/null
+++ b/bottleneck/tests/data/test_183_B
@@ -0,0 +1,6 @@
+10 20
+6 11
+9 10
+1 4
+0 8
+7 14
diff --git a/bottleneck/tests/data/test_184_A b/bottleneck/tests/data/test_184_A
new file mode 100644
index 0000000..a252760
--- /dev/null
+++ b/bottleneck/tests/data/test_184_A
@@ -0,0 +1,6 @@
+3 7
+1 10
+2 5
+0 5
+1 4
+2 3
diff --git a/bottleneck/tests/data/test_184_B b/bottleneck/tests/data/test_184_B
new file mode 100644
index 0000000..788be62
--- /dev/null
+++ b/bottleneck/tests/data/test_184_B
@@ -0,0 +1,6 @@
+8 14
+10 11
+3 5
+5 9
+6 8
+9 10
diff --git a/bottleneck/tests/data/test_185_A b/bottleneck/tests/data/test_185_A
new file mode 100644
index 0000000..8922d7a
--- /dev/null
+++ b/bottleneck/tests/data/test_185_A
@@ -0,0 +1,6 @@
+4 10
+8 10
+5 9
+9 13
+9 18
+8 14
diff --git a/bottleneck/tests/data/test_185_B b/bottleneck/tests/data/test_185_B
new file mode 100644
index 0000000..fc90091
--- /dev/null
+++ b/bottleneck/tests/data/test_185_B
@@ -0,0 +1,6 @@
+0 10
+4 5
+3 10
+1 11
+4 9
+4 14
diff --git a/bottleneck/tests/data/test_186_A b/bottleneck/tests/data/test_186_A
new file mode 100644
index 0000000..894dc49
--- /dev/null
+++ b/bottleneck/tests/data/test_186_A
@@ -0,0 +1,6 @@
+1 8
+10 11
+3 10
+8 9
+3 13
+9 13
diff --git a/bottleneck/tests/data/test_186_B b/bottleneck/tests/data/test_186_B
new file mode 100644
index 0000000..c0b49c0
--- /dev/null
+++ b/bottleneck/tests/data/test_186_B
@@ -0,0 +1,6 @@
+6 15
+8 9
+4 7
+0 10
+1 9
+1 2
diff --git a/bottleneck/tests/data/test_187_A b/bottleneck/tests/data/test_187_A
new file mode 100644
index 0000000..f2181af
--- /dev/null
+++ b/bottleneck/tests/data/test_187_A
@@ -0,0 +1,6 @@
+9 11
+8 11
+10 11
+3 8
+7 17
+3 5
diff --git a/bottleneck/tests/data/test_187_B b/bottleneck/tests/data/test_187_B
new file mode 100644
index 0000000..ab13d0f
--- /dev/null
+++ b/bottleneck/tests/data/test_187_B
@@ -0,0 +1,6 @@
+6 10
+10 19
+5 11
+6 13
+10 16
+10 20
diff --git a/bottleneck/tests/data/test_188_A b/bottleneck/tests/data/test_188_A
new file mode 100644
index 0000000..8290582
--- /dev/null
+++ b/bottleneck/tests/data/test_188_A
@@ -0,0 +1,6 @@
+4 9
+10 20
+0 4
+5 6
+8 9
+5 6
diff --git a/bottleneck/tests/data/test_188_B b/bottleneck/tests/data/test_188_B
new file mode 100644
index 0000000..6acfc2e
--- /dev/null
+++ b/bottleneck/tests/data/test_188_B
@@ -0,0 +1,6 @@
+9 19
+6 11
+0 2
+5 12
+3 11
+7 11
diff --git a/bottleneck/tests/data/test_189_A b/bottleneck/tests/data/test_189_A
new file mode 100644
index 0000000..468967c
--- /dev/null
+++ b/bottleneck/tests/data/test_189_A
@@ -0,0 +1,6 @@
+8 11
+4 8
+6 7
+9 15
+10 11
+2 3
diff --git a/bottleneck/tests/data/test_189_B b/bottleneck/tests/data/test_189_B
new file mode 100644
index 0000000..299edf6
--- /dev/null
+++ b/bottleneck/tests/data/test_189_B
@@ -0,0 +1,6 @@
+6 10
+2 6
+2 9
+1 3
+7 10
+8 15
diff --git a/bottleneck/tests/data/test_190_A b/bottleneck/tests/data/test_190_A
new file mode 100644
index 0000000..01b3e3c
--- /dev/null
+++ b/bottleneck/tests/data/test_190_A
@@ -0,0 +1,6 @@
+8 17
+9 10
+1 3
+9 16
+7 10
+8 14
diff --git a/bottleneck/tests/data/test_190_B b/bottleneck/tests/data/test_190_B
new file mode 100644
index 0000000..26d2d2a
--- /dev/null
+++ b/bottleneck/tests/data/test_190_B
@@ -0,0 +1,6 @@
+8 9
+10 15
+10 12
+8 14
+4 5
+4 10
diff --git a/bottleneck/tests/data/test_191_A b/bottleneck/tests/data/test_191_A
new file mode 100644
index 0000000..e89e4b8
--- /dev/null
+++ b/bottleneck/tests/data/test_191_A
@@ -0,0 +1,6 @@
+10 15
+2 7
+9 16
+6 14
+6 12
+4 13
diff --git a/bottleneck/tests/data/test_191_B b/bottleneck/tests/data/test_191_B
new file mode 100644
index 0000000..80022bc
--- /dev/null
+++ b/bottleneck/tests/data/test_191_B
@@ -0,0 +1,6 @@
+8 18
+5 11
+2 7
+7 16
+6 9
+7 17
diff --git a/bottleneck/tests/data/test_192_A b/bottleneck/tests/data/test_192_A
new file mode 100644
index 0000000..8e0e64f
--- /dev/null
+++ b/bottleneck/tests/data/test_192_A
@@ -0,0 +1,6 @@
+9 15
+1 9
+2 11
+1 8
+9 11
+7 8
diff --git a/bottleneck/tests/data/test_192_B b/bottleneck/tests/data/test_192_B
new file mode 100644
index 0000000..dcfe162
--- /dev/null
+++ b/bottleneck/tests/data/test_192_B
@@ -0,0 +1,6 @@
+8 16
+10 17
+8 9
+2 9
+2 12
+7 11
diff --git a/bottleneck/tests/data/test_193_A b/bottleneck/tests/data/test_193_A
new file mode 100644
index 0000000..6c2bcc8
--- /dev/null
+++ b/bottleneck/tests/data/test_193_A
@@ -0,0 +1,6 @@
+5 10
+4 13
+6 7
+7 8
+7 8
+6 12
diff --git a/bottleneck/tests/data/test_193_B b/bottleneck/tests/data/test_193_B
new file mode 100644
index 0000000..fb271c9
--- /dev/null
+++ b/bottleneck/tests/data/test_193_B
@@ -0,0 +1,6 @@
+7 12
+2 5
+9 18
+1 6
+7 16
+1 5
diff --git a/bottleneck/tests/data/test_194_A b/bottleneck/tests/data/test_194_A
new file mode 100644
index 0000000..2de1094
--- /dev/null
+++ b/bottleneck/tests/data/test_194_A
@@ -0,0 +1,6 @@
+9 14
+7 12
+3 10
+1 9
+3 10
+0 1
diff --git a/bottleneck/tests/data/test_194_B b/bottleneck/tests/data/test_194_B
new file mode 100644
index 0000000..5879993
--- /dev/null
+++ b/bottleneck/tests/data/test_194_B
@@ -0,0 +1,6 @@
+6 15
+4 9
+3 7
+2 3
+0 2
+2 12
diff --git a/bottleneck/tests/data/test_195_A b/bottleneck/tests/data/test_195_A
new file mode 100644
index 0000000..d109838
--- /dev/null
+++ b/bottleneck/tests/data/test_195_A
@@ -0,0 +1,6 @@
+0 9
+7 8
+9 15
+2 6
+3 8
+9 15
diff --git a/bottleneck/tests/data/test_195_B b/bottleneck/tests/data/test_195_B
new file mode 100644
index 0000000..6c66513
--- /dev/null
+++ b/bottleneck/tests/data/test_195_B
@@ -0,0 +1,6 @@
+3 9
+2 3
+3 10
+7 16
+4 7
+1 6
diff --git a/bottleneck/tests/data/test_196_A b/bottleneck/tests/data/test_196_A
new file mode 100644
index 0000000..4094acd
--- /dev/null
+++ b/bottleneck/tests/data/test_196_A
@@ -0,0 +1,6 @@
+6 8
+8 12
+0 4
+3 11
+4 14
+9 14
diff --git a/bottleneck/tests/data/test_196_B b/bottleneck/tests/data/test_196_B
new file mode 100644
index 0000000..e5ed3ad
--- /dev/null
+++ b/bottleneck/tests/data/test_196_B
@@ -0,0 +1,6 @@
+4 10
+2 3
+7 8
+2 8
+5 12
+9 10
diff --git a/bottleneck/tests/data/test_197_A b/bottleneck/tests/data/test_197_A
new file mode 100644
index 0000000..771897b
--- /dev/null
+++ b/bottleneck/tests/data/test_197_A
@@ -0,0 +1,6 @@
+4 10
+9 11
+0 6
+4 8
+9 14
+9 14
diff --git a/bottleneck/tests/data/test_197_B b/bottleneck/tests/data/test_197_B
new file mode 100644
index 0000000..1cfe6aa
--- /dev/null
+++ b/bottleneck/tests/data/test_197_B
@@ -0,0 +1,6 @@
+7 13
+6 7
+5 11
+3 13
+6 14
+10 15
diff --git a/bottleneck/tests/data/test_198_A b/bottleneck/tests/data/test_198_A
new file mode 100644
index 0000000..6966ac4
--- /dev/null
+++ b/bottleneck/tests/data/test_198_A
@@ -0,0 +1,6 @@
+10 17
+3 7
+7 8
+9 15
+0 3
+10 20
diff --git a/bottleneck/tests/data/test_198_B b/bottleneck/tests/data/test_198_B
new file mode 100644
index 0000000..6e9d9d4
--- /dev/null
+++ b/bottleneck/tests/data/test_198_B
@@ -0,0 +1,6 @@
+3 11
+4 7
+6 15
+8 15
+7 10
+2 10
diff --git a/bottleneck/tests/data/test_199_A b/bottleneck/tests/data/test_199_A
new file mode 100644
index 0000000..8556563
--- /dev/null
+++ b/bottleneck/tests/data/test_199_A
@@ -0,0 +1,6 @@
+7 17
+3 13
+10 15
+9 17
+7 8
+5 14
diff --git a/bottleneck/tests/data/test_199_B b/bottleneck/tests/data/test_199_B
new file mode 100644
index 0000000..a43e0df
--- /dev/null
+++ b/bottleneck/tests/data/test_199_B
@@ -0,0 +1,6 @@
+7 17
+7 17
+9 14
+4 13
+1 8
+1 10
diff --git a/bottleneck/tests/data/test_200_A b/bottleneck/tests/data/test_200_A
new file mode 100644
index 0000000..b0a7fbd
--- /dev/null
+++ b/bottleneck/tests/data/test_200_A
@@ -0,0 +1,7 @@
+9 10
+0 10
+7 8
+1 6
+8 14
+0 3
+6 9
diff --git a/bottleneck/tests/data/test_200_B b/bottleneck/tests/data/test_200_B
new file mode 100644
index 0000000..fcbab9a
--- /dev/null
+++ b/bottleneck/tests/data/test_200_B
@@ -0,0 +1,7 @@
+2 7
+0 7
+2 4
+8 12
+7 12
+10 16
+5 6
diff --git a/bottleneck/tests/data/test_201_A b/bottleneck/tests/data/test_201_A
new file mode 100644
index 0000000..07d880d
--- /dev/null
+++ b/bottleneck/tests/data/test_201_A
@@ -0,0 +1,7 @@
+4 5
+1 7
+0 8
+4 5
+9 14
+8 9
+2 10
diff --git a/bottleneck/tests/data/test_201_B b/bottleneck/tests/data/test_201_B
new file mode 100644
index 0000000..70b22f4
--- /dev/null
+++ b/bottleneck/tests/data/test_201_B
@@ -0,0 +1,7 @@
+5 6
+6 16
+1 2
+2 3
+4 12
+6 15
+8 18
diff --git a/bottleneck/tests/data/test_202_A b/bottleneck/tests/data/test_202_A
new file mode 100644
index 0000000..b8fe1b9
--- /dev/null
+++ b/bottleneck/tests/data/test_202_A
@@ -0,0 +1,7 @@
+0 6
+4 14
+9 10
+9 18
+5 12
+5 12
+1 7
diff --git a/bottleneck/tests/data/test_202_B b/bottleneck/tests/data/test_202_B
new file mode 100644
index 0000000..ee6e2e0
--- /dev/null
+++ b/bottleneck/tests/data/test_202_B
@@ -0,0 +1,7 @@
+5 6
+7 17
+1 6
+3 11
+7 15
+10 20
+3 4
diff --git a/bottleneck/tests/data/test_203_A b/bottleneck/tests/data/test_203_A
new file mode 100644
index 0000000..71a1737
--- /dev/null
+++ b/bottleneck/tests/data/test_203_A
@@ -0,0 +1,7 @@
+4 9
+10 20
+5 9
+0 9
+0 8
+5 9
+0 10
diff --git a/bottleneck/tests/data/test_203_B b/bottleneck/tests/data/test_203_B
new file mode 100644
index 0000000..d217cda
--- /dev/null
+++ b/bottleneck/tests/data/test_203_B
@@ -0,0 +1,7 @@
+3 12
+1 9
+9 17
+7 14
+6 10
+10 20
+7 12
diff --git a/bottleneck/tests/data/test_204_A b/bottleneck/tests/data/test_204_A
new file mode 100644
index 0000000..011da68
--- /dev/null
+++ b/bottleneck/tests/data/test_204_A
@@ -0,0 +1,7 @@
+9 14
+2 3
+9 14
+6 7
+2 3
+6 13
+10 11
diff --git a/bottleneck/tests/data/test_204_B b/bottleneck/tests/data/test_204_B
new file mode 100644
index 0000000..c5d6236
--- /dev/null
+++ b/bottleneck/tests/data/test_204_B
@@ -0,0 +1,7 @@
+9 10
+0 4
+4 7
+8 15
+8 9
+7 10
+10 11
diff --git a/bottleneck/tests/data/test_205_A b/bottleneck/tests/data/test_205_A
new file mode 100644
index 0000000..d082be1
--- /dev/null
+++ b/bottleneck/tests/data/test_205_A
@@ -0,0 +1,7 @@
+8 17
+9 12
+2 11
+0 8
+10 11
+0 7
+8 18
diff --git a/bottleneck/tests/data/test_205_B b/bottleneck/tests/data/test_205_B
new file mode 100644
index 0000000..30a242c
--- /dev/null
+++ b/bottleneck/tests/data/test_205_B
@@ -0,0 +1,7 @@
+10 17
+9 18
+6 11
+6 7
+10 17
+3 13
+8 17
diff --git a/bottleneck/tests/data/test_206_A b/bottleneck/tests/data/test_206_A
new file mode 100644
index 0000000..15ee45b
--- /dev/null
+++ b/bottleneck/tests/data/test_206_A
@@ -0,0 +1,7 @@
+5 7
+8 17
+4 7
+7 17
+9 11
+0 8
+9 10
diff --git a/bottleneck/tests/data/test_206_B b/bottleneck/tests/data/test_206_B
new file mode 100644
index 0000000..f8c89ef
--- /dev/null
+++ b/bottleneck/tests/data/test_206_B
@@ -0,0 +1,7 @@
+5 15
+9 17
+10 13
+6 13
+0 6
+10 16
+8 15
diff --git a/bottleneck/tests/data/test_207_A b/bottleneck/tests/data/test_207_A
new file mode 100644
index 0000000..2015b9e
--- /dev/null
+++ b/bottleneck/tests/data/test_207_A
@@ -0,0 +1,7 @@
+4 9
+9 17
+9 10
+9 15
+2 3
+8 13
+9 13
diff --git a/bottleneck/tests/data/test_207_B b/bottleneck/tests/data/test_207_B
new file mode 100644
index 0000000..036a8ca
--- /dev/null
+++ b/bottleneck/tests/data/test_207_B
@@ -0,0 +1,7 @@
+10 18
+1 3
+10 15
+5 14
+7 15
+0 1
+10 13
diff --git a/bottleneck/tests/data/test_208_A b/bottleneck/tests/data/test_208_A
new file mode 100644
index 0000000..a1e6af4
--- /dev/null
+++ b/bottleneck/tests/data/test_208_A
@@ -0,0 +1,7 @@
+6 14
+2 7
+6 16
+7 14
+8 13
+2 5
+5 9
diff --git a/bottleneck/tests/data/test_208_B b/bottleneck/tests/data/test_208_B
new file mode 100644
index 0000000..f21e91b
--- /dev/null
+++ b/bottleneck/tests/data/test_208_B
@@ -0,0 +1,7 @@
+3 10
+8 16
+2 11
+10 18
+2 6
+3 7
+3 8
diff --git a/bottleneck/tests/data/test_209_A b/bottleneck/tests/data/test_209_A
new file mode 100644
index 0000000..545aae9
--- /dev/null
+++ b/bottleneck/tests/data/test_209_A
@@ -0,0 +1,7 @@
+10 18
+5 8
+4 7
+10 16
+4 10
+2 9
+1 6
diff --git a/bottleneck/tests/data/test_209_B b/bottleneck/tests/data/test_209_B
new file mode 100644
index 0000000..2cf3171
--- /dev/null
+++ b/bottleneck/tests/data/test_209_B
@@ -0,0 +1,7 @@
+10 11
+1 2
+0 6
+10 11
+9 11
+10 17
+1 2
diff --git a/bottleneck/tests/data/test_210_A b/bottleneck/tests/data/test_210_A
new file mode 100644
index 0000000..799debc
--- /dev/null
+++ b/bottleneck/tests/data/test_210_A
@@ -0,0 +1,7 @@
+1 3
+6 7
+10 11
+7 16
+4 5
+2 5
+10 18
diff --git a/bottleneck/tests/data/test_210_B b/bottleneck/tests/data/test_210_B
new file mode 100644
index 0000000..7cb0519
--- /dev/null
+++ b/bottleneck/tests/data/test_210_B
@@ -0,0 +1,7 @@
+3 7
+5 13
+6 11
+0 10
+10 18
+8 9
+1 4
diff --git a/bottleneck/tests/data/test_211_A b/bottleneck/tests/data/test_211_A
new file mode 100644
index 0000000..6715acb
--- /dev/null
+++ b/bottleneck/tests/data/test_211_A
@@ -0,0 +1,7 @@
+9 15
+1 5
+10 11
+2 6
+6 8
+2 9
+8 11
diff --git a/bottleneck/tests/data/test_211_B b/bottleneck/tests/data/test_211_B
new file mode 100644
index 0000000..9c7890f
--- /dev/null
+++ b/bottleneck/tests/data/test_211_B
@@ -0,0 +1,7 @@
+5 7
+3 9
+1 3
+1 2
+4 5
+4 7
+3 7
diff --git a/bottleneck/tests/data/test_212_A b/bottleneck/tests/data/test_212_A
new file mode 100644
index 0000000..e3d327a
--- /dev/null
+++ b/bottleneck/tests/data/test_212_A
@@ -0,0 +1,7 @@
+3 6
+8 12
+7 15
+6 11
+9 16
+4 8
+7 12
diff --git a/bottleneck/tests/data/test_212_B b/bottleneck/tests/data/test_212_B
new file mode 100644
index 0000000..ee57410
--- /dev/null
+++ b/bottleneck/tests/data/test_212_B
@@ -0,0 +1,7 @@
+9 17
+1 2
+10 17
+1 10
+5 8
+5 7
+7 10
diff --git a/bottleneck/tests/data/test_213_A b/bottleneck/tests/data/test_213_A
new file mode 100644
index 0000000..4b904df
--- /dev/null
+++ b/bottleneck/tests/data/test_213_A
@@ -0,0 +1,7 @@
+4 8
+0 2
+0 7
+0 4
+6 15
+8 14
+3 10
diff --git a/bottleneck/tests/data/test_213_B b/bottleneck/tests/data/test_213_B
new file mode 100644
index 0000000..f5188b4
--- /dev/null
+++ b/bottleneck/tests/data/test_213_B
@@ -0,0 +1,7 @@
+8 9
+8 13
+9 10
+2 12
+4 7
+7 8
+3 12
diff --git a/bottleneck/tests/data/test_214_A b/bottleneck/tests/data/test_214_A
new file mode 100644
index 0000000..3914579
--- /dev/null
+++ b/bottleneck/tests/data/test_214_A
@@ -0,0 +1,7 @@
+4 10
+7 8
+8 15
+1 4
+6 13
+8 15
+8 9
diff --git a/bottleneck/tests/data/test_214_B b/bottleneck/tests/data/test_214_B
new file mode 100644
index 0000000..f75c54f
--- /dev/null
+++ b/bottleneck/tests/data/test_214_B
@@ -0,0 +1,7 @@
+5 12
+2 12
+5 10
+1 8
+10 19
+0 6
+3 9
diff --git a/bottleneck/tests/data/test_215_A b/bottleneck/tests/data/test_215_A
new file mode 100644
index 0000000..a8d6070
--- /dev/null
+++ b/bottleneck/tests/data/test_215_A
@@ -0,0 +1,7 @@
+3 4
+4 5
+3 9
+7 15
+9 12
+1 2
+4 12
diff --git a/bottleneck/tests/data/test_215_B b/bottleneck/tests/data/test_215_B
new file mode 100644
index 0000000..d956b59
--- /dev/null
+++ b/bottleneck/tests/data/test_215_B
@@ -0,0 +1,7 @@
+4 13
+5 7
+2 6
+9 12
+0 6
+0 1
+6 12
diff --git a/bottleneck/tests/data/test_216_A b/bottleneck/tests/data/test_216_A
new file mode 100644
index 0000000..67c5e86
--- /dev/null
+++ b/bottleneck/tests/data/test_216_A
@@ -0,0 +1,7 @@
+10 13
+10 17
+5 10
+4 6
+9 12
+6 9
+2 6
diff --git a/bottleneck/tests/data/test_216_B b/bottleneck/tests/data/test_216_B
new file mode 100644
index 0000000..802850d
--- /dev/null
+++ b/bottleneck/tests/data/test_216_B
@@ -0,0 +1,7 @@
+3 9
+9 13
+1 2
+4 13
+1 8
+0 2
+1 2
diff --git a/bottleneck/tests/data/test_217_A b/bottleneck/tests/data/test_217_A
new file mode 100644
index 0000000..a37f46d
--- /dev/null
+++ b/bottleneck/tests/data/test_217_A
@@ -0,0 +1,7 @@
+3 7
+1 4
+3 8
+1 2
+1 3
+8 9
+5 14
diff --git a/bottleneck/tests/data/test_217_B b/bottleneck/tests/data/test_217_B
new file mode 100644
index 0000000..4cac64e
--- /dev/null
+++ b/bottleneck/tests/data/test_217_B
@@ -0,0 +1,7 @@
+3 12
+9 10
+9 10
+5 14
+0 8
+5 8
+2 5
diff --git a/bottleneck/tests/data/test_218_A b/bottleneck/tests/data/test_218_A
new file mode 100644
index 0000000..7ca83bc
--- /dev/null
+++ b/bottleneck/tests/data/test_218_A
@@ -0,0 +1,7 @@
+7 11
+6 14
+9 19
+6 8
+2 7
+4 8
+2 8
diff --git a/bottleneck/tests/data/test_218_B b/bottleneck/tests/data/test_218_B
new file mode 100644
index 0000000..7c188f2
--- /dev/null
+++ b/bottleneck/tests/data/test_218_B
@@ -0,0 +1,7 @@
+2 4
+8 16
+3 13
+3 12
+1 11
+0 1
+5 7
diff --git a/bottleneck/tests/data/test_219_A b/bottleneck/tests/data/test_219_A
new file mode 100644
index 0000000..275bc18
--- /dev/null
+++ b/bottleneck/tests/data/test_219_A
@@ -0,0 +1,7 @@
+3 4
+8 10
+5 6
+3 7
+9 12
+5 6
+0 1
diff --git a/bottleneck/tests/data/test_219_B b/bottleneck/tests/data/test_219_B
new file mode 100644
index 0000000..be6ab2a
--- /dev/null
+++ b/bottleneck/tests/data/test_219_B
@@ -0,0 +1,7 @@
+7 16
+1 2
+4 12
+9 17
+10 11
+9 14
+10 16
diff --git a/bottleneck/tests/data/test_220_A b/bottleneck/tests/data/test_220_A
new file mode 100644
index 0000000..3b9ea09
--- /dev/null
+++ b/bottleneck/tests/data/test_220_A
@@ -0,0 +1,8 @@
+8 18
+6 9
+7 12
+8 14
+7 8
+4 11
+9 18
+4 8
diff --git a/bottleneck/tests/data/test_220_B b/bottleneck/tests/data/test_220_B
new file mode 100644
index 0000000..8e97d15
--- /dev/null
+++ b/bottleneck/tests/data/test_220_B
@@ -0,0 +1,8 @@
+9 19
+5 9
+8 9
+2 10
+3 9
+2 5
+6 15
+9 14
diff --git a/bottleneck/tests/data/test_221_A b/bottleneck/tests/data/test_221_A
new file mode 100644
index 0000000..2e229a8
--- /dev/null
+++ b/bottleneck/tests/data/test_221_A
@@ -0,0 +1,8 @@
+9 17
+4 10
+3 5
+9 18
+3 10
+9 18
+5 12
+0 10
diff --git a/bottleneck/tests/data/test_221_B b/bottleneck/tests/data/test_221_B
new file mode 100644
index 0000000..e3c3c1b
--- /dev/null
+++ b/bottleneck/tests/data/test_221_B
@@ -0,0 +1,8 @@
+1 3
+1 2
+2 6
+10 19
+4 14
+10 18
+4 9
+9 19
diff --git a/bottleneck/tests/data/test_222_A b/bottleneck/tests/data/test_222_A
new file mode 100644
index 0000000..fcb6c7f
--- /dev/null
+++ b/bottleneck/tests/data/test_222_A
@@ -0,0 +1,8 @@
+9 13
+6 10
+10 17
+9 14
+7 16
+2 4
+5 11
+10 13
diff --git a/bottleneck/tests/data/test_222_B b/bottleneck/tests/data/test_222_B
new file mode 100644
index 0000000..512f188
--- /dev/null
+++ b/bottleneck/tests/data/test_222_B
@@ -0,0 +1,8 @@
+1 11
+0 1
+8 10
+0 6
+9 19
+3 4
+2 6
+9 10
diff --git a/bottleneck/tests/data/test_223_A b/bottleneck/tests/data/test_223_A
new file mode 100644
index 0000000..6f6cef5
--- /dev/null
+++ b/bottleneck/tests/data/test_223_A
@@ -0,0 +1,8 @@
+0 8
+2 6
+3 13
+9 16
+4 7
+4 14
+7 17
+6 7
diff --git a/bottleneck/tests/data/test_223_B b/bottleneck/tests/data/test_223_B
new file mode 100644
index 0000000..07803f6
--- /dev/null
+++ b/bottleneck/tests/data/test_223_B
@@ -0,0 +1,8 @@
+7 9
+3 10
+0 9
+0 1
+1 5
+2 8
+0 1
+10 18
diff --git a/bottleneck/tests/data/test_224_A b/bottleneck/tests/data/test_224_A
new file mode 100644
index 0000000..f33d061
--- /dev/null
+++ b/bottleneck/tests/data/test_224_A
@@ -0,0 +1,8 @@
+5 12
+0 6
+5 11
+9 17
+9 10
+0 10
+0 4
+8 13
diff --git a/bottleneck/tests/data/test_224_B b/bottleneck/tests/data/test_224_B
new file mode 100644
index 0000000..1b9ef36
--- /dev/null
+++ b/bottleneck/tests/data/test_224_B
@@ -0,0 +1,8 @@
+8 14
+3 13
+3 4
+9 19
+8 16
+5 9
+4 14
+2 4
diff --git a/bottleneck/tests/data/test_225_A b/bottleneck/tests/data/test_225_A
new file mode 100644
index 0000000..cc0d576
--- /dev/null
+++ b/bottleneck/tests/data/test_225_A
@@ -0,0 +1,8 @@
+0 1
+9 17
+3 12
+9 19
+8 15
+7 15
+6 10
+1 10
diff --git a/bottleneck/tests/data/test_225_B b/bottleneck/tests/data/test_225_B
new file mode 100644
index 0000000..b810b48
--- /dev/null
+++ b/bottleneck/tests/data/test_225_B
@@ -0,0 +1,8 @@
+8 11
+4 8
+8 14
+3 8
+2 10
+8 15
+5 14
+6 16
diff --git a/bottleneck/tests/data/test_226_A b/bottleneck/tests/data/test_226_A
new file mode 100644
index 0000000..e39728a
--- /dev/null
+++ b/bottleneck/tests/data/test_226_A
@@ -0,0 +1,8 @@
+10 12
+3 5
+10 13
+6 8
+8 14
+8 15
+8 17
+3 8
diff --git a/bottleneck/tests/data/test_226_B b/bottleneck/tests/data/test_226_B
new file mode 100644
index 0000000..601abce
--- /dev/null
+++ b/bottleneck/tests/data/test_226_B
@@ -0,0 +1,8 @@
+3 4
+9 19
+3 7
+9 10
+1 4
+7 12
+0 1
+4 13
diff --git a/bottleneck/tests/data/test_227_A b/bottleneck/tests/data/test_227_A
new file mode 100644
index 0000000..e98b204
--- /dev/null
+++ b/bottleneck/tests/data/test_227_A
@@ -0,0 +1,8 @@
+10 11
+8 9
+2 8
+5 14
+6 16
+3 9
+7 8
+0 7
diff --git a/bottleneck/tests/data/test_227_B b/bottleneck/tests/data/test_227_B
new file mode 100644
index 0000000..3d5a25e
--- /dev/null
+++ b/bottleneck/tests/data/test_227_B
@@ -0,0 +1,8 @@
+7 8
+9 14
+2 7
+7 17
+5 13
+4 6
+3 4
+6 16
diff --git a/bottleneck/tests/data/test_228_A b/bottleneck/tests/data/test_228_A
new file mode 100644
index 0000000..a3edeae
--- /dev/null
+++ b/bottleneck/tests/data/test_228_A
@@ -0,0 +1,8 @@
+9 10
+1 6
+8 10
+0 9
+0 2
+7 13
+10 20
+1 10
diff --git a/bottleneck/tests/data/test_228_B b/bottleneck/tests/data/test_228_B
new file mode 100644
index 0000000..64f78ac
--- /dev/null
+++ b/bottleneck/tests/data/test_228_B
@@ -0,0 +1,8 @@
+4 6
+9 12
+5 11
+9 16
+8 9
+7 16
+4 10
+3 4
diff --git a/bottleneck/tests/data/test_229_A b/bottleneck/tests/data/test_229_A
new file mode 100644
index 0000000..c832a04
--- /dev/null
+++ b/bottleneck/tests/data/test_229_A
@@ -0,0 +1,8 @@
+9 12
+1 10
+6 14
+4 9
+7 11
+3 12
+6 8
+4 12
diff --git a/bottleneck/tests/data/test_229_B b/bottleneck/tests/data/test_229_B
new file mode 100644
index 0000000..0f232d0
--- /dev/null
+++ b/bottleneck/tests/data/test_229_B
@@ -0,0 +1,8 @@
+7 13
+2 11
+6 10
+6 10
+7 15
+10 14
+10 13
+10 14
diff --git a/bottleneck/tests/data/test_230_A b/bottleneck/tests/data/test_230_A
new file mode 100644
index 0000000..11d75a8
--- /dev/null
+++ b/bottleneck/tests/data/test_230_A
@@ -0,0 +1,8 @@
+9 16
+3 5
+3 11
+0 7
+0 2
+10 16
+4 6
+8 16
diff --git a/bottleneck/tests/data/test_230_B b/bottleneck/tests/data/test_230_B
new file mode 100644
index 0000000..f30b9d0
--- /dev/null
+++ b/bottleneck/tests/data/test_230_B
@@ -0,0 +1,8 @@
+4 11
+7 14
+8 17
+6 13
+0 1
+6 10
+8 10
+1 6
diff --git a/bottleneck/tests/data/test_231_A b/bottleneck/tests/data/test_231_A
new file mode 100644
index 0000000..8d21ce3
--- /dev/null
+++ b/bottleneck/tests/data/test_231_A
@@ -0,0 +1,8 @@
+2 9
+1 11
+10 20
+7 16
+7 9
+0 7
+6 7
+6 7
diff --git a/bottleneck/tests/data/test_231_B b/bottleneck/tests/data/test_231_B
new file mode 100644
index 0000000..f5d94fe
--- /dev/null
+++ b/bottleneck/tests/data/test_231_B
@@ -0,0 +1,8 @@
+7 10
+10 19
+8 9
+5 12
+7 17
+3 5
+10 11
+0 1
diff --git a/bottleneck/tests/data/test_232_A b/bottleneck/tests/data/test_232_A
new file mode 100644
index 0000000..ccad736
--- /dev/null
+++ b/bottleneck/tests/data/test_232_A
@@ -0,0 +1,8 @@
+1 6
+5 9
+9 10
+0 9
+0 8
+10 11
+2 7
+6 7
diff --git a/bottleneck/tests/data/test_232_B b/bottleneck/tests/data/test_232_B
new file mode 100644
index 0000000..f132580
--- /dev/null
+++ b/bottleneck/tests/data/test_232_B
@@ -0,0 +1,8 @@
+5 8
+4 5
+10 17
+10 16
+4 10
+5 14
+5 6
+0 7
diff --git a/bottleneck/tests/data/test_233_A b/bottleneck/tests/data/test_233_A
new file mode 100644
index 0000000..fd2fa4e
--- /dev/null
+++ b/bottleneck/tests/data/test_233_A
@@ -0,0 +1,8 @@
+9 13
+2 6
+0 1
+6 14
+9 13
+0 1
+6 9
+2 9
diff --git a/bottleneck/tests/data/test_233_B b/bottleneck/tests/data/test_233_B
new file mode 100644
index 0000000..3dc34c6
--- /dev/null
+++ b/bottleneck/tests/data/test_233_B
@@ -0,0 +1,8 @@
+8 12
+5 12
+1 5
+10 13
+1 7
+8 14
+7 15
+1 8
diff --git a/bottleneck/tests/data/test_234_A b/bottleneck/tests/data/test_234_A
new file mode 100644
index 0000000..6ff3442
--- /dev/null
+++ b/bottleneck/tests/data/test_234_A
@@ -0,0 +1,8 @@
+0 7
+5 13
+10 20
+1 2
+9 10
+10 17
+1 2
+0 7
diff --git a/bottleneck/tests/data/test_234_B b/bottleneck/tests/data/test_234_B
new file mode 100644
index 0000000..36a2966
--- /dev/null
+++ b/bottleneck/tests/data/test_234_B
@@ -0,0 +1,8 @@
+2 12
+1 2
+3 4
+1 4
+0 7
+7 8
+8 13
+9 18
diff --git a/bottleneck/tests/data/test_235_A b/bottleneck/tests/data/test_235_A
new file mode 100644
index 0000000..40aec79
--- /dev/null
+++ b/bottleneck/tests/data/test_235_A
@@ -0,0 +1,8 @@
+4 7
+10 11
+7 12
+2 7
+8 11
+9 11
+8 12
+7 16
diff --git a/bottleneck/tests/data/test_235_B b/bottleneck/tests/data/test_235_B
new file mode 100644
index 0000000..910422b
--- /dev/null
+++ b/bottleneck/tests/data/test_235_B
@@ -0,0 +1,8 @@
+1 3
+9 15
+10 20
+6 16
+2 8
+3 9
+8 10
+9 14
diff --git a/bottleneck/tests/data/test_236_A b/bottleneck/tests/data/test_236_A
new file mode 100644
index 0000000..8ca54db
--- /dev/null
+++ b/bottleneck/tests/data/test_236_A
@@ -0,0 +1,8 @@
+5 11
+10 15
+7 9
+8 14
+0 5
+1 7
+2 3
+6 11
diff --git a/bottleneck/tests/data/test_236_B b/bottleneck/tests/data/test_236_B
new file mode 100644
index 0000000..0855757
--- /dev/null
+++ b/bottleneck/tests/data/test_236_B
@@ -0,0 +1,8 @@
+4 5
+1 8
+1 2
+1 4
+8 17
+2 5
+3 10
+1 2
diff --git a/bottleneck/tests/data/test_237_A b/bottleneck/tests/data/test_237_A
new file mode 100644
index 0000000..18a69fa
--- /dev/null
+++ b/bottleneck/tests/data/test_237_A
@@ -0,0 +1,8 @@
+1 6
+3 6
+4 8
+0 3
+7 14
+6 7
+2 5
+6 13
diff --git a/bottleneck/tests/data/test_237_B b/bottleneck/tests/data/test_237_B
new file mode 100644
index 0000000..b2ad13f
--- /dev/null
+++ b/bottleneck/tests/data/test_237_B
@@ -0,0 +1,8 @@
+3 8
+6 16
+3 11
+6 15
+7 14
+6 11
+3 5
+8 14
diff --git a/bottleneck/tests/data/test_238_A b/bottleneck/tests/data/test_238_A
new file mode 100644
index 0000000..d9011b0
--- /dev/null
+++ b/bottleneck/tests/data/test_238_A
@@ -0,0 +1,8 @@
+7 16
+3 12
+4 7
+7 13
+6 9
+5 8
+5 9
+3 4
diff --git a/bottleneck/tests/data/test_238_B b/bottleneck/tests/data/test_238_B
new file mode 100644
index 0000000..788cf40
--- /dev/null
+++ b/bottleneck/tests/data/test_238_B
@@ -0,0 +1,8 @@
+5 6
+0 10
+2 5
+1 2
+9 16
+0 8
+0 3
+5 12
diff --git a/bottleneck/tests/data/test_239_A b/bottleneck/tests/data/test_239_A
new file mode 100644
index 0000000..dbb3bec
--- /dev/null
+++ b/bottleneck/tests/data/test_239_A
@@ -0,0 +1,8 @@
+2 10
+1 6
+10 20
+7 10
+2 7
+4 11
+0 5
+6 13
diff --git a/bottleneck/tests/data/test_239_B b/bottleneck/tests/data/test_239_B
new file mode 100644
index 0000000..a0c12ac
--- /dev/null
+++ b/bottleneck/tests/data/test_239_B
@@ -0,0 +1,8 @@
+1 5
+1 3
+5 8
+9 16
+8 17
+9 13
+3 4
+4 7
diff --git a/bottleneck/tests/data/test_240_A b/bottleneck/tests/data/test_240_A
new file mode 100644
index 0000000..2386a27
--- /dev/null
+++ b/bottleneck/tests/data/test_240_A
@@ -0,0 +1,9 @@
+0 1
+10 15
+6 7
+5 14
+10 15
+9 12
+0 4
+10 11
+3 10
diff --git a/bottleneck/tests/data/test_240_B b/bottleneck/tests/data/test_240_B
new file mode 100644
index 0000000..15439fb
--- /dev/null
+++ b/bottleneck/tests/data/test_240_B
@@ -0,0 +1,9 @@
+0 3
+3 6
+2 12
+3 4
+9 13
+0 3
+0 7
+10 17
+6 15
diff --git a/bottleneck/tests/data/test_241_A b/bottleneck/tests/data/test_241_A
new file mode 100644
index 0000000..8ed0c54
--- /dev/null
+++ b/bottleneck/tests/data/test_241_A
@@ -0,0 +1,9 @@
+1 10
+10 14
+3 4
+3 6
+7 12
+1 3
+9 14
+0 2
+1 11
diff --git a/bottleneck/tests/data/test_241_B b/bottleneck/tests/data/test_241_B
new file mode 100644
index 0000000..fdac53a
--- /dev/null
+++ b/bottleneck/tests/data/test_241_B
@@ -0,0 +1,9 @@
+7 8
+8 14
+10 20
+10 16
+2 7
+0 8
+7 17
+1 2
+5 6
diff --git a/bottleneck/tests/data/test_242_A b/bottleneck/tests/data/test_242_A
new file mode 100644
index 0000000..e1af329
--- /dev/null
+++ b/bottleneck/tests/data/test_242_A
@@ -0,0 +1,9 @@
+0 3
+2 4
+5 14
+4 8
+0 7
+3 13
+5 11
+5 7
+10 19
diff --git a/bottleneck/tests/data/test_242_B b/bottleneck/tests/data/test_242_B
new file mode 100644
index 0000000..b45d054
--- /dev/null
+++ b/bottleneck/tests/data/test_242_B
@@ -0,0 +1,9 @@
+5 6
+6 13
+7 12
+2 10
+0 9
+2 11
+2 9
+8 10
+10 13
diff --git a/bottleneck/tests/data/test_243_A b/bottleneck/tests/data/test_243_A
new file mode 100644
index 0000000..ed2d61b
--- /dev/null
+++ b/bottleneck/tests/data/test_243_A
@@ -0,0 +1,9 @@
+4 6
+10 11
+4 7
+8 14
+1 4
+9 15
+8 10
+4 11
+7 10
diff --git a/bottleneck/tests/data/test_243_B b/bottleneck/tests/data/test_243_B
new file mode 100644
index 0000000..f0b5359
--- /dev/null
+++ b/bottleneck/tests/data/test_243_B
@@ -0,0 +1,9 @@
+7 8
+1 9
+7 10
+5 6
+3 11
+10 12
+1 8
+3 13
+0 9
diff --git a/bottleneck/tests/data/test_244_A b/bottleneck/tests/data/test_244_A
new file mode 100644
index 0000000..1d1e4a7
--- /dev/null
+++ b/bottleneck/tests/data/test_244_A
@@ -0,0 +1,9 @@
+4 14
+3 8
+0 3
+3 12
+9 16
+4 7
+6 12
+7 8
+5 13
diff --git a/bottleneck/tests/data/test_244_B b/bottleneck/tests/data/test_244_B
new file mode 100644
index 0000000..5d9748f
--- /dev/null
+++ b/bottleneck/tests/data/test_244_B
@@ -0,0 +1,9 @@
+3 7
+3 8
+5 15
+4 7
+1 2
+0 10
+6 15
+8 9
+4 5
diff --git a/bottleneck/tests/data/test_245_A b/bottleneck/tests/data/test_245_A
new file mode 100644
index 0000000..f17d580
--- /dev/null
+++ b/bottleneck/tests/data/test_245_A
@@ -0,0 +1,9 @@
+5 6
+3 11
+7 9
+1 7
+5 14
+4 7
+9 19
+1 7
+4 6
diff --git a/bottleneck/tests/data/test_245_B b/bottleneck/tests/data/test_245_B
new file mode 100644
index 0000000..4b67caa
--- /dev/null
+++ b/bottleneck/tests/data/test_245_B
@@ -0,0 +1,9 @@
+1 2
+6 7
+7 13
+1 9
+9 13
+2 8
+2 4
+4 5
+4 7
diff --git a/bottleneck/tests/data/test_246_A b/bottleneck/tests/data/test_246_A
new file mode 100644
index 0000000..b4ddade
--- /dev/null
+++ b/bottleneck/tests/data/test_246_A
@@ -0,0 +1,9 @@
+10 15
+3 10
+2 7
+1 6
+2 3
+2 9
+9 10
+9 12
+8 18
diff --git a/bottleneck/tests/data/test_246_B b/bottleneck/tests/data/test_246_B
new file mode 100644
index 0000000..6e0c12d
--- /dev/null
+++ b/bottleneck/tests/data/test_246_B
@@ -0,0 +1,9 @@
+4 9
+4 7
+6 11
+7 10
+0 3
+7 14
+7 17
+4 6
+10 15
diff --git a/bottleneck/tests/data/test_247_A b/bottleneck/tests/data/test_247_A
new file mode 100644
index 0000000..4832963
--- /dev/null
+++ b/bottleneck/tests/data/test_247_A
@@ -0,0 +1,9 @@
+5 14
+9 19
+4 5
+3 4
+2 7
+9 12
+10 11
+7 12
+8 12
diff --git a/bottleneck/tests/data/test_247_B b/bottleneck/tests/data/test_247_B
new file mode 100644
index 0000000..17cc1f0
--- /dev/null
+++ b/bottleneck/tests/data/test_247_B
@@ -0,0 +1,9 @@
+4 12
+2 7
+1 2
+9 19
+4 14
+6 12
+8 11
+5 12
+9 10
diff --git a/bottleneck/tests/data/test_248_A b/bottleneck/tests/data/test_248_A
new file mode 100644
index 0000000..adbf3d6
--- /dev/null
+++ b/bottleneck/tests/data/test_248_A
@@ -0,0 +1,9 @@
+8 9
+8 15
+2 12
+0 1
+8 14
+0 5
+7 17
+7 12
+7 10
diff --git a/bottleneck/tests/data/test_248_B b/bottleneck/tests/data/test_248_B
new file mode 100644
index 0000000..39ee264
--- /dev/null
+++ b/bottleneck/tests/data/test_248_B
@@ -0,0 +1,9 @@
+6 11
+1 10
+6 16
+10 13
+3 13
+10 16
+8 14
+8 16
+1 5
diff --git a/bottleneck/tests/data/test_249_A b/bottleneck/tests/data/test_249_A
new file mode 100644
index 0000000..2b8a639
--- /dev/null
+++ b/bottleneck/tests/data/test_249_A
@@ -0,0 +1,9 @@
+2 7
+2 4
+7 17
+2 11
+6 12
+3 12
+2 8
+5 6
+0 1
diff --git a/bottleneck/tests/data/test_249_B b/bottleneck/tests/data/test_249_B
new file mode 100644
index 0000000..06b036c
--- /dev/null
+++ b/bottleneck/tests/data/test_249_B
@@ -0,0 +1,9 @@
+0 1
+8 11
+9 13
+3 11
+3 13
+7 15
+2 6
+4 5
+3 4
diff --git a/bottleneck/tests/data/test_250_A b/bottleneck/tests/data/test_250_A
new file mode 100644
index 0000000..6934dd8
--- /dev/null
+++ b/bottleneck/tests/data/test_250_A
@@ -0,0 +1,9 @@
+0 8
+7 14
+5 12
+7 15
+9 19
+8 14
+6 15
+10 11
+9 19
diff --git a/bottleneck/tests/data/test_250_B b/bottleneck/tests/data/test_250_B
new file mode 100644
index 0000000..0d387ac
--- /dev/null
+++ b/bottleneck/tests/data/test_250_B
@@ -0,0 +1,9 @@
+8 13
+7 14
+0 6
+4 14
+7 17
+6 8
+5 13
+0 1
+5 10
diff --git a/bottleneck/tests/data/test_251_A b/bottleneck/tests/data/test_251_A
new file mode 100644
index 0000000..6fb7509
--- /dev/null
+++ b/bottleneck/tests/data/test_251_A
@@ -0,0 +1,9 @@
+1 8
+6 13
+1 6
+10 15
+7 8
+3 6
+3 11
+7 12
+4 9
diff --git a/bottleneck/tests/data/test_251_B b/bottleneck/tests/data/test_251_B
new file mode 100644
index 0000000..4ea7b4a
--- /dev/null
+++ b/bottleneck/tests/data/test_251_B
@@ -0,0 +1,9 @@
+5 11
+6 12
+2 9
+5 6
+0 5
+0 2
+6 10
+4 10
+10 19
diff --git a/bottleneck/tests/data/test_252_A b/bottleneck/tests/data/test_252_A
new file mode 100644
index 0000000..0076fb9
--- /dev/null
+++ b/bottleneck/tests/data/test_252_A
@@ -0,0 +1,9 @@
+4 8
+5 15
+0 10
+8 15
+1 8
+4 6
+5 13
+7 10
+0 1
diff --git a/bottleneck/tests/data/test_252_B b/bottleneck/tests/data/test_252_B
new file mode 100644
index 0000000..cf7fab7
--- /dev/null
+++ b/bottleneck/tests/data/test_252_B
@@ -0,0 +1,9 @@
+2 3
+4 6
+0 9
+4 7
+4 11
+6 10
+9 11
+1 5
+3 4
diff --git a/bottleneck/tests/data/test_253_A b/bottleneck/tests/data/test_253_A
new file mode 100644
index 0000000..0916538
--- /dev/null
+++ b/bottleneck/tests/data/test_253_A
@@ -0,0 +1,9 @@
+9 18
+1 10
+7 12
+0 6
+2 4
+1 10
+2 4
+1 2
+2 11
diff --git a/bottleneck/tests/data/test_253_B b/bottleneck/tests/data/test_253_B
new file mode 100644
index 0000000..3ee1874
--- /dev/null
+++ b/bottleneck/tests/data/test_253_B
@@ -0,0 +1,9 @@
+9 12
+6 11
+0 1
+6 7
+2 5
+6 8
+10 20
+9 17
+8 15
diff --git a/bottleneck/tests/data/test_254_A b/bottleneck/tests/data/test_254_A
new file mode 100644
index 0000000..85af9cb
--- /dev/null
+++ b/bottleneck/tests/data/test_254_A
@@ -0,0 +1,9 @@
+1 9
+2 10
+4 7
+4 14
+3 9
+1 11
+7 16
+10 11
+5 15
diff --git a/bottleneck/tests/data/test_254_B b/bottleneck/tests/data/test_254_B
new file mode 100644
index 0000000..573f5c5
--- /dev/null
+++ b/bottleneck/tests/data/test_254_B
@@ -0,0 +1,9 @@
+9 13
+0 1
+8 9
+8 9
+3 10
+5 14
+6 12
+3 5
+2 3
diff --git a/bottleneck/tests/data/test_255_A b/bottleneck/tests/data/test_255_A
new file mode 100644
index 0000000..2fc0a84
--- /dev/null
+++ b/bottleneck/tests/data/test_255_A
@@ -0,0 +1,9 @@
+10 11
+4 8
+2 10
+2 10
+3 8
+6 7
+8 14
+2 10
+4 11
diff --git a/bottleneck/tests/data/test_255_B b/bottleneck/tests/data/test_255_B
new file mode 100644
index 0000000..04e0521
--- /dev/null
+++ b/bottleneck/tests/data/test_255_B
@@ -0,0 +1,9 @@
+5 13
+8 12
+8 9
+4 10
+7 8
+1 7
+3 11
+10 15
+5 10
diff --git a/bottleneck/tests/data/test_256_A b/bottleneck/tests/data/test_256_A
new file mode 100644
index 0000000..bb1df33
--- /dev/null
+++ b/bottleneck/tests/data/test_256_A
@@ -0,0 +1,9 @@
+6 7
+7 8
+10 16
+2 5
+5 15
+7 9
+10 15
+9 18
+4 9
diff --git a/bottleneck/tests/data/test_256_B b/bottleneck/tests/data/test_256_B
new file mode 100644
index 0000000..a9bb2f8
--- /dev/null
+++ b/bottleneck/tests/data/test_256_B
@@ -0,0 +1,9 @@
+0 10
+7 9
+9 10
+7 8
+1 2
+2 4
+8 15
+3 7
+0 2
diff --git a/bottleneck/tests/data/test_257_A b/bottleneck/tests/data/test_257_A
new file mode 100644
index 0000000..ac06787
--- /dev/null
+++ b/bottleneck/tests/data/test_257_A
@@ -0,0 +1,9 @@
+6 14
+9 16
+9 18
+4 7
+8 15
+7 9
+9 17
+1 2
+10 17
diff --git a/bottleneck/tests/data/test_257_B b/bottleneck/tests/data/test_257_B
new file mode 100644
index 0000000..93ab86c
--- /dev/null
+++ b/bottleneck/tests/data/test_257_B
@@ -0,0 +1,9 @@
+2 3
+3 6
+10 13
+7 14
+0 8
+0 2
+9 12
+1 7
+0 1
diff --git a/bottleneck/tests/data/test_258_A b/bottleneck/tests/data/test_258_A
new file mode 100644
index 0000000..b00d4c3
--- /dev/null
+++ b/bottleneck/tests/data/test_258_A
@@ -0,0 +1,9 @@
+4 11
+0 6
+5 6
+2 4
+2 7
+8 11
+3 8
+3 4
+7 10
diff --git a/bottleneck/tests/data/test_258_B b/bottleneck/tests/data/test_258_B
new file mode 100644
index 0000000..f3ab79e
--- /dev/null
+++ b/bottleneck/tests/data/test_258_B
@@ -0,0 +1,9 @@
+6 15
+5 10
+9 10
+4 10
+7 8
+2 8
+8 18
+9 18
+5 9
diff --git a/bottleneck/tests/data/test_259_A b/bottleneck/tests/data/test_259_A
new file mode 100644
index 0000000..30c4a56
--- /dev/null
+++ b/bottleneck/tests/data/test_259_A
@@ -0,0 +1,9 @@
+4 5
+0 1
+4 7
+5 14
+2 8
+0 1
+9 13
+5 9
+10 13
diff --git a/bottleneck/tests/data/test_259_B b/bottleneck/tests/data/test_259_B
new file mode 100644
index 0000000..8cb51f7
--- /dev/null
+++ b/bottleneck/tests/data/test_259_B
@@ -0,0 +1,9 @@
+6 15
+9 18
+7 8
+9 16
+9 15
+5 15
+9 10
+6 10
+5 6
diff --git a/bottleneck/tests/data/test_260_A b/bottleneck/tests/data/test_260_A
new file mode 100644
index 0000000..83740c1
--- /dev/null
+++ b/bottleneck/tests/data/test_260_A
@@ -0,0 +1,10 @@
+1 4
+2 5
+3 7
+7 9
+4 13
+8 15
+10 19
+9 14
+10 18
+10 17
diff --git a/bottleneck/tests/data/test_260_B b/bottleneck/tests/data/test_260_B
new file mode 100644
index 0000000..18e1128
--- /dev/null
+++ b/bottleneck/tests/data/test_260_B
@@ -0,0 +1,10 @@
+0 4
+8 15
+4 6
+10 13
+6 7
+7 10
+8 13
+2 7
+4 13
+3 5
diff --git a/bottleneck/tests/data/test_261_A b/bottleneck/tests/data/test_261_A
new file mode 100644
index 0000000..259e18a
--- /dev/null
+++ b/bottleneck/tests/data/test_261_A
@@ -0,0 +1,10 @@
+8 11
+6 11
+9 16
+7 17
+7 14
+9 11
+0 1
+9 14
+6 14
+0 10
diff --git a/bottleneck/tests/data/test_261_B b/bottleneck/tests/data/test_261_B
new file mode 100644
index 0000000..2be943f
--- /dev/null
+++ b/bottleneck/tests/data/test_261_B
@@ -0,0 +1,10 @@
+8 18
+5 7
+9 12
+7 10
+3 6
+4 14
+9 15
+8 14
+1 9
+0 5
diff --git a/bottleneck/tests/data/test_262_A b/bottleneck/tests/data/test_262_A
new file mode 100644
index 0000000..ccb706b
--- /dev/null
+++ b/bottleneck/tests/data/test_262_A
@@ -0,0 +1,10 @@
+1 8
+6 16
+7 13
+10 13
+7 11
+10 15
+10 17
+8 17
+0 3
+5 6
diff --git a/bottleneck/tests/data/test_262_B b/bottleneck/tests/data/test_262_B
new file mode 100644
index 0000000..944d288
--- /dev/null
+++ b/bottleneck/tests/data/test_262_B
@@ -0,0 +1,10 @@
+9 18
+7 8
+0 8
+8 15
+6 14
+6 11
+6 16
+7 17
+3 4
+4 7
diff --git a/bottleneck/tests/data/test_263_A b/bottleneck/tests/data/test_263_A
new file mode 100644
index 0000000..6262062
--- /dev/null
+++ b/bottleneck/tests/data/test_263_A
@@ -0,0 +1,10 @@
+0 9
+10 11
+4 13
+9 13
+4 6
+7 13
+4 5
+7 9
+10 11
+10 18
diff --git a/bottleneck/tests/data/test_263_B b/bottleneck/tests/data/test_263_B
new file mode 100644
index 0000000..c9f8716
--- /dev/null
+++ b/bottleneck/tests/data/test_263_B
@@ -0,0 +1,10 @@
+2 6
+6 13
+2 12
+3 13
+5 6
+10 16
+9 18
+9 16
+10 18
+10 20
diff --git a/bottleneck/tests/data/test_264_A b/bottleneck/tests/data/test_264_A
new file mode 100644
index 0000000..8c79b6d
--- /dev/null
+++ b/bottleneck/tests/data/test_264_A
@@ -0,0 +1,10 @@
+3 11
+3 4
+8 12
+2 10
+7 12
+2 10
+10 13
+4 8
+2 9
+10 11
diff --git a/bottleneck/tests/data/test_264_B b/bottleneck/tests/data/test_264_B
new file mode 100644
index 0000000..9b92607
--- /dev/null
+++ b/bottleneck/tests/data/test_264_B
@@ -0,0 +1,10 @@
+7 11
+2 7
+4 12
+9 10
+10 12
+8 15
+8 12
+6 7
+2 11
+10 11
diff --git a/bottleneck/tests/data/test_265_A b/bottleneck/tests/data/test_265_A
new file mode 100644
index 0000000..4de3ff9
--- /dev/null
+++ b/bottleneck/tests/data/test_265_A
@@ -0,0 +1,10 @@
+0 4
+1 2
+6 11
+9 19
+0 6
+9 19
+0 5
+4 5
+7 11
+9 14
diff --git a/bottleneck/tests/data/test_265_B b/bottleneck/tests/data/test_265_B
new file mode 100644
index 0000000..f03f49f
--- /dev/null
+++ b/bottleneck/tests/data/test_265_B
@@ -0,0 +1,10 @@
+1 7
+5 10
+5 10
+4 6
+0 7
+4 12
+8 11
+10 15
+2 11
+8 17
diff --git a/bottleneck/tests/data/test_266_A b/bottleneck/tests/data/test_266_A
new file mode 100644
index 0000000..95754d3
--- /dev/null
+++ b/bottleneck/tests/data/test_266_A
@@ -0,0 +1,10 @@
+7 8
+3 12
+0 5
+0 6
+1 5
+9 17
+6 11
+3 5
+2 11
+5 7
diff --git a/bottleneck/tests/data/test_266_B b/bottleneck/tests/data/test_266_B
new file mode 100644
index 0000000..5a2d560
--- /dev/null
+++ b/bottleneck/tests/data/test_266_B
@@ -0,0 +1,10 @@
+10 17
+5 13
+9 10
+3 4
+4 10
+6 12
+0 7
+6 14
+1 6
+4 10
diff --git a/bottleneck/tests/data/test_267_A b/bottleneck/tests/data/test_267_A
new file mode 100644
index 0000000..d2c663e
--- /dev/null
+++ b/bottleneck/tests/data/test_267_A
@@ -0,0 +1,10 @@
+3 4
+10 20
+2 10
+1 7
+0 4
+0 10
+0 8
+3 4
+9 19
+7 13
diff --git a/bottleneck/tests/data/test_267_B b/bottleneck/tests/data/test_267_B
new file mode 100644
index 0000000..aebae2b
--- /dev/null
+++ b/bottleneck/tests/data/test_267_B
@@ -0,0 +1,10 @@
+2 11
+4 5
+1 10
+3 9
+6 11
+0 8
+2 3
+0 3
+6 11
+7 12
diff --git a/bottleneck/tests/data/test_268_A b/bottleneck/tests/data/test_268_A
new file mode 100644
index 0000000..d0e9835
--- /dev/null
+++ b/bottleneck/tests/data/test_268_A
@@ -0,0 +1,10 @@
+3 4
+10 17
+8 17
+0 2
+4 8
+0 8
+4 5
+5 6
+1 2
+1 7
diff --git a/bottleneck/tests/data/test_268_B b/bottleneck/tests/data/test_268_B
new file mode 100644
index 0000000..ac0c242
--- /dev/null
+++ b/bottleneck/tests/data/test_268_B
@@ -0,0 +1,10 @@
+3 11
+3 6
+1 2
+8 9
+2 5
+4 13
+4 9
+9 18
+9 15
+9 13
diff --git a/bottleneck/tests/data/test_269_A b/bottleneck/tests/data/test_269_A
new file mode 100644
index 0000000..62a1a47
--- /dev/null
+++ b/bottleneck/tests/data/test_269_A
@@ -0,0 +1,10 @@
+10 17
+10 18
+3 10
+6 8
+3 5
+5 11
+5 12
+9 13
+6 16
+2 11
diff --git a/bottleneck/tests/data/test_269_B b/bottleneck/tests/data/test_269_B
new file mode 100644
index 0000000..ecf44f6
--- /dev/null
+++ b/bottleneck/tests/data/test_269_B
@@ -0,0 +1,10 @@
+3 8
+2 9
+1 6
+8 11
+10 18
+4 12
+0 2
+0 1
+0 8
+0 4
diff --git a/bottleneck/tests/data/test_270_A b/bottleneck/tests/data/test_270_A
new file mode 100644
index 0000000..6bd9f37
--- /dev/null
+++ b/bottleneck/tests/data/test_270_A
@@ -0,0 +1,10 @@
+6 16
+3 8
+6 7
+5 10
+7 17
+1 2
+10 19
+10 18
+4 9
+9 14
diff --git a/bottleneck/tests/data/test_270_B b/bottleneck/tests/data/test_270_B
new file mode 100644
index 0000000..5e177c7
--- /dev/null
+++ b/bottleneck/tests/data/test_270_B
@@ -0,0 +1,10 @@
+8 14
+10 14
+6 7
+3 8
+9 10
+3 7
+2 3
+2 3
+10 19
+8 15
diff --git a/bottleneck/tests/data/test_271_A b/bottleneck/tests/data/test_271_A
new file mode 100644
index 0000000..12f7492
--- /dev/null
+++ b/bottleneck/tests/data/test_271_A
@@ -0,0 +1,10 @@
+0 7
+0 6
+3 10
+3 6
+1 10
+10 11
+3 13
+9 16
+9 15
+10 20
diff --git a/bottleneck/tests/data/test_271_B b/bottleneck/tests/data/test_271_B
new file mode 100644
index 0000000..1af6dd6
--- /dev/null
+++ b/bottleneck/tests/data/test_271_B
@@ -0,0 +1,10 @@
+9 10
+9 16
+10 14
+1 4
+8 14
+10 11
+9 10
+3 7
+6 14
+7 8
diff --git a/bottleneck/tests/data/test_272_A b/bottleneck/tests/data/test_272_A
new file mode 100644
index 0000000..b6b67f0
--- /dev/null
+++ b/bottleneck/tests/data/test_272_A
@@ -0,0 +1,10 @@
+9 17
+6 16
+6 8
+1 2
+7 12
+1 4
+0 9
+9 16
+8 10
+10 11
diff --git a/bottleneck/tests/data/test_272_B b/bottleneck/tests/data/test_272_B
new file mode 100644
index 0000000..9b12c0e
--- /dev/null
+++ b/bottleneck/tests/data/test_272_B
@@ -0,0 +1,10 @@
+1 11
+9 14
+8 9
+3 11
+7 15
+0 5
+0 8
+5 11
+0 1
+10 11
diff --git a/bottleneck/tests/data/test_273_A b/bottleneck/tests/data/test_273_A
new file mode 100644
index 0000000..6ae8fde
--- /dev/null
+++ b/bottleneck/tests/data/test_273_A
@@ -0,0 +1,10 @@
+2 10
+8 9
+10 19
+3 7
+4 5
+1 8
+0 5
+6 9
+0 1
+4 10
diff --git a/bottleneck/tests/data/test_273_B b/bottleneck/tests/data/test_273_B
new file mode 100644
index 0000000..42955e8
--- /dev/null
+++ b/bottleneck/tests/data/test_273_B
@@ -0,0 +1,10 @@
+9 19
+0 2
+0 1
+2 9
+7 9
+2 7
+3 6
+9 10
+2 3
+0 9
diff --git a/bottleneck/tests/data/test_274_A b/bottleneck/tests/data/test_274_A
new file mode 100644
index 0000000..78e099d
--- /dev/null
+++ b/bottleneck/tests/data/test_274_A
@@ -0,0 +1,10 @@
+0 1
+10 11
+4 6
+9 15
+9 19
+4 7
+8 17
+0 7
+7 17
+4 14
diff --git a/bottleneck/tests/data/test_274_B b/bottleneck/tests/data/test_274_B
new file mode 100644
index 0000000..59cac0c
--- /dev/null
+++ b/bottleneck/tests/data/test_274_B
@@ -0,0 +1,10 @@
+4 12
+2 7
+0 5
+3 10
+7 15
+3 8
+8 14
+8 11
+6 14
+6 16
diff --git a/bottleneck/tests/data/test_275_A b/bottleneck/tests/data/test_275_A
new file mode 100644
index 0000000..9593ad1
--- /dev/null
+++ b/bottleneck/tests/data/test_275_A
@@ -0,0 +1,10 @@
+7 13
+2 3
+10 11
+5 10
+6 11
+10 16
+5 10
+5 9
+10 18
+10 11
diff --git a/bottleneck/tests/data/test_275_B b/bottleneck/tests/data/test_275_B
new file mode 100644
index 0000000..46d793b
--- /dev/null
+++ b/bottleneck/tests/data/test_275_B
@@ -0,0 +1,10 @@
+9 19
+10 11
+8 9
+7 8
+4 8
+0 2
+4 12
+6 16
+4 9
+8 9
diff --git a/bottleneck/tests/data/test_276_A b/bottleneck/tests/data/test_276_A
new file mode 100644
index 0000000..546a9ad
--- /dev/null
+++ b/bottleneck/tests/data/test_276_A
@@ -0,0 +1,10 @@
+6 16
+2 3
+0 6
+9 18
+3 13
+1 5
+1 6
+3 4
+7 11
+0 1
diff --git a/bottleneck/tests/data/test_276_B b/bottleneck/tests/data/test_276_B
new file mode 100644
index 0000000..3b63537
--- /dev/null
+++ b/bottleneck/tests/data/test_276_B
@@ -0,0 +1,10 @@
+9 17
+8 9
+7 10
+2 10
+2 11
+2 7
+6 11
+7 12
+10 18
+4 14
diff --git a/bottleneck/tests/data/test_277_A b/bottleneck/tests/data/test_277_A
new file mode 100644
index 0000000..41ee575
--- /dev/null
+++ b/bottleneck/tests/data/test_277_A
@@ -0,0 +1,10 @@
+6 8
+6 15
+0 10
+9 10
+5 10
+4 10
+0 5
+5 9
+8 9
+2 5
diff --git a/bottleneck/tests/data/test_277_B b/bottleneck/tests/data/test_277_B
new file mode 100644
index 0000000..84ade69
--- /dev/null
+++ b/bottleneck/tests/data/test_277_B
@@ -0,0 +1,10 @@
+0 2
+4 7
+3 12
+8 13
+2 3
+9 18
+8 16
+2 3
+10 20
+4 10
diff --git a/bottleneck/tests/data/test_278_A b/bottleneck/tests/data/test_278_A
new file mode 100644
index 0000000..d2e3a7a
--- /dev/null
+++ b/bottleneck/tests/data/test_278_A
@@ -0,0 +1,10 @@
+8 10
+6 7
+9 19
+6 11
+4 6
+0 8
+5 6
+5 10
+1 10
+2 7
diff --git a/bottleneck/tests/data/test_278_B b/bottleneck/tests/data/test_278_B
new file mode 100644
index 0000000..0046a8a
--- /dev/null
+++ b/bottleneck/tests/data/test_278_B
@@ -0,0 +1,10 @@
+1 2
+0 8
+9 19
+4 13
+0 10
+7 15
+2 3
+10 17
+2 12
+10 17
diff --git a/bottleneck/tests/data/test_279_A b/bottleneck/tests/data/test_279_A
new file mode 100644
index 0000000..4e5619f
--- /dev/null
+++ b/bottleneck/tests/data/test_279_A
@@ -0,0 +1,10 @@
+5 9
+4 8
+5 7
+0 2
+8 17
+5 12
+3 5
+1 3
+3 10
+7 10
diff --git a/bottleneck/tests/data/test_279_B b/bottleneck/tests/data/test_279_B
new file mode 100644
index 0000000..7ae40fa
--- /dev/null
+++ b/bottleneck/tests/data/test_279_B
@@ -0,0 +1,10 @@
+9 11
+2 5
+5 15
+4 11
+5 11
+9 10
+2 8
+10 14
+6 16
+7 16
diff --git a/bottleneck/tests/data/test_280_A b/bottleneck/tests/data/test_280_A
new file mode 100644
index 0000000..3ac2922
--- /dev/null
+++ b/bottleneck/tests/data/test_280_A
@@ -0,0 +1,20 @@
+5 8
+10 11
+0 1
+8 18
+0 7
+2 12
+3 6
+10 20
+9 14
+4 9
+6 7
+4 13
+3 4
+10 13
+6 7
+8 17
+8 9
+5 7
+5 6
+3 11
diff --git a/bottleneck/tests/data/test_280_B b/bottleneck/tests/data/test_280_B
new file mode 100644
index 0000000..c5485cf
--- /dev/null
+++ b/bottleneck/tests/data/test_280_B
@@ -0,0 +1,20 @@
+9 16
+6 7
+4 12
+9 10
+5 12
+5 14
+1 4
+8 17
+4 14
+8 15
+6 14
+3 13
+7 17
+4 7
+0 2
+9 17
+3 4
+6 11
+0 10
+2 3
diff --git a/bottleneck/tests/data/test_281_A b/bottleneck/tests/data/test_281_A
new file mode 100644
index 0000000..e9a4644
--- /dev/null
+++ b/bottleneck/tests/data/test_281_A
@@ -0,0 +1,20 @@
+2 4
+3 4
+7 10
+9 14
+9 16
+8 10
+2 3
+0 10
+10 14
+7 14
+4 7
+4 6
+5 11
+1 7
+3 10
+7 8
+6 11
+0 1
+8 9
+7 16
diff --git a/bottleneck/tests/data/test_281_B b/bottleneck/tests/data/test_281_B
new file mode 100644
index 0000000..f219b2a
--- /dev/null
+++ b/bottleneck/tests/data/test_281_B
@@ -0,0 +1,20 @@
+5 15
+8 17
+0 5
+5 11
+7 13
+5 9
+4 7
+3 9
+6 9
+2 10
+4 9
+6 13
+8 17
+8 12
+10 15
+4 11
+3 11
+0 2
+3 8
+1 6
diff --git a/bottleneck/tests/data/test_282_A b/bottleneck/tests/data/test_282_A
new file mode 100644
index 0000000..946f3f2
--- /dev/null
+++ b/bottleneck/tests/data/test_282_A
@@ -0,0 +1,20 @@
+7 17
+1 10
+7 12
+2 12
+1 2
+2 11
+2 6
+7 10
+9 18
+2 12
+3 12
+8 9
+0 10
+5 6
+3 9
+9 13
+0 7
+6 7
+0 2
+4 13
diff --git a/bottleneck/tests/data/test_282_B b/bottleneck/tests/data/test_282_B
new file mode 100644
index 0000000..ac3c7c8
--- /dev/null
+++ b/bottleneck/tests/data/test_282_B
@@ -0,0 +1,20 @@
+0 8
+10 18
+4 11
+1 10
+4 9
+4 8
+3 9
+0 6
+9 12
+9 10
+9 15
+0 3
+2 11
+6 11
+2 8
+1 3
+8 16
+0 5
+9 18
+4 11
diff --git a/bottleneck/tests/data/test_283_A b/bottleneck/tests/data/test_283_A
new file mode 100644
index 0000000..0c4676e
--- /dev/null
+++ b/bottleneck/tests/data/test_283_A
@@ -0,0 +1,20 @@
+4 12
+6 9
+7 12
+10 16
+10 11
+1 2
+0 5
+4 7
+3 12
+4 7
+10 11
+3 5
+10 16
+6 7
+10 18
+7 8
+10 11
+4 10
+6 14
+2 4
diff --git a/bottleneck/tests/data/test_283_B b/bottleneck/tests/data/test_283_B
new file mode 100644
index 0000000..23a83e7
--- /dev/null
+++ b/bottleneck/tests/data/test_283_B
@@ -0,0 +1,20 @@
+9 16
+7 17
+2 7
+0 1
+9 17
+8 10
+8 15
+10 17
+6 12
+7 8
+1 8
+2 12
+8 9
+3 6
+6 12
+3 6
+3 5
+2 6
+10 11
+7 13
diff --git a/bottleneck/tests/data/test_284_A b/bottleneck/tests/data/test_284_A
new file mode 100644
index 0000000..4cec19a
--- /dev/null
+++ b/bottleneck/tests/data/test_284_A
@@ -0,0 +1,20 @@
+9 13
+2 11
+2 4
+6 7
+6 14
+6 13
+7 14
+0 8
+3 4
+2 9
+4 10
+4 11
+6 15
+1 3
+5 9
+4 5
+4 13
+7 11
+9 15
+7 16
diff --git a/bottleneck/tests/data/test_284_B b/bottleneck/tests/data/test_284_B
new file mode 100644
index 0000000..f09aa28
--- /dev/null
+++ b/bottleneck/tests/data/test_284_B
@@ -0,0 +1,20 @@
+9 11
+7 10
+3 5
+0 1
+5 11
+2 10
+3 5
+2 4
+7 15
+3 4
+10 13
+1 3
+8 14
+0 8
+1 11
+5 13
+0 1
+2 3
+0 6
+2 6
diff --git a/bottleneck/tests/data/test_285_A b/bottleneck/tests/data/test_285_A
new file mode 100644
index 0000000..8e27a5a
--- /dev/null
+++ b/bottleneck/tests/data/test_285_A
@@ -0,0 +1,20 @@
+7 9
+7 12
+7 16
+4 14
+1 8
+3 13
+7 15
+4 5
+10 18
+10 16
+5 6
+6 12
+3 13
+5 9
+7 15
+1 2
+10 14
+5 6
+6 12
+3 9
diff --git a/bottleneck/tests/data/test_285_B b/bottleneck/tests/data/test_285_B
new file mode 100644
index 0000000..16a8754
--- /dev/null
+++ b/bottleneck/tests/data/test_285_B
@@ -0,0 +1,20 @@
+4 5
+4 9
+10 19
+1 5
+3 9
+10 11
+0 1
+2 12
+1 8
+7 15
+5 9
+8 10
+7 10
+9 18
+4 9
+3 10
+7 15
+7 14
+2 4
+5 7
diff --git a/bottleneck/tests/data/test_286_A b/bottleneck/tests/data/test_286_A
new file mode 100644
index 0000000..f8083ac
--- /dev/null
+++ b/bottleneck/tests/data/test_286_A
@@ -0,0 +1,20 @@
+5 6
+10 11
+2 10
+0 6
+4 5
+7 8
+2 10
+4 12
+0 1
+7 15
+2 10
+10 13
+1 10
+9 14
+2 6
+2 8
+6 15
+3 4
+4 6
+2 11
diff --git a/bottleneck/tests/data/test_286_B b/bottleneck/tests/data/test_286_B
new file mode 100644
index 0000000..6ba8e74
--- /dev/null
+++ b/bottleneck/tests/data/test_286_B
@@ -0,0 +1,20 @@
+7 8
+3 4
+7 15
+10 14
+4 12
+4 8
+8 12
+4 8
+1 4
+10 12
+0 2
+0 1
+6 12
+7 11
+9 16
+3 11
+2 4
+10 14
+2 10
+6 8
diff --git a/bottleneck/tests/data/test_287_A b/bottleneck/tests/data/test_287_A
new file mode 100644
index 0000000..5dd8f38
--- /dev/null
+++ b/bottleneck/tests/data/test_287_A
@@ -0,0 +1,20 @@
+10 20
+8 9
+0 4
+6 14
+1 4
+3 7
+0 3
+10 13
+7 9
+4 6
+7 14
+3 13
+10 17
+4 13
+9 18
+2 3
+1 11
+10 16
+6 12
+4 13
diff --git a/bottleneck/tests/data/test_287_B b/bottleneck/tests/data/test_287_B
new file mode 100644
index 0000000..6fff124
--- /dev/null
+++ b/bottleneck/tests/data/test_287_B
@@ -0,0 +1,20 @@
+0 2
+6 7
+8 9
+2 10
+0 4
+7 8
+0 9
+1 4
+6 11
+0 2
+5 7
+9 18
+9 16
+5 14
+3 4
+5 14
+3 4
+6 9
+1 5
+7 10
diff --git a/bottleneck/tests/data/test_288_A b/bottleneck/tests/data/test_288_A
new file mode 100644
index 0000000..567d877
--- /dev/null
+++ b/bottleneck/tests/data/test_288_A
@@ -0,0 +1,20 @@
+8 12
+4 9
+5 14
+7 8
+4 11
+5 15
+2 10
+1 3
+0 7
+3 5
+1 3
+1 7
+8 13
+7 10
+5 6
+7 10
+3 6
+10 20
+10 17
+4 14
diff --git a/bottleneck/tests/data/test_288_B b/bottleneck/tests/data/test_288_B
new file mode 100644
index 0000000..1d50cf6
--- /dev/null
+++ b/bottleneck/tests/data/test_288_B
@@ -0,0 +1,20 @@
+6 14
+8 11
+5 13
+1 10
+9 12
+9 19
+4 14
+0 2
+8 16
+1 10
+3 9
+0 3
+2 5
+2 4
+5 8
+2 11
+3 5
+6 16
+7 11
+5 11
diff --git a/bottleneck/tests/data/test_289_A b/bottleneck/tests/data/test_289_A
new file mode 100644
index 0000000..39c74ff
--- /dev/null
+++ b/bottleneck/tests/data/test_289_A
@@ -0,0 +1,20 @@
+3 4
+5 13
+8 18
+9 18
+4 10
+2 8
+1 10
+10 17
+2 3
+10 15
+2 3
+4 6
+7 8
+7 9
+8 12
+7 9
+8 15
+6 9
+0 2
+8 17
diff --git a/bottleneck/tests/data/test_289_B b/bottleneck/tests/data/test_289_B
new file mode 100644
index 0000000..cb24888
--- /dev/null
+++ b/bottleneck/tests/data/test_289_B
@@ -0,0 +1,20 @@
+1 11
+10 18
+6 16
+7 14
+8 16
+9 11
+2 3
+8 12
+4 5
+7 14
+5 10
+7 8
+2 12
+5 9
+0 1
+10 19
+1 5
+10 20
+3 10
+9 11
diff --git a/bottleneck/tests/data/test_290_A b/bottleneck/tests/data/test_290_A
new file mode 100644
index 0000000..21e124b
--- /dev/null
+++ b/bottleneck/tests/data/test_290_A
@@ -0,0 +1,20 @@
+8 15
+6 10
+4 5
+10 20
+3 8
+0 10
+0 2
+3 9
+1 10
+3 11
+5 12
+6 7
+6 8
+3 6
+8 9
+9 15
+2 12
+8 12
+3 11
+4 9
diff --git a/bottleneck/tests/data/test_290_B b/bottleneck/tests/data/test_290_B
new file mode 100644
index 0000000..d705f0e
--- /dev/null
+++ b/bottleneck/tests/data/test_290_B
@@ -0,0 +1,20 @@
+8 10
+1 2
+5 6
+2 9
+6 15
+3 8
+6 7
+4 11
+2 3
+10 14
+3 4
+3 4
+1 2
+2 11
+2 6
+6 7
+1 4
+8 16
+4 5
+9 12
diff --git a/bottleneck/tests/data/test_291_A b/bottleneck/tests/data/test_291_A
new file mode 100644
index 0000000..0ba0226
--- /dev/null
+++ b/bottleneck/tests/data/test_291_A
@@ -0,0 +1,20 @@
+10 11
+4 5
+4 13
+4 10
+9 13
+3 4
+8 13
+9 15
+2 8
+9 16
+8 14
+8 18
+1 6
+0 8
+8 16
+5 6
+9 19
+8 15
+8 13
+8 16
diff --git a/bottleneck/tests/data/test_291_B b/bottleneck/tests/data/test_291_B
new file mode 100644
index 0000000..1c933ef
--- /dev/null
+++ b/bottleneck/tests/data/test_291_B
@@ -0,0 +1,20 @@
+2 9
+4 13
+8 13
+10 13
+8 18
+8 13
+5 14
+1 6
+5 6
+7 8
+2 12
+5 6
+6 10
+7 10
+0 6
+10 14
+2 3
+10 18
+5 12
+4 5
diff --git a/bottleneck/tests/data/test_292_A b/bottleneck/tests/data/test_292_A
new file mode 100644
index 0000000..1929d2e
--- /dev/null
+++ b/bottleneck/tests/data/test_292_A
@@ -0,0 +1,20 @@
+7 8
+5 15
+7 11
+6 15
+2 8
+8 9
+7 9
+0 2
+4 8
+2 10
+0 2
+2 4
+1 3
+6 10
+2 10
+2 9
+10 13
+7 8
+5 8
+9 11
diff --git a/bottleneck/tests/data/test_292_B b/bottleneck/tests/data/test_292_B
new file mode 100644
index 0000000..305f8b8
--- /dev/null
+++ b/bottleneck/tests/data/test_292_B
@@ -0,0 +1,20 @@
+4 6
+3 9
+8 12
+5 15
+10 12
+4 10
+4 6
+4 6
+0 8
+8 14
+7 14
+4 13
+4 10
+5 12
+10 19
+0 7
+3 10
+10 15
+0 2
+10 11
diff --git a/bottleneck/tests/data/test_293_A b/bottleneck/tests/data/test_293_A
new file mode 100644
index 0000000..752bd33
--- /dev/null
+++ b/bottleneck/tests/data/test_293_A
@@ -0,0 +1,20 @@
+8 15
+5 15
+10 11
+6 7
+10 13
+9 10
+6 8
+9 18
+0 4
+2 4
+2 9
+6 15
+0 1
+5 12
+7 12
+2 9
+3 13
+4 10
+10 16
+2 9
diff --git a/bottleneck/tests/data/test_293_B b/bottleneck/tests/data/test_293_B
new file mode 100644
index 0000000..6ce5afb
--- /dev/null
+++ b/bottleneck/tests/data/test_293_B
@@ -0,0 +1,20 @@
+2 10
+8 11
+6 16
+0 10
+2 3
+10 17
+1 2
+7 16
+3 7
+0 3
+8 9
+2 7
+7 17
+3 13
+2 7
+5 11
+6 9
+10 20
+2 4
+3 8
diff --git a/bottleneck/tests/data/test_294_A b/bottleneck/tests/data/test_294_A
new file mode 100644
index 0000000..556a43e
--- /dev/null
+++ b/bottleneck/tests/data/test_294_A
@@ -0,0 +1,20 @@
+5 13
+4 12
+6 7
+10 16
+5 14
+3 10
+2 10
+7 11
+5 15
+0 1
+4 14
+3 12
+0 8
+10 13
+0 1
+3 9
+5 6
+7 11
+4 13
+9 11
diff --git a/bottleneck/tests/data/test_294_B b/bottleneck/tests/data/test_294_B
new file mode 100644
index 0000000..5a0896c
--- /dev/null
+++ b/bottleneck/tests/data/test_294_B
@@ -0,0 +1,20 @@
+1 10
+6 16
+6 10
+4 12
+6 12
+0 6
+3 9
+3 12
+5 14
+9 17
+10 18
+3 13
+2 10
+8 9
+9 16
+8 14
+5 12
+4 6
+9 10
+7 12
diff --git a/bottleneck/tests/data/test_295_A b/bottleneck/tests/data/test_295_A
new file mode 100644
index 0000000..53b904f
--- /dev/null
+++ b/bottleneck/tests/data/test_295_A
@@ -0,0 +1,20 @@
+2 10
+10 20
+9 16
+2 9
+2 7
+7 11
+8 11
+10 12
+4 9
+4 13
+6 12
+7 8
+4 8
+7 15
+2 9
+9 11
+10 13
+9 19
+7 14
+5 13
diff --git a/bottleneck/tests/data/test_295_B b/bottleneck/tests/data/test_295_B
new file mode 100644
index 0000000..61d13ff
--- /dev/null
+++ b/bottleneck/tests/data/test_295_B
@@ -0,0 +1,20 @@
+3 13
+3 13
+8 17
+1 6
+3 9
+3 10
+5 12
+9 10
+5 7
+9 16
+2 6
+0 1
+4 8
+1 3
+5 15
+6 7
+7 10
+1 3
+5 13
+1 7
diff --git a/bottleneck/tests/data/test_296_A b/bottleneck/tests/data/test_296_A
new file mode 100644
index 0000000..444d20f
--- /dev/null
+++ b/bottleneck/tests/data/test_296_A
@@ -0,0 +1,20 @@
+0 6
+4 10
+10 13
+0 6
+1 6
+10 19
+6 13
+1 2
+5 13
+6 14
+4 12
+1 8
+6 16
+2 9
+9 11
+9 19
+1 10
+3 4
+2 11
+4 8
diff --git a/bottleneck/tests/data/test_296_B b/bottleneck/tests/data/test_296_B
new file mode 100644
index 0000000..476d729
--- /dev/null
+++ b/bottleneck/tests/data/test_296_B
@@ -0,0 +1,20 @@
+1 3
+7 9
+4 10
+10 11
+0 5
+4 12
+1 2
+7 14
+10 19
+8 9
+3 12
+1 2
+1 5
+0 1
+10 17
+9 17
+1 7
+2 5
+2 5
+4 13
diff --git a/bottleneck/tests/data/test_297_A b/bottleneck/tests/data/test_297_A
new file mode 100644
index 0000000..745d7f6
--- /dev/null
+++ b/bottleneck/tests/data/test_297_A
@@ -0,0 +1,20 @@
+6 9
+1 3
+7 10
+9 14
+9 18
+8 12
+2 3
+5 15
+8 14
+3 12
+5 6
+7 15
+6 16
+8 18
+6 13
+6 7
+3 8
+2 3
+9 13
+9 14
diff --git a/bottleneck/tests/data/test_297_B b/bottleneck/tests/data/test_297_B
new file mode 100644
index 0000000..99b1ccc
--- /dev/null
+++ b/bottleneck/tests/data/test_297_B
@@ -0,0 +1,20 @@
+4 11
+9 18
+9 11
+2 7
+2 9
+4 12
+4 13
+10 18
+8 10
+2 5
+9 15
+2 9
+10 15
+6 15
+9 12
+10 20
+9 16
+8 11
+0 1
+2 12
diff --git a/bottleneck/tests/data/test_298_A b/bottleneck/tests/data/test_298_A
new file mode 100644
index 0000000..d35fccc
--- /dev/null
+++ b/bottleneck/tests/data/test_298_A
@@ -0,0 +1,20 @@
+0 6
+9 10
+4 5
+7 13
+10 19
+7 12
+10 20
+2 6
+7 13
+7 8
+9 10
+4 8
+9 10
+7 14
+9 19
+10 16
+3 7
+2 3
+1 5
+3 4
diff --git a/bottleneck/tests/data/test_298_B b/bottleneck/tests/data/test_298_B
new file mode 100644
index 0000000..5cf0d1c
--- /dev/null
+++ b/bottleneck/tests/data/test_298_B
@@ -0,0 +1,20 @@
+4 10
+6 8
+2 3
+6 15
+9 16
+10 11
+7 13
+5 6
+2 9
+6 13
+8 14
+9 15
+10 15
+10 12
+9 18
+3 4
+6 7
+1 9
+4 10
+3 7
diff --git a/bottleneck/tests/data/test_299_A b/bottleneck/tests/data/test_299_A
new file mode 100644
index 0000000..3506828
--- /dev/null
+++ b/bottleneck/tests/data/test_299_A
@@ -0,0 +1,20 @@
+9 10
+1 6
+7 16
+9 13
+3 8
+6 11
+1 9
+5 14
+3 7
+3 10
+5 11
+1 7
+1 5
+0 6
+6 14
+8 11
+10 13
+9 17
+4 10
+9 14
diff --git a/bottleneck/tests/data/test_299_B b/bottleneck/tests/data/test_299_B
new file mode 100644
index 0000000..3600634
--- /dev/null
+++ b/bottleneck/tests/data/test_299_B
@@ -0,0 +1,20 @@
+0 9
+7 13
+8 14
+8 9
+7 17
+0 5
+1 10
+0 5
+3 4
+10 19
+6 14
+8 9
+9 14
+1 6
+9 14
+3 5
+4 5
+8 18
+10 14
+10 18
diff --git a/bottleneck/tests/data/test_300_A b/bottleneck/tests/data/test_300_A
new file mode 100644
index 0000000..2ab4a1e
--- /dev/null
+++ b/bottleneck/tests/data/test_300_A
@@ -0,0 +1,30 @@
+8 10
+1 4
+9 12
+0 1
+0 5
+2 9
+7 13
+6 7
+3 8
+2 7
+6 8
+8 12
+1 2
+0 1
+5 10
+4 5
+9 13
+8 15
+6 8
+9 17
+7 10
+8 16
+10 11
+6 8
+6 8
+5 11
+1 4
+9 13
+2 4
+2 3
diff --git a/bottleneck/tests/data/test_300_B b/bottleneck/tests/data/test_300_B
new file mode 100644
index 0000000..a54300d
--- /dev/null
+++ b/bottleneck/tests/data/test_300_B
@@ -0,0 +1,30 @@
+9 10
+9 11
+6 10
+1 3
+5 8
+7 12
+4 9
+7 11
+1 9
+6 15
+3 9
+3 10
+1 6
+8 15
+1 11
+1 2
+10 11
+6 7
+7 8
+0 3
+10 11
+3 9
+3 9
+5 6
+0 4
+6 9
+2 3
+1 2
+10 11
+4 14
diff --git a/bottleneck/tests/data/test_301_A b/bottleneck/tests/data/test_301_A
new file mode 100644
index 0000000..85f8ae5
--- /dev/null
+++ b/bottleneck/tests/data/test_301_A
@@ -0,0 +1,30 @@
+4 10
+5 9
+6 12
+0 1
+4 7
+4 6
+9 19
+4 9
+2 7
+4 13
+6 7
+4 5
+0 10
+7 8
+3 4
+8 12
+0 9
+8 14
+7 13
+8 14
+1 2
+4 5
+10 14
+4 5
+3 11
+7 12
+9 16
+0 1
+9 19
+9 15
diff --git a/bottleneck/tests/data/test_301_B b/bottleneck/tests/data/test_301_B
new file mode 100644
index 0000000..4d9ef19
--- /dev/null
+++ b/bottleneck/tests/data/test_301_B
@@ -0,0 +1,30 @@
+5 15
+2 9
+3 4
+2 12
+10 17
+0 7
+5 8
+5 7
+7 16
+2 4
+4 8
+1 4
+5 15
+1 2
+2 12
+0 10
+9 10
+2 11
+7 8
+10 19
+1 11
+10 14
+8 11
+6 7
+3 7
+8 16
+3 11
+7 13
+5 10
+8 10
diff --git a/bottleneck/tests/data/test_302_A b/bottleneck/tests/data/test_302_A
new file mode 100644
index 0000000..be0e810
--- /dev/null
+++ b/bottleneck/tests/data/test_302_A
@@ -0,0 +1,30 @@
+7 13
+9 18
+1 11
+5 11
+2 3
+5 10
+1 3
+1 9
+7 11
+5 15
+4 5
+3 5
+9 13
+5 13
+10 14
+7 8
+10 19
+4 5
+2 12
+3 7
+3 4
+8 16
+6 16
+6 7
+6 11
+0 2
+0 8
+7 17
+9 17
+0 3
diff --git a/bottleneck/tests/data/test_302_B b/bottleneck/tests/data/test_302_B
new file mode 100644
index 0000000..38806fc
--- /dev/null
+++ b/bottleneck/tests/data/test_302_B
@@ -0,0 +1,30 @@
+9 17
+3 4
+7 14
+1 6
+8 18
+2 8
+8 16
+9 19
+2 5
+10 18
+9 15
+5 13
+3 13
+7 8
+1 3
+9 10
+0 8
+6 14
+10 11
+4 14
+4 14
+4 8
+2 4
+1 9
+7 8
+6 13
+8 9
+5 11
+10 18
+7 10
diff --git a/bottleneck/tests/data/test_303_A b/bottleneck/tests/data/test_303_A
new file mode 100644
index 0000000..b277929
--- /dev/null
+++ b/bottleneck/tests/data/test_303_A
@@ -0,0 +1,30 @@
+4 10
+2 11
+1 5
+9 18
+9 16
+8 11
+9 13
+1 11
+1 11
+9 13
+6 10
+6 15
+0 2
+0 1
+6 10
+1 3
+0 6
+7 8
+3 6
+4 11
+7 14
+8 16
+6 7
+6 7
+6 11
+0 4
+7 12
+1 5
+2 8
+0 1
diff --git a/bottleneck/tests/data/test_303_B b/bottleneck/tests/data/test_303_B
new file mode 100644
index 0000000..2cff171
--- /dev/null
+++ b/bottleneck/tests/data/test_303_B
@@ -0,0 +1,30 @@
+7 8
+5 11
+8 15
+2 3
+10 11
+7 17
+0 10
+5 10
+6 8
+4 8
+7 8
+5 12
+8 15
+5 11
+4 9
+9 17
+7 13
+8 13
+6 7
+3 11
+1 6
+6 8
+1 8
+5 10
+9 19
+8 9
+7 17
+1 6
+10 13
+10 19
diff --git a/bottleneck/tests/data/test_304_A b/bottleneck/tests/data/test_304_A
new file mode 100644
index 0000000..2c3de43
--- /dev/null
+++ b/bottleneck/tests/data/test_304_A
@@ -0,0 +1,30 @@
+0 2
+8 14
+1 2
+0 8
+0 6
+4 8
+5 12
+3 4
+2 3
+0 6
+10 11
+0 4
+0 10
+9 16
+9 10
+5 6
+6 11
+8 9
+0 1
+6 13
+8 18
+4 10
+9 18
+1 6
+5 7
+1 8
+9 13
+5 12
+4 5
+7 8
diff --git a/bottleneck/tests/data/test_304_B b/bottleneck/tests/data/test_304_B
new file mode 100644
index 0000000..24402f6
--- /dev/null
+++ b/bottleneck/tests/data/test_304_B
@@ -0,0 +1,30 @@
+5 15
+2 7
+8 13
+4 5
+2 3
+6 9
+8 12
+8 12
+9 18
+10 12
+3 8
+5 9
+2 12
+9 19
+6 13
+6 12
+10 14
+0 2
+2 3
+1 10
+8 13
+10 20
+3 5
+1 8
+0 6
+2 3
+8 9
+5 6
+9 17
+6 9
diff --git a/bottleneck/tests/data/test_305_A b/bottleneck/tests/data/test_305_A
new file mode 100644
index 0000000..aa88ed8
--- /dev/null
+++ b/bottleneck/tests/data/test_305_A
@@ -0,0 +1,30 @@
+1 5
+6 7
+7 15
+4 11
+9 12
+8 10
+4 7
+10 17
+9 10
+7 15
+4 7
+8 12
+9 10
+10 15
+1 5
+4 5
+2 10
+2 3
+4 14
+8 17
+1 10
+7 10
+2 4
+6 15
+8 10
+10 20
+3 7
+2 4
+6 10
+2 5
diff --git a/bottleneck/tests/data/test_305_B b/bottleneck/tests/data/test_305_B
new file mode 100644
index 0000000..8edd827
--- /dev/null
+++ b/bottleneck/tests/data/test_305_B
@@ -0,0 +1,30 @@
+8 13
+10 11
+0 1
+8 13
+2 3
+9 10
+0 4
+3 9
+8 11
+7 12
+3 8
+8 10
+10 14
+2 4
+1 7
+7 10
+6 7
+7 17
+6 14
+0 6
+8 17
+9 14
+2 7
+0 2
+3 12
+7 16
+10 16
+9 13
+8 13
+1 2
diff --git a/bottleneck/tests/data/test_306_A b/bottleneck/tests/data/test_306_A
new file mode 100644
index 0000000..8baa725
--- /dev/null
+++ b/bottleneck/tests/data/test_306_A
@@ -0,0 +1,30 @@
+3 13
+1 8
+7 14
+5 7
+0 1
+10 17
+5 8
+4 5
+6 8
+9 10
+3 10
+9 15
+8 18
+8 14
+5 15
+8 13
+8 9
+7 13
+1 8
+7 13
+3 9
+6 12
+6 9
+2 7
+7 10
+3 9
+8 13
+5 14
+10 11
+2 6
diff --git a/bottleneck/tests/data/test_306_B b/bottleneck/tests/data/test_306_B
new file mode 100644
index 0000000..b33f874
--- /dev/null
+++ b/bottleneck/tests/data/test_306_B
@@ -0,0 +1,30 @@
+8 10
+8 12
+6 9
+9 11
+5 7
+2 12
+0 9
+10 13
+0 1
+3 13
+1 6
+0 4
+2 12
+4 10
+10 14
+4 5
+9 10
+1 6
+4 12
+4 7
+4 13
+0 5
+10 17
+3 5
+2 3
+5 6
+7 11
+10 12
+2 9
+6 8
diff --git a/bottleneck/tests/data/test_307_A b/bottleneck/tests/data/test_307_A
new file mode 100644
index 0000000..bce4bc1
--- /dev/null
+++ b/bottleneck/tests/data/test_307_A
@@ -0,0 +1,30 @@
+0 1
+9 18
+5 7
+2 7
+2 8
+10 17
+9 16
+9 16
+1 6
+7 15
+5 10
+1 2
+8 14
+0 1
+5 6
+2 8
+3 4
+5 12
+4 6
+5 12
+7 11
+8 9
+3 10
+6 13
+0 7
+0 4
+7 16
+10 16
+8 12
+6 8
diff --git a/bottleneck/tests/data/test_307_B b/bottleneck/tests/data/test_307_B
new file mode 100644
index 0000000..fd4fcb5
--- /dev/null
+++ b/bottleneck/tests/data/test_307_B
@@ -0,0 +1,30 @@
+2 5
+3 9
+0 10
+10 14
+4 9
+0 1
+1 9
+3 13
+4 5
+10 16
+5 8
+8 15
+0 5
+0 9
+9 11
+2 3
+10 20
+8 9
+7 15
+4 13
+1 9
+5 8
+7 17
+3 5
+10 16
+2 11
+4 6
+3 7
+7 15
+5 10
diff --git a/bottleneck/tests/data/test_308_A b/bottleneck/tests/data/test_308_A
new file mode 100644
index 0000000..55ab2aa
--- /dev/null
+++ b/bottleneck/tests/data/test_308_A
@@ -0,0 +1,30 @@
+3 5
+6 16
+0 3
+0 10
+6 7
+2 6
+7 12
+0 7
+6 9
+6 12
+0 4
+3 12
+2 10
+5 8
+10 16
+8 12
+0 8
+2 3
+6 12
+7 8
+0 4
+2 9
+0 8
+4 7
+10 16
+6 8
+9 14
+6 9
+0 1
+0 1
diff --git a/bottleneck/tests/data/test_308_B b/bottleneck/tests/data/test_308_B
new file mode 100644
index 0000000..cdf0c84
--- /dev/null
+++ b/bottleneck/tests/data/test_308_B
@@ -0,0 +1,30 @@
+3 11
+1 4
+0 3
+9 15
+2 8
+6 12
+3 13
+0 4
+1 5
+8 18
+6 15
+0 5
+6 16
+4 6
+3 11
+4 5
+0 1
+0 10
+4 6
+0 1
+6 7
+6 7
+8 9
+7 13
+8 15
+3 4
+1 7
+4 13
+6 16
+3 12
diff --git a/bottleneck/tests/data/test_309_A b/bottleneck/tests/data/test_309_A
new file mode 100644
index 0000000..20cee09
--- /dev/null
+++ b/bottleneck/tests/data/test_309_A
@@ -0,0 +1,30 @@
+5 15
+2 4
+5 11
+3 13
+5 15
+8 13
+1 10
+2 10
+7 8
+0 7
+9 13
+10 13
+4 14
+0 3
+10 17
+2 7
+5 15
+1 10
+9 11
+7 10
+10 15
+5 7
+0 4
+0 8
+1 2
+8 16
+3 10
+8 16
+3 4
+5 6
diff --git a/bottleneck/tests/data/test_309_B b/bottleneck/tests/data/test_309_B
new file mode 100644
index 0000000..86fe46e
--- /dev/null
+++ b/bottleneck/tests/data/test_309_B
@@ -0,0 +1,30 @@
+2 4
+9 17
+4 11
+3 9
+8 13
+6 7
+0 8
+10 15
+10 13
+7 12
+7 14
+9 10
+0 10
+6 7
+6 13
+2 4
+2 3
+6 10
+9 19
+7 17
+2 6
+3 10
+8 17
+8 13
+1 6
+6 16
+10 11
+7 9
+6 13
+9 15
diff --git a/bottleneck/tests/data/test_310_A b/bottleneck/tests/data/test_310_A
new file mode 100644
index 0000000..320f176
--- /dev/null
+++ b/bottleneck/tests/data/test_310_A
@@ -0,0 +1,30 @@
+7 12
+8 15
+10 13
+4 5
+10 12
+6 14
+5 7
+1 8
+10 19
+0 4
+0 5
+10 11
+3 12
+0 6
+8 11
+6 15
+10 16
+1 2
+8 10
+4 5
+10 17
+9 15
+7 9
+7 11
+5 11
+9 13
+0 3
+4 7
+3 4
+10 18
diff --git a/bottleneck/tests/data/test_310_B b/bottleneck/tests/data/test_310_B
new file mode 100644
index 0000000..3bcf21c
--- /dev/null
+++ b/bottleneck/tests/data/test_310_B
@@ -0,0 +1,30 @@
+8 10
+1 11
+4 8
+4 14
+3 13
+1 5
+1 9
+3 8
+0 7
+9 10
+1 4
+0 1
+7 17
+6 9
+4 6
+6 9
+2 12
+2 10
+8 14
+7 13
+1 9
+8 14
+1 6
+3 11
+5 8
+5 12
+2 10
+0 6
+4 5
+3 13
diff --git a/bottleneck/tests/data/test_311_A b/bottleneck/tests/data/test_311_A
new file mode 100644
index 0000000..d98eb28
--- /dev/null
+++ b/bottleneck/tests/data/test_311_A
@@ -0,0 +1,30 @@
+2 11
+6 10
+1 4
+2 7
+2 3
+9 15
+2 3
+9 12
+2 3
+5 15
+9 17
+2 6
+0 8
+4 7
+0 5
+0 9
+7 12
+7 12
+9 12
+6 9
+7 16
+1 2
+0 8
+4 12
+2 11
+9 13
+2 7
+5 15
+5 6
+4 10
diff --git a/bottleneck/tests/data/test_311_B b/bottleneck/tests/data/test_311_B
new file mode 100644
index 0000000..311ede4
--- /dev/null
+++ b/bottleneck/tests/data/test_311_B
@@ -0,0 +1,30 @@
+2 3
+7 15
+6 12
+10 18
+10 14
+10 11
+8 9
+1 9
+5 11
+0 1
+10 19
+8 14
+10 12
+8 13
+7 14
+3 5
+10 14
+8 17
+9 10
+7 16
+2 3
+1 7
+9 15
+8 12
+0 1
+6 11
+8 15
+8 13
+2 8
+3 12
diff --git a/bottleneck/tests/data/test_312_A b/bottleneck/tests/data/test_312_A
new file mode 100644
index 0000000..2745003
--- /dev/null
+++ b/bottleneck/tests/data/test_312_A
@@ -0,0 +1,30 @@
+7 12
+0 7
+4 14
+0 6
+10 11
+8 9
+5 14
+5 6
+9 12
+4 8
+2 3
+1 4
+8 10
+2 8
+9 13
+7 12
+10 17
+1 2
+4 8
+3 5
+7 8
+1 5
+6 7
+7 16
+6 10
+10 17
+10 20
+2 5
+4 13
+2 9
diff --git a/bottleneck/tests/data/test_312_B b/bottleneck/tests/data/test_312_B
new file mode 100644
index 0000000..4a7645b
--- /dev/null
+++ b/bottleneck/tests/data/test_312_B
@@ -0,0 +1,30 @@
+8 9
+4 10
+9 19
+5 13
+6 12
+4 6
+5 11
+5 6
+3 12
+7 10
+5 12
+7 8
+3 13
+5 14
+4 9
+6 15
+5 14
+4 13
+1 9
+5 13
+5 12
+1 10
+3 4
+7 13
+3 12
+7 11
+4 5
+7 9
+0 4
+0 9
diff --git a/bottleneck/tests/data/test_313_A b/bottleneck/tests/data/test_313_A
new file mode 100644
index 0000000..db46821
--- /dev/null
+++ b/bottleneck/tests/data/test_313_A
@@ -0,0 +1,30 @@
+8 14
+10 15
+7 16
+8 9
+1 10
+8 16
+0 10
+2 3
+4 8
+1 7
+2 6
+5 15
+0 7
+5 6
+0 9
+2 3
+5 6
+9 12
+3 7
+8 10
+10 17
+3 12
+10 13
+4 12
+2 8
+8 14
+6 10
+4 6
+0 7
+8 11
diff --git a/bottleneck/tests/data/test_313_B b/bottleneck/tests/data/test_313_B
new file mode 100644
index 0000000..d387050
--- /dev/null
+++ b/bottleneck/tests/data/test_313_B
@@ -0,0 +1,30 @@
+4 10
+4 11
+4 5
+2 8
+3 6
+1 5
+8 18
+1 4
+7 8
+5 8
+7 15
+10 18
+6 10
+9 17
+6 15
+0 7
+10 19
+8 10
+4 9
+5 14
+5 9
+4 5
+5 12
+5 9
+0 1
+7 9
+2 4
+0 7
+9 18
+8 11
diff --git a/bottleneck/tests/data/test_314_A b/bottleneck/tests/data/test_314_A
new file mode 100644
index 0000000..03ad5db
--- /dev/null
+++ b/bottleneck/tests/data/test_314_A
@@ -0,0 +1,30 @@
+10 11
+10 11
+9 12
+2 11
+8 17
+3 10
+8 10
+10 14
+5 9
+5 6
+10 11
+9 17
+10 19
+3 8
+6 15
+10 20
+0 9
+8 12
+7 13
+4 6
+9 10
+6 15
+1 9
+3 9
+10 11
+10 15
+4 9
+8 13
+9 10
+6 9
diff --git a/bottleneck/tests/data/test_314_B b/bottleneck/tests/data/test_314_B
new file mode 100644
index 0000000..eaa46d9
--- /dev/null
+++ b/bottleneck/tests/data/test_314_B
@@ -0,0 +1,30 @@
+10 20
+2 12
+8 13
+0 7
+6 7
+10 15
+10 20
+5 15
+7 8
+3 10
+5 7
+3 10
+0 4
+10 17
+4 9
+5 14
+9 16
+3 4
+6 7
+4 12
+4 10
+9 10
+0 10
+10 11
+1 6
+8 16
+7 16
+10 12
+6 13
+3 7
diff --git a/bottleneck/tests/data/test_315_A b/bottleneck/tests/data/test_315_A
new file mode 100644
index 0000000..fa49507
--- /dev/null
+++ b/bottleneck/tests/data/test_315_A
@@ -0,0 +1,30 @@
+9 16
+10 18
+6 7
+9 12
+1 5
+10 20
+9 14
+4 5
+7 13
+6 12
+1 9
+10 12
+5 8
+10 12
+7 16
+10 16
+1 9
+3 10
+1 4
+1 3
+0 6
+7 13
+1 2
+3 8
+6 13
+6 8
+3 10
+0 1
+9 18
+0 10
diff --git a/bottleneck/tests/data/test_315_B b/bottleneck/tests/data/test_315_B
new file mode 100644
index 0000000..d5390e2
--- /dev/null
+++ b/bottleneck/tests/data/test_315_B
@@ -0,0 +1,30 @@
+1 2
+2 8
+0 2
+9 18
+1 11
+3 6
+6 7
+0 1
+8 14
+6 8
+5 6
+9 17
+5 6
+7 13
+7 9
+9 10
+7 15
+9 11
+3 4
+0 3
+8 16
+0 10
+8 15
+1 11
+8 16
+1 6
+9 17
+10 19
+7 10
+7 9
diff --git a/bottleneck/tests/data/test_316_A b/bottleneck/tests/data/test_316_A
new file mode 100644
index 0000000..57ff91f
--- /dev/null
+++ b/bottleneck/tests/data/test_316_A
@@ -0,0 +1,30 @@
+6 16
+4 10
+6 10
+8 11
+1 2
+0 5
+7 16
+4 9
+9 11
+0 2
+0 7
+10 18
+3 6
+9 15
+8 15
+5 9
+7 17
+5 12
+9 19
+10 20
+1 2
+1 11
+3 4
+6 15
+10 18
+3 11
+10 19
+5 6
+1 5
+3 12
diff --git a/bottleneck/tests/data/test_316_B b/bottleneck/tests/data/test_316_B
new file mode 100644
index 0000000..407332e
--- /dev/null
+++ b/bottleneck/tests/data/test_316_B
@@ -0,0 +1,30 @@
+4 7
+10 11
+3 4
+2 12
+3 4
+8 13
+3 4
+3 11
+10 11
+9 17
+5 12
+6 14
+10 17
+8 12
+8 9
+4 6
+10 14
+4 11
+5 10
+5 14
+6 7
+0 1
+8 13
+8 12
+3 8
+0 9
+7 8
+8 13
+10 11
+3 7
diff --git a/bottleneck/tests/data/test_317_A b/bottleneck/tests/data/test_317_A
new file mode 100644
index 0000000..4b6204e
--- /dev/null
+++ b/bottleneck/tests/data/test_317_A
@@ -0,0 +1,30 @@
+5 6
+1 6
+6 10
+8 16
+7 15
+2 4
+8 17
+5 12
+0 2
+7 17
+2 11
+0 2
+8 10
+8 9
+0 8
+5 10
+2 9
+3 6
+8 9
+9 17
+4 12
+7 9
+1 11
+2 10
+9 19
+10 13
+7 10
+5 8
+5 8
+2 5
diff --git a/bottleneck/tests/data/test_317_B b/bottleneck/tests/data/test_317_B
new file mode 100644
index 0000000..b30729a
--- /dev/null
+++ b/bottleneck/tests/data/test_317_B
@@ -0,0 +1,30 @@
+4 9
+0 7
+10 11
+4 5
+2 11
+4 9
+7 17
+7 14
+10 18
+2 6
+2 8
+2 7
+1 11
+5 14
+2 3
+6 9
+2 12
+1 4
+5 6
+5 11
+8 17
+4 12
+3 8
+1 4
+9 13
+0 7
+3 9
+3 4
+5 6
+3 11
diff --git a/bottleneck/tests/data/test_318_A b/bottleneck/tests/data/test_318_A
new file mode 100644
index 0000000..2ea4ad5
--- /dev/null
+++ b/bottleneck/tests/data/test_318_A
@@ -0,0 +1,30 @@
+4 13
+0 5
+5 12
+3 8
+9 17
+6 16
+7 8
+9 14
+9 19
+6 15
+2 8
+1 2
+10 18
+5 11
+5 6
+8 10
+3 7
+1 11
+9 12
+8 9
+10 20
+2 6
+8 16
+9 19
+10 11
+7 11
+9 10
+8 18
+6 14
+2 4
diff --git a/bottleneck/tests/data/test_318_B b/bottleneck/tests/data/test_318_B
new file mode 100644
index 0000000..64fd49d
--- /dev/null
+++ b/bottleneck/tests/data/test_318_B
@@ -0,0 +1,30 @@
+10 13
+6 16
+3 11
+10 20
+1 9
+1 10
+4 5
+5 10
+10 11
+1 8
+7 9
+10 11
+4 10
+0 8
+4 13
+7 9
+7 9
+7 15
+9 17
+2 11
+0 1
+6 13
+1 2
+10 13
+10 18
+7 12
+8 15
+4 10
+5 13
+3 11
diff --git a/bottleneck/tests/data/test_319_A b/bottleneck/tests/data/test_319_A
new file mode 100644
index 0000000..f7ffeda
--- /dev/null
+++ b/bottleneck/tests/data/test_319_A
@@ -0,0 +1,30 @@
+8 12
+6 14
+2 8
+9 18
+10 16
+8 17
+5 15
+6 7
+1 7
+6 7
+7 9
+9 10
+4 9
+9 14
+6 11
+7 8
+8 14
+6 7
+5 14
+2 10
+0 1
+0 6
+4 5
+1 5
+4 13
+6 14
+5 14
+9 11
+0 7
+3 6
diff --git a/bottleneck/tests/data/test_319_B b/bottleneck/tests/data/test_319_B
new file mode 100644
index 0000000..5529fa0
--- /dev/null
+++ b/bottleneck/tests/data/test_319_B
@@ -0,0 +1,30 @@
+6 7
+5 6
+4 5
+0 4
+5 6
+9 11
+1 2
+8 16
+4 9
+8 10
+7 9
+4 5
+5 15
+0 7
+8 14
+10 15
+5 7
+1 6
+5 6
+5 11
+1 10
+0 5
+5 15
+5 10
+0 2
+10 13
+0 9
+3 9
+10 11
+1 10
diff --git a/bottleneck/tests/data/test_320_A b/bottleneck/tests/data/test_320_A
new file mode 100644
index 0000000..c7c7380
--- /dev/null
+++ b/bottleneck/tests/data/test_320_A
@@ -0,0 +1,50 @@
+5 6
+0 6
+6 10
+5 10
+0 9
+0 4
+10 11
+7 13
+0 2
+4 8
+1 2
+4 13
+8 15
+1 7
+3 4
+5 14
+0 6
+7 16
+2 12
+3 11
+0 1
+3 4
+10 16
+3 8
+0 3
+1 9
+9 14
+5 6
+1 11
+6 9
+6 12
+0 6
+9 13
+4 8
+8 10
+4 9
+7 15
+5 7
+1 2
+8 15
+5 6
+6 12
+0 7
+0 9
+5 12
+1 3
+5 7
+4 12
+7 14
+9 16
diff --git a/bottleneck/tests/data/test_320_B b/bottleneck/tests/data/test_320_B
new file mode 100644
index 0000000..2807b27
--- /dev/null
+++ b/bottleneck/tests/data/test_320_B
@@ -0,0 +1,50 @@
+9 17
+7 13
+7 14
+7 10
+7 12
+2 10
+8 9
+0 1
+0 10
+0 8
+1 4
+2 11
+4 13
+8 13
+4 11
+1 5
+5 6
+2 4
+9 17
+5 15
+5 8
+7 9
+8 14
+9 10
+5 13
+8 13
+8 17
+1 11
+4 7
+3 10
+3 8
+10 20
+7 8
+10 15
+3 5
+8 12
+1 2
+7 16
+7 17
+1 10
+2 8
+4 12
+9 15
+5 7
+4 8
+5 14
+6 15
+7 16
+2 8
+5 14
diff --git a/bottleneck/tests/data/test_321_A b/bottleneck/tests/data/test_321_A
new file mode 100644
index 0000000..b24cee9
--- /dev/null
+++ b/bottleneck/tests/data/test_321_A
@@ -0,0 +1,50 @@
+1 6
+1 7
+1 2
+4 13
+8 15
+1 10
+10 17
+7 17
+0 6
+7 15
+7 13
+9 14
+9 16
+7 12
+5 8
+6 16
+1 3
+8 13
+2 6
+2 10
+2 11
+0 1
+7 15
+4 6
+10 14
+9 10
+0 3
+9 10
+3 9
+7 10
+5 6
+8 18
+2 9
+9 17
+7 12
+9 18
+2 5
+6 8
+7 14
+9 13
+8 16
+9 19
+2 11
+9 16
+6 7
+5 6
+9 17
+8 15
+3 4
+7 14
diff --git a/bottleneck/tests/data/test_321_B b/bottleneck/tests/data/test_321_B
new file mode 100644
index 0000000..be6f00b
--- /dev/null
+++ b/bottleneck/tests/data/test_321_B
@@ -0,0 +1,50 @@
+3 8
+8 13
+10 11
+9 11
+10 18
+3 10
+5 10
+9 18
+5 11
+5 7
+9 15
+10 13
+5 7
+6 14
+10 17
+4 10
+10 12
+10 17
+6 16
+3 8
+5 13
+9 12
+9 10
+10 12
+9 14
+7 16
+7 16
+10 14
+7 14
+3 4
+3 4
+8 18
+9 14
+5 9
+2 12
+9 17
+0 7
+2 4
+10 11
+7 14
+0 8
+1 9
+5 6
+2 4
+5 8
+3 12
+3 5
+1 5
+0 6
+4 14
diff --git a/bottleneck/tests/data/test_322_A b/bottleneck/tests/data/test_322_A
new file mode 100644
index 0000000..18eed8e
--- /dev/null
+++ b/bottleneck/tests/data/test_322_A
@@ -0,0 +1,50 @@
+8 12
+6 11
+2 8
+0 2
+5 14
+6 8
+1 3
+5 9
+5 10
+6 13
+3 6
+10 14
+2 10
+8 11
+3 13
+3 8
+0 10
+0 3
+8 11
+2 12
+1 2
+10 11
+1 2
+7 16
+1 4
+8 11
+5 7
+8 17
+5 11
+3 8
+5 10
+1 4
+3 5
+4 5
+7 10
+4 13
+1 7
+0 1
+0 7
+6 16
+8 16
+4 11
+2 3
+10 13
+2 8
+7 9
+5 6
+4 10
+1 10
+0 7
diff --git a/bottleneck/tests/data/test_322_B b/bottleneck/tests/data/test_322_B
new file mode 100644
index 0000000..f829c84
--- /dev/null
+++ b/bottleneck/tests/data/test_322_B
@@ -0,0 +1,50 @@
+1 9
+1 8
+6 12
+8 18
+9 17
+5 7
+3 8
+10 11
+10 19
+8 14
+6 8
+6 13
+3 5
+7 16
+0 5
+1 10
+1 2
+0 2
+6 7
+8 17
+4 12
+0 3
+6 8
+0 6
+9 10
+10 11
+8 15
+4 7
+1 11
+7 10
+3 11
+6 16
+2 7
+8 9
+10 18
+0 5
+1 4
+10 12
+3 9
+7 8
+10 14
+7 14
+6 13
+9 16
+5 15
+0 2
+5 12
+9 10
+2 10
+6 7
diff --git a/bottleneck/tests/data/test_323_A b/bottleneck/tests/data/test_323_A
new file mode 100644
index 0000000..c452dff
--- /dev/null
+++ b/bottleneck/tests/data/test_323_A
@@ -0,0 +1,50 @@
+2 3
+8 16
+7 16
+7 8
+10 11
+2 12
+5 13
+5 14
+9 10
+7 8
+2 12
+0 9
+1 11
+6 12
+9 19
+6 12
+8 10
+7 10
+10 19
+0 2
+6 12
+2 11
+9 10
+0 9
+9 15
+4 11
+2 5
+4 10
+5 10
+0 7
+8 14
+1 4
+9 16
+1 10
+10 12
+3 10
+2 5
+2 12
+10 15
+0 7
+9 14
+7 8
+5 6
+8 18
+0 5
+0 10
+5 13
+7 11
+9 19
+4 11
diff --git a/bottleneck/tests/data/test_323_B b/bottleneck/tests/data/test_323_B
new file mode 100644
index 0000000..4a7c144
--- /dev/null
+++ b/bottleneck/tests/data/test_323_B
@@ -0,0 +1,50 @@
+3 4
+3 12
+0 3
+0 5
+2 4
+5 8
+5 10
+8 18
+6 15
+1 9
+8 15
+5 11
+8 13
+4 6
+9 18
+3 4
+10 18
+2 11
+3 10
+3 4
+9 12
+6 13
+7 15
+7 11
+6 9
+3 11
+8 11
+8 13
+9 14
+5 14
+1 7
+6 14
+0 1
+10 17
+0 3
+10 13
+0 1
+3 4
+1 7
+4 6
+7 14
+2 12
+8 10
+3 8
+8 18
+8 18
+8 14
+5 9
+10 18
+5 7
diff --git a/bottleneck/tests/data/test_324_A b/bottleneck/tests/data/test_324_A
new file mode 100644
index 0000000..330da65
--- /dev/null
+++ b/bottleneck/tests/data/test_324_A
@@ -0,0 +1,50 @@
+0 3
+8 9
+4 7
+1 5
+4 5
+5 7
+5 11
+5 9
+2 4
+9 16
+9 15
+7 13
+5 10
+3 11
+8 12
+8 14
+4 7
+6 9
+5 12
+7 11
+4 9
+8 18
+8 13
+3 9
+5 12
+3 12
+3 4
+2 3
+9 17
+0 7
+4 8
+5 13
+1 4
+1 4
+5 6
+3 12
+3 4
+8 14
+3 13
+7 10
+3 4
+9 15
+4 10
+9 17
+5 8
+2 6
+2 9
+1 3
+6 12
+0 2
diff --git a/bottleneck/tests/data/test_324_B b/bottleneck/tests/data/test_324_B
new file mode 100644
index 0000000..4fb3fef
--- /dev/null
+++ b/bottleneck/tests/data/test_324_B
@@ -0,0 +1,50 @@
+3 9
+2 3
+5 12
+1 8
+5 10
+3 5
+1 2
+6 13
+10 17
+5 14
+7 13
+2 6
+4 5
+2 12
+3 12
+4 9
+7 14
+5 7
+6 7
+4 7
+1 9
+4 13
+10 19
+2 11
+3 9
+10 16
+2 7
+3 5
+5 12
+7 14
+0 10
+4 5
+8 18
+1 5
+7 14
+4 13
+4 7
+6 9
+6 12
+2 11
+4 12
+4 5
+7 17
+8 13
+3 4
+2 6
+6 14
+5 6
+5 6
+6 13
diff --git a/bottleneck/tests/data/test_325_A b/bottleneck/tests/data/test_325_A
new file mode 100644
index 0000000..0e38bad
--- /dev/null
+++ b/bottleneck/tests/data/test_325_A
@@ -0,0 +1,50 @@
+6 9
+5 6
+7 17
+4 13
+6 12
+3 9
+3 9
+2 11
+0 3
+4 5
+6 11
+6 7
+8 12
+4 5
+10 11
+9 10
+0 3
+4 6
+0 8
+6 13
+8 12
+7 14
+0 1
+0 1
+8 9
+9 14
+10 12
+3 6
+4 5
+5 13
+10 13
+8 16
+8 16
+2 6
+3 4
+8 16
+2 6
+8 17
+7 11
+0 2
+5 12
+5 9
+5 12
+1 11
+3 10
+5 12
+5 7
+4 5
+4 6
+4 11
diff --git a/bottleneck/tests/data/test_325_B b/bottleneck/tests/data/test_325_B
new file mode 100644
index 0000000..807bb12
--- /dev/null
+++ b/bottleneck/tests/data/test_325_B
@@ -0,0 +1,50 @@
+6 12
+6 12
+5 13
+10 13
+9 16
+4 11
+9 15
+1 9
+2 3
+9 19
+5 8
+10 11
+9 15
+10 13
+9 15
+6 10
+1 5
+9 12
+5 11
+5 8
+10 19
+9 13
+2 3
+7 10
+6 8
+5 12
+7 16
+2 12
+2 6
+10 15
+0 1
+2 10
+10 11
+0 6
+6 13
+3 13
+8 12
+10 11
+10 14
+4 13
+6 13
+0 4
+9 15
+5 15
+6 13
+9 10
+10 15
+2 10
+6 16
+1 9
diff --git a/bottleneck/tests/data/test_326_A b/bottleneck/tests/data/test_326_A
new file mode 100644
index 0000000..2cb897b
--- /dev/null
+++ b/bottleneck/tests/data/test_326_A
@@ -0,0 +1,50 @@
+10 12
+3 12
+0 1
+2 7
+3 9
+6 14
+9 19
+3 7
+8 10
+1 2
+4 7
+1 4
+5 6
+10 16
+6 11
+4 9
+5 10
+5 6
+5 10
+3 6
+6 15
+3 7
+9 19
+4 6
+9 19
+4 13
+8 18
+10 12
+9 13
+1 3
+9 16
+9 10
+5 10
+6 12
+8 10
+3 9
+1 8
+7 8
+7 11
+9 13
+0 1
+9 12
+5 14
+10 13
+1 4
+0 8
+9 19
+4 11
+4 13
+7 11
diff --git a/bottleneck/tests/data/test_326_B b/bottleneck/tests/data/test_326_B
new file mode 100644
index 0000000..6b37e39
--- /dev/null
+++ b/bottleneck/tests/data/test_326_B
@@ -0,0 +1,50 @@
+1 8
+6 14
+7 9
+5 14
+8 12
+9 19
+0 5
+0 2
+9 10
+2 3
+4 9
+9 10
+9 10
+7 15
+1 4
+1 6
+9 16
+8 12
+2 9
+9 15
+7 8
+7 13
+0 1
+4 14
+7 17
+4 10
+7 12
+9 10
+5 12
+4 9
+7 8
+3 10
+10 11
+9 19
+1 2
+5 13
+6 13
+6 11
+6 8
+2 9
+5 9
+4 12
+10 18
+5 9
+9 12
+1 11
+7 8
+3 5
+7 17
+3 9
diff --git a/bottleneck/tests/data/test_327_A b/bottleneck/tests/data/test_327_A
new file mode 100644
index 0000000..0d54292
--- /dev/null
+++ b/bottleneck/tests/data/test_327_A
@@ -0,0 +1,50 @@
+8 17
+4 7
+1 11
+9 10
+4 7
+0 9
+10 13
+5 7
+2 6
+7 9
+8 9
+5 8
+4 5
+3 9
+5 13
+10 17
+1 4
+7 15
+1 6
+10 17
+3 11
+10 11
+1 6
+3 12
+5 10
+8 14
+2 11
+6 11
+9 14
+7 16
+1 9
+8 9
+0 5
+4 13
+4 5
+1 3
+10 17
+10 13
+7 11
+4 9
+7 8
+7 15
+0 10
+3 4
+2 3
+6 16
+10 18
+6 13
+9 11
+6 16
diff --git a/bottleneck/tests/data/test_327_B b/bottleneck/tests/data/test_327_B
new file mode 100644
index 0000000..548eb3f
--- /dev/null
+++ b/bottleneck/tests/data/test_327_B
@@ -0,0 +1,50 @@
+1 6
+10 11
+1 9
+6 10
+7 17
+9 11
+7 10
+6 10
+4 13
+7 17
+7 11
+3 4
+2 5
+0 8
+8 10
+7 9
+3 7
+4 12
+8 10
+4 6
+9 17
+1 2
+1 5
+6 11
+0 4
+5 8
+5 6
+7 13
+5 10
+4 5
+8 17
+10 12
+7 8
+3 13
+2 3
+3 9
+10 17
+0 1
+0 1
+9 16
+7 8
+3 4
+1 10
+4 13
+1 2
+9 10
+1 2
+5 14
+2 6
+1 5
diff --git a/bottleneck/tests/data/test_328_A b/bottleneck/tests/data/test_328_A
new file mode 100644
index 0000000..810b747
--- /dev/null
+++ b/bottleneck/tests/data/test_328_A
@@ -0,0 +1,50 @@
+2 11
+0 5
+2 6
+5 14
+1 10
+10 12
+0 1
+4 5
+1 2
+8 16
+8 9
+4 13
+2 3
+4 6
+4 14
+0 5
+5 15
+7 12
+5 8
+5 6
+10 15
+7 8
+3 9
+0 10
+4 5
+4 7
+1 9
+10 13
+0 1
+9 10
+2 9
+2 3
+8 16
+4 5
+9 11
+2 9
+7 14
+8 11
+5 8
+10 19
+4 7
+5 14
+0 5
+4 5
+2 5
+3 8
+10 20
+1 11
+4 14
+3 11
diff --git a/bottleneck/tests/data/test_328_B b/bottleneck/tests/data/test_328_B
new file mode 100644
index 0000000..e781d51
--- /dev/null
+++ b/bottleneck/tests/data/test_328_B
@@ -0,0 +1,50 @@
+3 10
+5 8
+4 10
+4 5
+4 11
+4 6
+0 5
+7 11
+6 16
+3 4
+7 14
+1 7
+10 11
+10 11
+2 3
+2 11
+9 12
+2 3
+5 6
+2 4
+2 8
+7 9
+10 14
+4 13
+2 9
+10 11
+6 13
+5 8
+1 8
+7 11
+7 8
+10 17
+9 10
+3 8
+2 4
+10 14
+4 9
+10 19
+9 11
+3 5
+10 20
+9 10
+3 6
+6 15
+6 14
+9 19
+9 11
+5 12
+3 8
+3 9
diff --git a/bottleneck/tests/data/test_329_A b/bottleneck/tests/data/test_329_A
new file mode 100644
index 0000000..b02fd14
--- /dev/null
+++ b/bottleneck/tests/data/test_329_A
@@ -0,0 +1,50 @@
+8 13
+4 13
+0 1
+6 12
+3 12
+0 1
+7 8
+4 12
+2 6
+7 11
+4 8
+3 5
+2 6
+5 12
+2 12
+1 10
+3 10
+2 3
+3 10
+3 4
+2 4
+7 8
+9 16
+3 5
+5 6
+6 11
+3 12
+2 4
+10 11
+8 11
+8 11
+2 9
+0 6
+4 7
+0 1
+2 3
+2 5
+8 16
+8 9
+2 11
+6 16
+6 12
+10 17
+6 11
+3 9
+2 9
+10 11
+9 12
+4 5
+2 6
diff --git a/bottleneck/tests/data/test_329_B b/bottleneck/tests/data/test_329_B
new file mode 100644
index 0000000..0ca3fcd
--- /dev/null
+++ b/bottleneck/tests/data/test_329_B
@@ -0,0 +1,50 @@
+0 9
+5 6
+0 5
+9 12
+10 20
+9 12
+7 14
+9 19
+2 3
+5 14
+0 4
+2 3
+8 9
+0 5
+2 5
+9 10
+3 4
+1 7
+7 13
+10 13
+2 11
+9 18
+0 5
+5 13
+1 9
+10 19
+3 5
+2 6
+0 4
+8 13
+10 11
+5 13
+0 2
+0 1
+6 16
+5 8
+8 9
+2 10
+0 3
+4 14
+8 11
+7 14
+1 2
+1 3
+3 5
+3 10
+9 17
+3 6
+3 4
+1 10
diff --git a/bottleneck/tests/data/test_330_A b/bottleneck/tests/data/test_330_A
new file mode 100644
index 0000000..4cdb2c9
--- /dev/null
+++ b/bottleneck/tests/data/test_330_A
@@ -0,0 +1,50 @@
+7 13
+2 8
+2 4
+5 15
+4 10
+9 17
+2 9
+9 12
+6 7
+6 7
+5 15
+4 5
+5 6
+4 6
+0 7
+4 7
+0 2
+8 18
+1 11
+10 11
+5 13
+3 5
+3 11
+0 1
+1 2
+10 14
+1 6
+2 3
+5 15
+3 13
+8 10
+6 15
+10 14
+3 10
+7 17
+4 14
+2 8
+10 11
+9 18
+10 15
+6 12
+4 8
+0 7
+9 11
+6 7
+1 8
+10 15
+0 6
+1 7
+7 16
diff --git a/bottleneck/tests/data/test_330_B b/bottleneck/tests/data/test_330_B
new file mode 100644
index 0000000..01f1570
--- /dev/null
+++ b/bottleneck/tests/data/test_330_B
@@ -0,0 +1,50 @@
+7 10
+4 5
+2 9
+1 2
+7 10
+4 6
+1 9
+6 16
+0 1
+9 14
+6 11
+10 16
+6 9
+0 6
+0 5
+10 12
+4 14
+7 8
+0 3
+9 18
+8 14
+4 7
+1 9
+2 5
+8 9
+9 10
+2 6
+1 11
+2 8
+4 10
+0 4
+2 9
+3 4
+0 10
+5 14
+4 12
+5 11
+4 7
+2 9
+7 16
+8 14
+8 12
+2 9
+4 11
+4 7
+0 1
+6 7
+5 6
+4 12
+2 4
diff --git a/bottleneck/tests/data/test_331_A b/bottleneck/tests/data/test_331_A
new file mode 100644
index 0000000..a271a66
--- /dev/null
+++ b/bottleneck/tests/data/test_331_A
@@ -0,0 +1,50 @@
+10 17
+0 8
+5 8
+10 11
+8 9
+10 13
+10 20
+6 7
+7 12
+0 8
+4 7
+0 10
+8 9
+1 9
+3 8
+10 12
+7 12
+9 18
+6 13
+3 9
+5 9
+6 7
+9 18
+10 17
+6 14
+4 8
+5 14
+10 17
+10 11
+7 16
+5 11
+8 10
+7 14
+6 8
+10 17
+7 8
+3 5
+0 2
+4 10
+8 9
+1 2
+3 12
+1 4
+2 6
+0 1
+0 10
+9 10
+5 6
+5 9
+10 15
diff --git a/bottleneck/tests/data/test_331_B b/bottleneck/tests/data/test_331_B
new file mode 100644
index 0000000..72a1a7b
--- /dev/null
+++ b/bottleneck/tests/data/test_331_B
@@ -0,0 +1,50 @@
+5 6
+9 13
+9 17
+8 9
+8 18
+4 14
+8 9
+6 9
+1 5
+8 15
+6 7
+0 1
+5 12
+9 15
+10 16
+2 4
+3 6
+10 14
+10 13
+3 10
+7 13
+9 13
+6 16
+2 3
+6 10
+8 12
+0 9
+2 3
+5 13
+10 12
+1 5
+5 11
+2 6
+1 10
+7 11
+4 5
+5 14
+1 10
+10 15
+3 11
+2 6
+4 10
+6 13
+1 9
+3 10
+6 15
+2 8
+8 14
+4 7
+9 14
diff --git a/bottleneck/tests/data/test_332_A b/bottleneck/tests/data/test_332_A
new file mode 100644
index 0000000..c1e999a
--- /dev/null
+++ b/bottleneck/tests/data/test_332_A
@@ -0,0 +1,50 @@
+5 13
+10 20
+4 5
+4 5
+3 13
+9 13
+6 8
+10 11
+3 8
+6 9
+4 5
+2 10
+10 17
+4 13
+8 12
+7 13
+2 4
+10 16
+3 11
+7 16
+5 6
+5 11
+3 6
+8 10
+2 3
+6 9
+1 3
+5 9
+7 16
+6 11
+4 14
+6 15
+10 18
+10 15
+1 10
+2 12
+6 14
+3 12
+0 5
+5 8
+4 14
+9 13
+7 14
+8 9
+8 17
+9 19
+6 15
+5 15
+1 8
+7 12
diff --git a/bottleneck/tests/data/test_332_B b/bottleneck/tests/data/test_332_B
new file mode 100644
index 0000000..1f4686e
--- /dev/null
+++ b/bottleneck/tests/data/test_332_B
@@ -0,0 +1,50 @@
+10 11
+5 11
+0 10
+5 9
+4 7
+10 14
+7 12
+10 19
+1 7
+4 8
+3 12
+10 20
+0 3
+4 11
+8 11
+3 13
+0 9
+6 8
+4 12
+6 9
+5 8
+9 12
+7 12
+8 14
+6 11
+0 5
+4 7
+10 19
+9 10
+10 11
+4 8
+10 14
+2 11
+10 11
+3 5
+0 6
+10 20
+9 19
+5 14
+4 11
+7 9
+9 15
+2 3
+2 4
+8 14
+10 14
+9 16
+2 7
+9 17
+7 13
diff --git a/bottleneck/tests/data/test_333_A b/bottleneck/tests/data/test_333_A
new file mode 100644
index 0000000..c1cc126
--- /dev/null
+++ b/bottleneck/tests/data/test_333_A
@@ -0,0 +1,50 @@
+7 12
+4 10
+2 5
+3 12
+8 15
+0 9
+0 6
+9 12
+6 16
+10 18
+5 13
+10 11
+2 3
+9 14
+10 19
+2 11
+9 10
+5 15
+9 19
+1 2
+7 8
+1 5
+8 10
+8 9
+2 3
+7 8
+3 4
+2 6
+0 10
+10 17
+7 16
+6 8
+1 2
+9 10
+10 19
+4 5
+4 10
+2 4
+8 11
+2 7
+2 7
+0 5
+3 7
+7 16
+5 15
+4 11
+7 16
+0 6
+7 8
+1 2
diff --git a/bottleneck/tests/data/test_333_B b/bottleneck/tests/data/test_333_B
new file mode 100644
index 0000000..fd22364
--- /dev/null
+++ b/bottleneck/tests/data/test_333_B
@@ -0,0 +1,50 @@
+0 3
+10 20
+6 13
+9 16
+3 4
+4 13
+2 3
+3 8
+5 13
+10 11
+3 5
+3 5
+7 10
+1 4
+1 2
+8 18
+0 10
+6 16
+5 8
+7 15
+4 10
+1 11
+5 9
+5 13
+1 2
+1 9
+3 8
+6 16
+7 8
+0 8
+9 15
+4 5
+10 11
+0 5
+2 5
+1 8
+10 16
+2 9
+8 14
+6 10
+9 18
+7 8
+9 16
+4 12
+10 15
+3 10
+6 10
+2 5
+4 14
+3 4
diff --git a/bottleneck/tests/data/test_334_A b/bottleneck/tests/data/test_334_A
new file mode 100644
index 0000000..914d6c3
--- /dev/null
+++ b/bottleneck/tests/data/test_334_A
@@ -0,0 +1,50 @@
+8 13
+10 20
+2 3
+7 15
+9 17
+2 12
+5 6
+2 5
+6 13
+10 20
+3 8
+1 9
+3 13
+10 11
+1 5
+7 11
+5 15
+5 6
+9 11
+3 5
+3 8
+6 16
+8 12
+4 7
+0 4
+8 12
+5 15
+9 14
+5 6
+3 4
+1 8
+2 7
+4 7
+8 18
+3 9
+0 5
+0 10
+8 10
+8 14
+3 13
+3 9
+9 17
+5 15
+7 16
+1 9
+0 2
+1 9
+9 12
+5 13
+9 19
diff --git a/bottleneck/tests/data/test_334_B b/bottleneck/tests/data/test_334_B
new file mode 100644
index 0000000..27524b9
--- /dev/null
+++ b/bottleneck/tests/data/test_334_B
@@ -0,0 +1,50 @@
+10 11
+9 14
+2 11
+10 17
+9 15
+4 9
+7 16
+9 12
+8 12
+7 11
+6 16
+3 12
+0 4
+9 15
+3 10
+2 9
+2 3
+6 7
+3 9
+5 8
+6 8
+4 5
+9 14
+6 10
+1 10
+10 12
+8 10
+7 12
+3 9
+4 9
+4 11
+5 10
+9 11
+7 8
+6 16
+8 17
+9 14
+4 14
+2 4
+1 2
+9 11
+7 13
+9 10
+2 9
+2 12
+2 4
+9 16
+7 17
+3 11
+8 9
diff --git a/bottleneck/tests/data/test_335_A b/bottleneck/tests/data/test_335_A
new file mode 100644
index 0000000..1a400bc
--- /dev/null
+++ b/bottleneck/tests/data/test_335_A
@@ -0,0 +1,50 @@
+0 2
+6 11
+7 11
+7 12
+7 11
+9 10
+6 14
+4 5
+5 7
+7 16
+2 3
+10 15
+10 19
+9 16
+6 15
+7 14
+8 18
+7 15
+8 14
+10 11
+10 11
+5 9
+0 10
+9 11
+9 19
+0 6
+2 10
+8 15
+1 7
+5 12
+3 4
+1 6
+0 2
+9 16
+9 19
+10 16
+6 9
+1 9
+6 7
+9 10
+8 14
+4 8
+9 10
+1 10
+5 6
+9 11
+7 16
+0 9
+7 13
+7 9
diff --git a/bottleneck/tests/data/test_335_B b/bottleneck/tests/data/test_335_B
new file mode 100644
index 0000000..93c3211
--- /dev/null
+++ b/bottleneck/tests/data/test_335_B
@@ -0,0 +1,50 @@
+8 14
+9 15
+6 11
+4 14
+2 3
+7 13
+5 11
+8 14
+1 8
+9 12
+0 10
+3 5
+10 11
+0 2
+5 13
+6 12
+8 11
+4 10
+5 14
+6 15
+9 19
+4 6
+4 5
+9 16
+5 9
+5 6
+7 14
+9 11
+9 18
+1 9
+1 4
+6 12
+2 10
+8 14
+1 11
+2 4
+9 16
+3 9
+2 11
+7 12
+6 9
+0 8
+9 17
+9 15
+10 12
+0 7
+6 9
+8 13
+10 18
+6 15
diff --git a/bottleneck/tests/data/test_336_A b/bottleneck/tests/data/test_336_A
new file mode 100644
index 0000000..5410dc3
--- /dev/null
+++ b/bottleneck/tests/data/test_336_A
@@ -0,0 +1,50 @@
+4 7
+9 16
+2 5
+0 8
+0 9
+10 11
+7 11
+2 3
+6 13
+6 9
+2 8
+7 16
+2 6
+5 14
+6 9
+7 17
+1 8
+0 4
+7 13
+9 13
+10 16
+0 2
+7 16
+8 17
+7 11
+6 7
+2 12
+5 12
+9 17
+6 7
+1 5
+9 12
+7 10
+6 11
+7 16
+6 11
+6 7
+2 6
+1 8
+10 14
+5 6
+2 7
+5 6
+2 11
+8 10
+6 10
+3 12
+3 11
+8 12
+8 10
diff --git a/bottleneck/tests/data/test_336_B b/bottleneck/tests/data/test_336_B
new file mode 100644
index 0000000..8b60a46
--- /dev/null
+++ b/bottleneck/tests/data/test_336_B
@@ -0,0 +1,50 @@
+6 15
+8 10
+0 10
+5 10
+1 10
+8 17
+2 9
+7 9
+9 12
+7 8
+8 9
+7 8
+4 14
+10 17
+3 8
+2 7
+1 10
+6 13
+9 16
+6 13
+2 4
+4 12
+2 3
+3 10
+6 13
+6 11
+6 13
+9 17
+4 5
+0 1
+5 6
+0 7
+1 8
+5 9
+0 7
+0 3
+8 10
+4 6
+10 16
+1 9
+1 10
+7 12
+1 3
+6 10
+5 6
+9 10
+6 7
+5 7
+8 12
+0 9
diff --git a/bottleneck/tests/data/test_337_A b/bottleneck/tests/data/test_337_A
new file mode 100644
index 0000000..652b5f1
--- /dev/null
+++ b/bottleneck/tests/data/test_337_A
@@ -0,0 +1,50 @@
+3 5
+1 2
+6 14
+10 18
+3 10
+1 11
+1 7
+2 11
+1 2
+0 7
+2 8
+9 14
+8 10
+1 3
+5 11
+7 8
+6 14
+8 17
+2 10
+7 15
+0 2
+4 12
+10 18
+10 11
+2 6
+3 9
+0 4
+5 15
+4 10
+8 14
+5 12
+10 11
+9 16
+9 14
+3 4
+3 5
+1 10
+3 4
+10 11
+1 6
+6 10
+1 8
+9 10
+1 6
+5 6
+5 6
+3 13
+10 19
+5 9
+4 12
diff --git a/bottleneck/tests/data/test_337_B b/bottleneck/tests/data/test_337_B
new file mode 100644
index 0000000..eba21bc
--- /dev/null
+++ b/bottleneck/tests/data/test_337_B
@@ -0,0 +1,50 @@
+0 7
+2 4
+5 14
+7 8
+10 18
+4 13
+2 9
+8 16
+1 9
+5 9
+6 13
+0 1
+10 17
+4 9
+8 15
+1 9
+9 17
+5 14
+7 14
+5 12
+9 18
+8 15
+3 12
+7 17
+1 4
+5 7
+5 15
+3 6
+2 5
+1 2
+4 6
+6 15
+3 7
+4 5
+1 9
+7 8
+10 14
+9 18
+9 13
+9 11
+2 6
+8 10
+2 8
+0 9
+0 10
+1 5
+0 1
+6 9
+6 10
+0 3
diff --git a/bottleneck/tests/data/test_338_A b/bottleneck/tests/data/test_338_A
new file mode 100644
index 0000000..567256f
--- /dev/null
+++ b/bottleneck/tests/data/test_338_A
@@ -0,0 +1,50 @@
+9 16
+3 6
+8 18
+7 15
+5 7
+8 14
+2 6
+10 12
+1 5
+5 8
+2 11
+1 3
+7 15
+5 13
+10 16
+1 11
+4 6
+7 8
+4 5
+5 11
+7 12
+6 12
+7 15
+8 16
+4 14
+1 6
+4 13
+3 12
+0 1
+3 6
+4 5
+4 11
+8 9
+0 7
+2 10
+9 17
+1 11
+5 9
+1 8
+10 11
+1 7
+6 8
+7 16
+1 4
+10 17
+2 8
+6 10
+10 14
+1 11
+5 15
diff --git a/bottleneck/tests/data/test_338_B b/bottleneck/tests/data/test_338_B
new file mode 100644
index 0000000..82c3d80
--- /dev/null
+++ b/bottleneck/tests/data/test_338_B
@@ -0,0 +1,50 @@
+1 2
+10 14
+5 6
+8 17
+9 17
+1 6
+4 10
+3 13
+7 15
+5 6
+8 10
+2 5
+3 13
+5 15
+2 4
+8 10
+2 9
+1 3
+6 12
+3 6
+2 12
+2 10
+3 11
+0 2
+4 12
+7 12
+3 5
+6 7
+9 17
+8 9
+3 12
+10 20
+2 10
+3 5
+2 11
+7 17
+3 12
+2 6
+9 11
+4 12
+0 8
+9 11
+1 4
+2 7
+7 16
+0 8
+4 13
+4 5
+8 14
+8 11
diff --git a/bottleneck/tests/data/test_339_A b/bottleneck/tests/data/test_339_A
new file mode 100644
index 0000000..9148a9c
--- /dev/null
+++ b/bottleneck/tests/data/test_339_A
@@ -0,0 +1,50 @@
+3 4
+10 13
+6 8
+8 10
+2 3
+3 6
+10 19
+6 14
+6 9
+0 8
+5 7
+10 15
+9 17
+2 3
+9 14
+6 14
+1 11
+4 9
+2 3
+9 16
+6 11
+3 8
+6 9
+10 12
+1 3
+3 13
+7 14
+4 9
+8 11
+7 9
+1 2
+9 11
+8 17
+0 2
+9 19
+5 14
+6 8
+10 14
+7 13
+0 10
+4 5
+0 9
+2 9
+0 5
+9 15
+3 9
+3 7
+7 16
+1 2
+10 18
diff --git a/bottleneck/tests/data/test_339_B b/bottleneck/tests/data/test_339_B
new file mode 100644
index 0000000..385967f
--- /dev/null
+++ b/bottleneck/tests/data/test_339_B
@@ -0,0 +1,50 @@
+2 9
+3 4
+1 5
+8 12
+8 12
+5 14
+4 9
+4 10
+5 8
+3 8
+9 10
+0 3
+1 10
+0 7
+6 13
+4 7
+10 20
+7 8
+5 8
+9 18
+1 6
+5 8
+4 8
+7 12
+7 17
+10 18
+9 10
+8 16
+8 13
+7 16
+9 18
+0 1
+7 8
+3 13
+3 4
+1 8
+6 14
+5 14
+3 6
+6 9
+7 15
+5 13
+6 15
+2 12
+9 19
+7 15
+0 4
+3 12
+9 11
+10 11
diff --git a/bottleneck/tests/data/test_340_A b/bottleneck/tests/data/test_340_A
new file mode 100644
index 0000000..4af25b1
--- /dev/null
+++ b/bottleneck/tests/data/test_340_A
@@ -0,0 +1,100 @@
+0 5
+10 19
+1 4
+6 9
+1 6
+3 11
+4 10
+9 12
+1 10
+7 12
+8 11
+3 4
+8 18
+9 15
+0 2
+9 12
+1 6
+0 8
+4 5
+2 10
+0 2
+4 10
+6 7
+7 13
+2 3
+0 9
+5 6
+0 10
+5 7
+6 15
+9 15
+1 2
+2 3
+9 14
+8 18
+4 10
+7 15
+5 8
+3 11
+10 14
+4 12
+8 13
+8 17
+2 4
+0 9
+10 19
+3 4
+0 5
+8 15
+1 9
+8 11
+9 16
+0 1
+3 6
+4 6
+2 9
+3 9
+5 11
+1 8
+6 12
+10 19
+5 6
+3 12
+0 2
+9 17
+0 3
+0 4
+10 20
+8 14
+2 10
+3 7
+7 12
+2 4
+8 9
+1 7
+3 13
+1 5
+6 7
+10 13
+9 10
+6 15
+9 11
+0 10
+6 8
+8 9
+5 9
+10 16
+5 11
+7 13
+2 6
+2 3
+5 7
+4 10
+9 19
+7 10
+1 8
+2 9
+10 13
+10 12
+7 11
diff --git a/bottleneck/tests/data/test_340_B b/bottleneck/tests/data/test_340_B
new file mode 100644
index 0000000..0e3fa2a
--- /dev/null
+++ b/bottleneck/tests/data/test_340_B
@@ -0,0 +1,100 @@
+7 11
+8 16
+1 4
+8 12
+9 19
+2 5
+2 8
+2 9
+0 4
+1 9
+5 7
+5 9
+10 14
+1 9
+3 10
+0 8
+10 11
+2 10
+2 11
+9 15
+0 1
+0 10
+3 10
+5 12
+5 12
+1 2
+7 12
+0 1
+1 4
+6 15
+1 5
+9 13
+9 17
+9 19
+8 9
+4 6
+1 10
+5 9
+2 3
+7 8
+1 5
+1 4
+8 9
+6 14
+2 9
+1 8
+4 10
+8 10
+1 11
+7 10
+8 13
+5 9
+9 19
+8 9
+3 6
+10 11
+7 8
+3 8
+6 9
+4 12
+10 19
+5 8
+1 9
+8 13
+2 4
+1 8
+7 16
+3 9
+0 3
+1 4
+8 17
+8 9
+5 12
+9 19
+2 8
+0 1
+1 2
+6 10
+1 7
+7 15
+4 8
+2 5
+3 13
+4 7
+9 12
+8 15
+10 12
+9 12
+5 13
+6 15
+1 3
+4 9
+9 16
+7 8
+2 12
+10 19
+1 9
+2 5
+5 6
+9 12
diff --git a/bottleneck/tests/data/test_341_A b/bottleneck/tests/data/test_341_A
new file mode 100644
index 0000000..932688b
--- /dev/null
+++ b/bottleneck/tests/data/test_341_A
@@ -0,0 +1,100 @@
+6 15
+6 7
+3 11
+8 15
+2 10
+10 13
+6 16
+9 10
+8 15
+3 12
+10 14
+1 8
+8 17
+1 8
+4 10
+7 12
+1 10
+7 10
+8 18
+3 5
+1 3
+1 6
+0 3
+10 19
+8 18
+4 7
+1 3
+2 8
+1 10
+4 13
+10 13
+10 17
+0 4
+6 12
+4 5
+3 8
+2 4
+4 10
+5 11
+9 14
+5 15
+2 11
+4 12
+5 11
+7 16
+5 7
+4 7
+6 7
+2 6
+3 12
+10 15
+7 12
+1 9
+0 1
+5 8
+1 8
+5 12
+1 3
+2 3
+4 10
+2 10
+10 19
+2 3
+4 13
+10 14
+3 4
+0 10
+5 7
+10 11
+8 11
+6 11
+7 17
+3 4
+0 6
+9 11
+3 12
+5 12
+9 10
+6 8
+4 11
+3 7
+2 6
+9 10
+8 18
+10 11
+2 9
+4 9
+4 13
+0 5
+10 17
+5 6
+6 16
+0 3
+0 8
+5 15
+5 12
+3 10
+8 11
+10 17
+4 6
diff --git a/bottleneck/tests/data/test_341_B b/bottleneck/tests/data/test_341_B
new file mode 100644
index 0000000..68cc4b9
--- /dev/null
+++ b/bottleneck/tests/data/test_341_B
@@ -0,0 +1,100 @@
+9 15
+10 18
+2 5
+5 7
+3 13
+6 13
+0 1
+2 12
+2 11
+3 4
+3 5
+1 9
+4 7
+10 12
+3 8
+9 17
+10 20
+5 7
+3 5
+9 18
+9 12
+3 5
+0 7
+1 2
+6 14
+7 8
+0 2
+3 11
+10 18
+7 10
+0 4
+10 11
+6 12
+8 16
+7 17
+0 8
+0 10
+9 16
+8 15
+5 6
+5 10
+4 8
+4 10
+1 11
+6 7
+6 9
+1 10
+3 5
+10 20
+10 11
+2 8
+10 13
+9 14
+8 11
+10 11
+7 16
+8 10
+8 17
+5 14
+0 7
+7 8
+4 8
+6 14
+2 5
+10 15
+2 10
+2 4
+8 13
+6 14
+2 3
+7 8
+8 13
+4 8
+1 6
+1 9
+0 1
+7 14
+10 11
+2 7
+5 15
+0 4
+1 7
+0 6
+6 13
+6 15
+1 2
+2 4
+8 9
+0 1
+3 4
+8 9
+9 11
+9 16
+8 17
+1 3
+8 10
+8 9
+8 15
+1 3
+7 16
diff --git a/bottleneck/tests/data/test_342_A b/bottleneck/tests/data/test_342_A
new file mode 100644
index 0000000..04cdc19
--- /dev/null
+++ b/bottleneck/tests/data/test_342_A
@@ -0,0 +1,100 @@
+4 8
+4 5
+1 9
+4 13
+2 10
+7 15
+6 7
+8 17
+1 8
+6 7
+9 19
+8 12
+10 18
+5 7
+8 13
+9 12
+9 14
+1 2
+7 11
+9 11
+6 15
+2 12
+6 10
+0 7
+1 10
+2 5
+8 11
+3 13
+3 11
+3 10
+6 14
+1 10
+4 6
+3 13
+5 10
+3 9
+9 16
+3 4
+0 2
+9 10
+10 16
+5 12
+6 11
+4 7
+9 18
+10 16
+5 7
+6 12
+0 7
+5 9
+8 18
+4 7
+2 6
+8 17
+7 10
+7 10
+6 11
+8 9
+3 7
+8 16
+4 9
+6 12
+0 6
+4 12
+10 15
+10 17
+10 20
+3 11
+2 12
+0 9
+3 12
+4 5
+5 7
+3 7
+0 4
+5 9
+1 7
+6 13
+9 13
+8 9
+0 6
+3 10
+1 11
+0 2
+0 6
+3 9
+2 7
+4 7
+8 14
+2 7
+2 4
+4 7
+1 7
+10 13
+6 16
+5 15
+7 17
+7 10
+3 5
+7 10
diff --git a/bottleneck/tests/data/test_342_B b/bottleneck/tests/data/test_342_B
new file mode 100644
index 0000000..e6aae99
--- /dev/null
+++ b/bottleneck/tests/data/test_342_B
@@ -0,0 +1,100 @@
+9 16
+6 15
+1 4
+0 1
+3 5
+2 3
+10 20
+3 7
+0 10
+3 13
+7 8
+4 6
+7 14
+8 9
+8 14
+10 20
+1 9
+4 14
+4 5
+2 6
+6 8
+1 10
+7 14
+8 10
+4 8
+7 8
+7 12
+6 16
+6 7
+9 19
+8 12
+1 9
+1 3
+10 16
+3 6
+2 8
+0 2
+7 15
+2 3
+8 13
+5 8
+1 2
+10 11
+4 11
+5 12
+10 15
+7 8
+2 5
+6 13
+8 17
+8 14
+4 8
+6 11
+5 6
+0 7
+0 5
+8 13
+1 2
+6 11
+6 11
+8 9
+4 5
+4 8
+0 5
+3 9
+1 3
+8 9
+10 16
+8 17
+8 17
+3 4
+3 5
+8 12
+9 10
+9 10
+8 14
+3 10
+5 9
+1 4
+9 19
+0 2
+7 8
+6 8
+7 12
+6 12
+0 1
+9 11
+3 11
+5 6
+0 8
+2 4
+1 7
+3 4
+0 3
+9 17
+2 9
+1 6
+2 6
+7 15
+1 4
diff --git a/bottleneck/tests/data/test_343_A b/bottleneck/tests/data/test_343_A
new file mode 100644
index 0000000..9759369
--- /dev/null
+++ b/bottleneck/tests/data/test_343_A
@@ -0,0 +1,100 @@
+5 13
+5 9
+2 3
+6 14
+1 2
+3 6
+1 3
+9 14
+0 6
+1 8
+9 10
+4 5
+10 19
+6 13
+7 8
+10 16
+6 7
+10 18
+8 11
+2 8
+8 9
+5 10
+1 2
+10 14
+10 12
+8 17
+7 12
+9 12
+1 5
+2 4
+8 13
+2 11
+0 5
+4 8
+2 12
+2 10
+6 15
+1 2
+8 11
+8 18
+8 9
+7 9
+5 7
+0 10
+4 10
+5 13
+8 16
+5 11
+8 16
+7 9
+2 11
+8 12
+8 10
+9 16
+7 8
+5 15
+0 1
+6 7
+7 8
+6 7
+7 13
+9 16
+9 15
+3 11
+4 10
+2 10
+3 13
+0 1
+7 10
+9 10
+8 10
+3 4
+1 4
+1 6
+4 7
+4 10
+6 11
+10 13
+7 10
+9 14
+9 15
+7 9
+3 10
+6 8
+5 15
+8 11
+7 14
+8 18
+9 13
+9 15
+10 17
+3 13
+5 7
+8 16
+4 12
+9 10
+6 12
+1 9
+0 6
+5 11
diff --git a/bottleneck/tests/data/test_343_B b/bottleneck/tests/data/test_343_B
new file mode 100644
index 0000000..e338ab2
--- /dev/null
+++ b/bottleneck/tests/data/test_343_B
@@ -0,0 +1,100 @@
+2 12
+5 9
+5 6
+10 19
+2 6
+6 14
+8 18
+6 9
+2 10
+5 7
+0 6
+7 10
+7 14
+10 15
+10 16
+6 16
+7 16
+3 8
+2 4
+2 11
+10 19
+7 15
+8 9
+7 11
+10 20
+9 11
+3 6
+6 15
+5 14
+2 3
+1 3
+5 11
+3 8
+2 9
+1 3
+10 20
+6 11
+0 9
+6 9
+0 5
+9 10
+2 7
+8 14
+9 19
+2 7
+10 11
+0 6
+4 7
+10 16
+9 12
+7 16
+5 12
+1 8
+4 12
+1 2
+1 8
+9 13
+9 14
+8 9
+4 9
+4 11
+9 19
+5 15
+2 3
+9 10
+8 15
+7 8
+9 10
+5 12
+2 12
+0 1
+3 4
+3 5
+5 14
+10 18
+3 10
+0 1
+9 10
+4 6
+10 18
+9 17
+6 7
+8 15
+3 11
+7 8
+6 12
+5 11
+0 10
+5 8
+6 15
+6 13
+0 4
+4 13
+6 9
+0 1
+0 1
+3 10
+8 17
+0 8
+9 18
diff --git a/bottleneck/tests/data/test_344_A b/bottleneck/tests/data/test_344_A
new file mode 100644
index 0000000..e8e81ab
--- /dev/null
+++ b/bottleneck/tests/data/test_344_A
@@ -0,0 +1,100 @@
+2 11
+2 7
+2 7
+1 11
+2 6
+0 9
+2 8
+2 12
+0 9
+5 10
+6 10
+2 4
+9 19
+0 6
+0 6
+9 18
+6 7
+3 13
+3 9
+1 4
+1 9
+1 11
+9 19
+8 9
+7 13
+5 13
+10 14
+10 12
+1 3
+10 17
+2 4
+8 9
+8 18
+7 15
+3 13
+10 19
+0 2
+0 10
+2 7
+5 6
+9 14
+0 4
+7 14
+10 11
+3 5
+0 2
+8 18
+4 5
+10 16
+9 18
+6 16
+4 8
+3 4
+2 7
+4 14
+4 10
+4 10
+10 14
+8 9
+7 16
+1 7
+4 14
+6 7
+3 4
+9 10
+2 3
+7 13
+10 13
+10 14
+3 8
+0 6
+3 4
+1 10
+6 12
+4 6
+3 9
+3 9
+5 11
+10 13
+2 5
+9 16
+4 14
+3 5
+0 1
+10 19
+9 16
+10 14
+0 4
+1 3
+6 8
+7 14
+1 11
+0 6
+1 5
+8 9
+8 11
+7 16
+10 11
+1 7
+2 12
diff --git a/bottleneck/tests/data/test_344_B b/bottleneck/tests/data/test_344_B
new file mode 100644
index 0000000..af72be5
--- /dev/null
+++ b/bottleneck/tests/data/test_344_B
@@ -0,0 +1,100 @@
+10 11
+8 9
+3 12
+2 10
+1 6
+4 8
+8 11
+7 17
+8 18
+9 10
+5 6
+2 9
+8 10
+1 8
+3 13
+5 12
+8 14
+7 14
+2 12
+10 15
+0 7
+7 8
+8 17
+8 10
+4 8
+6 7
+6 8
+2 3
+5 15
+2 11
+10 18
+6 13
+1 2
+6 16
+2 8
+8 11
+9 18
+8 14
+6 16
+10 20
+8 9
+0 7
+1 5
+7 16
+10 17
+1 2
+2 5
+2 6
+3 4
+7 9
+5 8
+5 7
+5 7
+1 11
+7 10
+7 17
+7 14
+5 7
+10 20
+0 2
+5 9
+0 1
+4 12
+5 6
+5 6
+2 9
+0 10
+10 11
+2 7
+8 9
+5 6
+0 2
+4 10
+6 13
+5 15
+9 11
+3 9
+6 10
+0 4
+6 9
+6 16
+10 15
+6 16
+0 8
+4 12
+10 15
+6 11
+8 11
+8 9
+3 12
+4 11
+5 11
+10 14
+9 14
+3 12
+7 8
+2 7
+8 12
+8 9
+4 12
diff --git a/bottleneck/tests/data/test_345_A b/bottleneck/tests/data/test_345_A
new file mode 100644
index 0000000..584e4ed
--- /dev/null
+++ b/bottleneck/tests/data/test_345_A
@@ -0,0 +1,100 @@
+2 6
+6 16
+7 11
+0 4
+4 5
+3 9
+9 10
+6 12
+1 3
+9 16
+6 15
+10 14
+4 6
+6 7
+1 7
+2 8
+3 10
+9 10
+0 10
+0 1
+10 11
+3 8
+4 10
+9 15
+6 9
+0 3
+1 7
+1 3
+4 5
+8 12
+2 3
+6 14
+8 14
+1 9
+10 17
+4 5
+3 7
+9 10
+4 7
+7 12
+10 11
+6 11
+0 7
+6 8
+5 15
+1 5
+7 11
+5 7
+10 11
+9 14
+0 3
+8 12
+10 20
+0 10
+5 14
+5 8
+9 10
+3 12
+0 8
+1 11
+3 6
+3 5
+10 14
+3 12
+5 9
+5 13
+6 16
+7 15
+9 17
+7 12
+1 10
+7 10
+6 8
+3 12
+4 12
+5 9
+1 7
+7 16
+8 10
+1 11
+2 11
+4 10
+7 8
+5 15
+2 5
+3 10
+8 12
+9 12
+2 3
+0 3
+10 12
+0 10
+10 14
+4 6
+10 11
+8 17
+6 8
+10 16
+9 18
+5 7
diff --git a/bottleneck/tests/data/test_345_B b/bottleneck/tests/data/test_345_B
new file mode 100644
index 0000000..8c3e758
--- /dev/null
+++ b/bottleneck/tests/data/test_345_B
@@ -0,0 +1,100 @@
+2 5
+8 13
+1 3
+4 13
+3 12
+1 9
+8 14
+4 13
+9 14
+8 14
+7 16
+8 14
+7 8
+0 9
+3 12
+9 14
+9 10
+2 3
+3 6
+6 15
+9 15
+6 12
+0 6
+9 12
+4 9
+5 14
+9 13
+8 9
+5 15
+2 7
+8 10
+0 2
+7 11
+5 10
+7 15
+5 6
+1 8
+7 9
+9 15
+3 10
+1 2
+3 6
+0 5
+6 16
+2 8
+9 10
+4 11
+2 3
+4 8
+5 11
+9 15
+2 7
+5 14
+10 18
+1 3
+9 14
+10 16
+3 8
+9 14
+1 3
+9 13
+2 7
+1 2
+7 13
+1 8
+2 5
+4 5
+3 5
+1 2
+10 13
+6 16
+10 15
+1 7
+10 12
+0 10
+7 12
+9 14
+4 5
+4 5
+6 9
+9 19
+5 12
+9 10
+9 19
+10 18
+8 11
+7 17
+0 3
+3 13
+3 11
+4 8
+6 11
+1 6
+0 9
+9 12
+8 13
+1 10
+7 13
+6 12
+4 8
diff --git a/bottleneck/tests/data/test_346_A b/bottleneck/tests/data/test_346_A
new file mode 100644
index 0000000..ab26e2f
--- /dev/null
+++ b/bottleneck/tests/data/test_346_A
@@ -0,0 +1,100 @@
+10 11
+1 11
+1 9
+0 5
+1 3
+10 18
+0 5
+4 5
+1 8
+8 16
+5 6
+9 13
+6 13
+4 5
+7 14
+8 9
+4 5
+9 11
+6 9
+9 18
+10 15
+8 15
+10 12
+3 7
+10 14
+3 9
+10 12
+3 9
+0 10
+5 8
+7 17
+8 11
+6 7
+10 17
+0 8
+0 1
+0 9
+8 10
+7 15
+8 17
+0 4
+0 3
+10 11
+7 10
+4 13
+4 9
+3 4
+4 5
+4 12
+4 11
+5 11
+3 4
+10 16
+0 2
+0 6
+8 10
+9 11
+7 15
+7 9
+5 11
+9 15
+7 8
+7 16
+4 14
+2 3
+5 8
+2 3
+9 15
+8 15
+6 15
+1 6
+2 5
+4 13
+6 12
+7 8
+0 2
+8 14
+4 9
+10 11
+10 16
+3 10
+7 16
+9 13
+1 2
+7 12
+3 5
+5 6
+4 12
+9 11
+6 7
+2 8
+9 10
+7 8
+0 6
+1 2
+5 9
+3 10
+3 13
+2 9
+2 9
diff --git a/bottleneck/tests/data/test_346_B b/bottleneck/tests/data/test_346_B
new file mode 100644
index 0000000..5e30972
--- /dev/null
+++ b/bottleneck/tests/data/test_346_B
@@ -0,0 +1,100 @@
+8 15
+1 8
+10 15
+8 13
+9 16
+3 13
+3 5
+1 8
+8 16
+6 12
+7 16
+4 14
+3 9
+0 8
+9 18
+4 14
+1 10
+6 12
+4 5
+10 14
+3 6
+9 10
+1 4
+6 16
+8 17
+6 7
+0 5
+1 9
+3 7
+8 14
+9 17
+10 15
+3 10
+4 14
+9 10
+9 16
+4 9
+2 12
+4 5
+6 14
+3 12
+10 16
+10 14
+6 12
+2 11
+4 11
+1 10
+5 6
+3 13
+10 19
+4 8
+0 2
+7 9
+6 7
+10 12
+9 18
+2 8
+6 9
+2 6
+4 11
+9 18
+8 14
+10 16
+9 13
+4 5
+1 6
+9 15
+8 9
+10 14
+1 2
+9 17
+10 15
+5 8
+8 11
+8 9
+10 17
+2 4
+5 6
+1 4
+1 4
+5 15
+7 13
+6 12
+10 12
+7 13
+9 10
+5 9
+0 5
+1 7
+2 3
+9 14
+4 10
+8 9
+3 12
+2 3
+4 11
+10 20
+10 13
+3 9
+8 16
diff --git a/bottleneck/tests/data/test_347_A b/bottleneck/tests/data/test_347_A
new file mode 100644
index 0000000..0cfd08b
--- /dev/null
+++ b/bottleneck/tests/data/test_347_A
@@ -0,0 +1,100 @@
+0 3
+9 14
+9 11
+1 3
+7 8
+4 12
+7 8
+10 20
+8 13
+2 5
+8 9
+5 14
+8 9
+5 11
+10 14
+7 15
+4 9
+4 10
+1 2
+2 6
+6 12
+0 1
+7 8
+10 13
+4 9
+0 3
+2 3
+0 4
+3 6
+7 13
+0 1
+10 13
+3 4
+1 2
+0 5
+9 12
+1 11
+8 17
+3 4
+3 7
+4 9
+1 2
+1 9
+4 14
+10 11
+3 11
+8 9
+2 6
+4 7
+8 13
+7 10
+0 1
+10 19
+7 13
+6 11
+1 10
+4 12
+9 14
+5 12
+3 13
+0 1
+2 3
+4 8
+5 11
+8 18
+5 6
+0 3
+0 3
+5 8
+10 11
+3 9
+0 4
+8 11
+5 14
+3 7
+9 10
+6 7
+8 14
+9 18
+6 11
+7 8
+6 10
+4 9
+4 9
+9 14
+6 13
+6 13
+10 17
+7 17
+8 15
+7 9
+4 9
+4 14
+0 1
+5 15
+4 8
+0 7
+4 5
+7 16
+4 9
diff --git a/bottleneck/tests/data/test_347_B b/bottleneck/tests/data/test_347_B
new file mode 100644
index 0000000..66d57ea
--- /dev/null
+++ b/bottleneck/tests/data/test_347_B
@@ -0,0 +1,100 @@
+10 11
+6 15
+5 11
+8 9
+8 12
+4 7
+6 7
+6 11
+10 16
+6 15
+9 19
+7 16
+10 12
+0 1
+9 13
+9 10
+10 15
+6 10
+10 12
+7 10
+9 17
+2 3
+10 19
+2 3
+5 13
+7 9
+9 16
+9 18
+9 16
+4 10
+1 11
+6 7
+9 10
+6 7
+3 4
+8 15
+6 16
+8 9
+6 8
+8 10
+0 6
+7 9
+5 10
+3 6
+1 5
+6 7
+6 9
+4 13
+5 7
+8 17
+10 16
+9 19
+5 9
+2 3
+6 7
+7 16
+4 10
+3 10
+6 9
+3 11
+9 18
+7 15
+8 16
+6 9
+8 10
+6 10
+0 3
+1 2
+2 3
+5 11
+5 9
+1 11
+10 11
+0 10
+9 14
+1 5
+3 4
+3 10
+6 12
+0 7
+5 9
+9 12
+8 16
+7 12
+1 11
+9 11
+5 15
+10 19
+2 8
+5 15
+4 6
+3 10
+4 13
+0 9
+5 6
+6 10
+2 3
+3 12
+1 10
+6 7
diff --git a/bottleneck/tests/data/test_348_A b/bottleneck/tests/data/test_348_A
new file mode 100644
index 0000000..8cef3ff
--- /dev/null
+++ b/bottleneck/tests/data/test_348_A
@@ -0,0 +1,100 @@
+8 16
+2 7
+7 12
+0 9
+9 12
+8 18
+1 3
+2 6
+3 8
+2 6
+3 11
+5 10
+8 9
+0 7
+5 11
+3 10
+3 7
+2 12
+5 12
+6 12
+3 9
+2 9
+1 2
+9 12
+0 9
+9 16
+6 10
+6 10
+2 4
+2 10
+7 8
+8 15
+4 14
+3 5
+8 10
+7 9
+10 19
+8 16
+7 8
+3 4
+8 13
+3 13
+0 1
+7 16
+7 13
+0 7
+7 11
+3 10
+4 14
+4 7
+1 2
+10 13
+8 14
+5 15
+7 11
+6 14
+9 10
+6 15
+2 12
+4 13
+1 4
+6 11
+1 2
+2 7
+3 4
+3 4
+2 8
+2 10
+8 18
+9 12
+9 13
+8 9
+4 10
+5 6
+6 10
+8 9
+5 15
+3 7
+2 10
+1 5
+6 7
+4 5
+5 8
+10 17
+5 8
+10 19
+5 15
+3 10
+8 18
+0 2
+9 13
+2 11
+1 7
+4 12
+5 7
+4 10
+5 13
+3 4
+7 15
+0 1
diff --git a/bottleneck/tests/data/test_348_B b/bottleneck/tests/data/test_348_B
new file mode 100644
index 0000000..5db1829
--- /dev/null
+++ b/bottleneck/tests/data/test_348_B
@@ -0,0 +1,100 @@
+8 18
+0 10
+5 12
+5 13
+5 6
+7 14
+3 9
+2 7
+0 1
+4 11
+10 11
+10 17
+7 8
+5 6
+1 6
+10 15
+8 9
+8 11
+5 6
+7 9
+4 6
+10 13
+6 14
+1 2
+5 6
+7 15
+1 9
+10 12
+9 10
+4 9
+7 10
+7 9
+8 16
+1 9
+5 10
+10 17
+4 5
+8 10
+5 15
+7 14
+5 10
+1 11
+7 11
+8 16
+1 10
+10 17
+2 6
+7 12
+4 5
+2 6
+0 7
+2 9
+10 11
+10 20
+7 17
+9 17
+2 8
+7 11
+2 4
+2 7
+7 10
+10 16
+6 13
+1 3
+2 10
+9 19
+2 12
+6 12
+4 5
+9 17
+1 6
+0 1
+4 10
+8 12
+0 8
+10 19
+2 11
+3 4
+0 1
+1 9
+9 14
+4 8
+2 10
+0 3
+7 15
+8 12
+7 15
+5 7
+8 11
+5 12
+2 11
+9 14
+10 12
+1 11
+7 9
+10 11
+1 5
+2 8
+6 15
+1 5
diff --git a/bottleneck/tests/data/test_349_A b/bottleneck/tests/data/test_349_A
new file mode 100644
index 0000000..a3d008e
--- /dev/null
+++ b/bottleneck/tests/data/test_349_A
@@ -0,0 +1,100 @@
+9 18
+5 7
+10 20
+5 6
+8 12
+5 6
+7 14
+9 17
+9 11
+6 7
+3 4
+1 2
+7 9
+1 8
+3 6
+10 13
+2 9
+9 10
+0 8
+3 12
+2 12
+0 6
+7 16
+8 16
+7 8
+10 12
+6 7
+10 13
+3 9
+2 3
+8 14
+4 8
+7 12
+6 12
+6 16
+1 8
+7 13
+2 10
+9 16
+3 10
+0 8
+10 11
+1 2
+5 12
+10 20
+3 10
+7 14
+2 12
+2 10
+4 7
+6 15
+6 7
+3 13
+5 12
+6 9
+5 6
+10 17
+6 7
+4 5
+10 11
+9 13
+6 14
+4 9
+4 7
+5 9
+6 11
+10 13
+5 15
+3 6
+1 7
+7 12
+6 7
+3 9
+5 9
+0 2
+10 14
+3 4
+6 16
+5 13
+2 7
+9 16
+0 6
+9 11
+0 3
+1 10
+3 6
+10 16
+4 10
+10 11
+9 14
+3 13
+0 3
+8 10
+8 18
+5 13
+5 11
+9 18
+1 3
+8 12
+5 6
diff --git a/bottleneck/tests/data/test_349_B b/bottleneck/tests/data/test_349_B
new file mode 100644
index 0000000..d66b5eb
--- /dev/null
+++ b/bottleneck/tests/data/test_349_B
@@ -0,0 +1,100 @@
+8 9
+2 3
+7 8
+4 14
+8 15
+3 8
+5 9
+1 3
+7 9
+0 5
+6 11
+3 12
+9 12
+4 10
+7 8
+10 14
+4 9
+5 6
+3 8
+7 15
+2 9
+3 4
+8 14
+7 11
+5 6
+10 19
+8 13
+2 5
+0 9
+0 8
+8 13
+4 8
+10 17
+10 14
+8 17
+2 6
+9 10
+6 10
+8 9
+0 2
+10 18
+6 9
+10 17
+0 3
+8 13
+9 12
+4 5
+8 14
+9 10
+1 2
+2 10
+8 15
+3 12
+4 9
+5 12
+3 11
+2 6
+3 7
+2 4
+5 10
+10 13
+2 4
+4 5
+1 2
+2 8
+2 3
+5 10
+6 7
+9 18
+8 9
+7 12
+2 4
+7 9
+7 14
+8 10
+10 11
+8 13
+10 15
+6 12
+10 16
+9 12
+9 16
+1 5
+2 9
+6 8
+8 10
+0 1
+1 3
+10 11
+7 16
+5 9
+7 13
+7 15
+6 10
+1 4
+10 15
+2 7
+2 7
+8 9
+3 13
diff --git a/bottleneck/tests/data/test_350_A b/bottleneck/tests/data/test_350_A
new file mode 100644
index 0000000..734d037
--- /dev/null
+++ b/bottleneck/tests/data/test_350_A
@@ -0,0 +1,100 @@
+4 13
+9 10
+7 11
+3 10
+1 9
+3 4
+3 11
+7 13
+9 15
+7 8
+7 14
+0 10
+1 6
+7 10
+3 4
+1 2
+7 12
+7 17
+3 11
+4 9
+7 16
+10 11
+3 13
+3 7
+4 5
+3 7
+6 9
+9 10
+0 8
+9 16
+10 13
+5 13
+3 8
+6 9
+10 11
+9 16
+10 11
+5 15
+9 13
+0 1
+10 17
+1 2
+10 20
+0 2
+9 17
+4 9
+10 16
+3 5
+9 18
+2 6
+4 12
+3 12
+7 9
+2 11
+5 13
+2 5
+0 5
+3 9
+3 7
+2 6
+8 15
+1 9
+3 4
+5 10
+3 4
+9 19
+6 8
+9 10
+3 13
+4 5
+1 4
+10 11
+9 13
+8 10
+10 12
+6 8
+1 6
+9 10
+1 5
+1 2
+8 9
+2 9
+3 4
+1 10
+0 7
+0 1
+1 10
+7 8
+4 11
+9 12
+7 17
+8 9
+4 8
+8 11
+9 16
+4 7
+3 5
+3 6
+5 6
+0 9
diff --git a/bottleneck/tests/data/test_350_B b/bottleneck/tests/data/test_350_B
new file mode 100644
index 0000000..3cf03c4
--- /dev/null
+++ b/bottleneck/tests/data/test_350_B
@@ -0,0 +1,100 @@
+10 11
+7 8
+10 13
+1 2
+0 1
+9 10
+10 18
+9 18
+1 9
+0 10
+10 11
+10 14
+0 2
+8 17
+7 17
+8 13
+0 3
+4 11
+5 7
+9 14
+5 14
+1 4
+5 9
+3 5
+10 18
+3 13
+3 4
+4 7
+3 7
+8 13
+1 11
+0 3
+1 4
+10 20
+4 5
+0 9
+9 13
+6 12
+9 19
+7 16
+2 3
+5 6
+1 9
+0 8
+2 4
+8 15
+0 7
+5 6
+4 8
+2 6
+1 2
+8 10
+2 10
+0 1
+8 13
+10 12
+1 8
+2 8
+2 4
+9 12
+7 8
+6 14
+3 9
+1 6
+7 13
+4 7
+10 17
+7 8
+9 12
+8 10
+6 13
+5 14
+5 13
+10 14
+9 13
+1 2
+2 3
+7 11
+6 13
+10 11
+1 9
+1 3
+7 14
+5 14
+2 3
+3 6
+9 11
+10 15
+0 6
+8 16
+4 11
+1 8
+3 8
+2 5
+6 13
+3 6
+7 8
+10 15
+7 10
+3 4
diff --git a/bottleneck/tests/data/test_351_A b/bottleneck/tests/data/test_351_A
new file mode 100644
index 0000000..3989d6c
--- /dev/null
+++ b/bottleneck/tests/data/test_351_A
@@ -0,0 +1,100 @@
+2 11
+9 18
+7 13
+10 12
+5 10
+8 11
+10 11
+0 1
+6 13
+2 12
+5 13
+6 8
+2 3
+4 6
+4 10
+5 12
+7 12
+6 13
+6 13
+7 17
+6 10
+6 14
+8 9
+1 9
+0 10
+7 10
+3 12
+9 14
+2 10
+10 14
+1 7
+1 6
+2 12
+7 13
+3 6
+4 5
+2 9
+7 8
+1 2
+8 12
+6 11
+7 8
+10 13
+3 10
+4 12
+5 8
+9 15
+8 15
+4 11
+6 7
+6 8
+9 18
+2 3
+10 20
+0 5
+10 20
+4 13
+10 12
+7 17
+8 16
+2 10
+9 11
+5 11
+5 15
+2 5
+3 12
+5 8
+6 9
+10 11
+3 8
+5 15
+3 13
+10 15
+8 10
+4 9
+4 6
+8 10
+8 17
+0 1
+1 2
+1 8
+7 14
+0 1
+1 5
+6 7
+1 6
+9 14
+8 12
+0 1
+2 10
+0 8
+4 10
+0 8
+3 4
+7 11
+9 13
+0 5
+3 9
+4 9
+2 4
diff --git a/bottleneck/tests/data/test_351_B b/bottleneck/tests/data/test_351_B
new file mode 100644
index 0000000..b1c32d7
--- /dev/null
+++ b/bottleneck/tests/data/test_351_B
@@ -0,0 +1,100 @@
+9 18
+7 9
+6 14
+2 10
+6 7
+9 13
+3 12
+6 7
+4 7
+6 9
+3 4
+7 17
+0 9
+3 8
+0 3
+3 13
+10 15
+1 5
+1 7
+4 10
+2 9
+9 12
+4 11
+10 16
+2 7
+9 17
+1 8
+9 12
+5 8
+10 13
+2 11
+8 9
+5 6
+0 6
+0 5
+2 3
+9 12
+9 13
+8 10
+4 6
+1 4
+7 9
+4 5
+8 9
+5 7
+4 14
+5 9
+3 11
+4 8
+3 10
+4 13
+6 14
+6 13
+6 16
+9 18
+4 14
+3 4
+6 12
+2 6
+8 16
+9 13
+0 4
+9 18
+7 17
+0 5
+0 2
+7 8
+8 10
+0 1
+10 17
+2 7
+10 14
+7 9
+3 10
+1 11
+2 4
+7 13
+5 8
+2 7
+4 9
+8 14
+1 6
+2 4
+4 5
+6 12
+8 9
+0 4
+4 5
+0 7
+9 12
+8 9
+4 9
+8 9
+9 18
+3 10
+0 3
+10 16
+3 9
+3 7
+3 13
diff --git a/bottleneck/tests/data/test_352_A b/bottleneck/tests/data/test_352_A
new file mode 100644
index 0000000..df81454
--- /dev/null
+++ b/bottleneck/tests/data/test_352_A
@@ -0,0 +1,100 @@
+8 12
+1 7
+7 15
+10 15
+5 8
+1 7
+1 2
+1 7
+6 10
+6 12
+8 16
+0 10
+4 8
+1 2
+6 13
+7 11
+5 11
+5 6
+0 1
+8 17
+0 2
+0 4
+9 16
+9 16
+10 13
+5 12
+3 11
+4 9
+9 12
+9 13
+1 5
+1 2
+2 6
+1 7
+8 17
+7 8
+4 9
+9 13
+1 8
+7 9
+0 10
+7 8
+9 15
+5 11
+0 4
+6 9
+0 10
+10 19
+6 11
+0 10
+7 16
+9 10
+2 5
+6 7
+6 11
+5 14
+9 10
+6 11
+8 12
+7 11
+4 12
+9 11
+1 4
+5 7
+6 8
+3 4
+8 15
+2 5
+8 13
+1 2
+4 5
+5 12
+6 15
+6 10
+1 8
+0 9
+0 2
+9 18
+7 14
+4 8
+5 10
+0 10
+9 10
+0 10
+10 14
+0 1
+7 8
+9 14
+8 11
+8 12
+8 14
+7 16
+4 7
+4 14
+0 4
+2 3
+6 16
+9 16
+6 12
+8 17
diff --git a/bottleneck/tests/data/test_352_B b/bottleneck/tests/data/test_352_B
new file mode 100644
index 0000000..9b30bae
--- /dev/null
+++ b/bottleneck/tests/data/test_352_B
@@ -0,0 +1,100 @@
+2 10
+0 1
+10 15
+7 14
+2 3
+0 9
+1 4
+5 6
+1 4
+2 8
+2 4
+0 6
+2 8
+0 1
+10 14
+5 11
+0 6
+10 17
+2 9
+10 16
+7 14
+4 11
+6 7
+3 6
+7 16
+2 8
+0 3
+1 2
+5 7
+10 12
+5 6
+1 3
+5 14
+5 14
+6 13
+8 16
+0 10
+6 12
+9 17
+3 5
+4 10
+3 6
+1 9
+1 9
+8 17
+3 4
+0 1
+1 9
+9 11
+6 7
+0 7
+3 4
+9 15
+9 13
+0 5
+1 10
+6 15
+10 19
+5 14
+1 11
+6 12
+4 13
+4 11
+2 3
+7 11
+2 5
+0 6
+0 2
+10 11
+1 5
+6 7
+2 10
+9 17
+0 5
+8 13
+2 12
+6 7
+1 6
+9 17
+8 14
+0 10
+1 2
+2 3
+2 10
+2 12
+4 6
+8 9
+7 8
+6 10
+7 17
+8 17
+10 19
+4 6
+7 9
+2 12
+2 10
+8 15
+0 4
+1 6
+2 5
diff --git a/bottleneck/tests/data/test_353_A b/bottleneck/tests/data/test_353_A
new file mode 100644
index 0000000..3dda9d1
--- /dev/null
+++ b/bottleneck/tests/data/test_353_A
@@ -0,0 +1,100 @@
+1 11
+3 5
+3 5
+2 3
+9 10
+0 9
+6 9
+0 8
+8 10
+6 12
+1 10
+1 2
+0 8
+8 18
+0 7
+3 4
+2 7
+8 15
+1 5
+1 9
+2 11
+7 11
+3 12
+4 6
+0 2
+8 16
+0 1
+10 18
+4 9
+8 18
+1 8
+5 7
+8 16
+1 2
+4 10
+9 18
+3 5
+5 8
+2 10
+3 8
+8 16
+10 12
+0 1
+0 9
+3 7
+3 4
+3 6
+3 9
+8 10
+2 12
+6 10
+3 13
+2 6
+9 10
+6 10
+9 19
+3 5
+4 6
+8 9
+2 3
+5 6
+3 4
+3 7
+7 17
+8 12
+5 6
+1 2
+0 1
+6 10
+7 9
+5 15
+7 14
+2 9
+1 5
+4 5
+0 9
+1 9
+7 8
+1 7
+2 3
+10 16
+5 6
+5 10
+0 9
+1 11
+7 10
+7 17
+10 19
+1 2
+9 19
+10 14
+7 11
+9 14
+8 17
+1 2
+7 16
+2 9
+9 16
+3 4
+0 1
diff --git a/bottleneck/tests/data/test_353_B b/bottleneck/tests/data/test_353_B
new file mode 100644
index 0000000..16ed654
--- /dev/null
+++ b/bottleneck/tests/data/test_353_B
@@ -0,0 +1,100 @@
+1 9
+1 9
+9 14
+7 9
+9 18
+6 13
+1 2
+5 15
+7 8
+8 15
+5 11
+9 13
+1 8
+4 6
+10 11
+6 7
+4 10
+0 4
+3 7
+0 1
+10 11
+7 13
+0 2
+4 5
+10 18
+8 13
+4 11
+8 18
+8 15
+1 10
+6 13
+5 8
+10 15
+7 14
+2 3
+10 19
+5 8
+2 3
+7 14
+1 7
+1 9
+6 12
+2 8
+3 11
+5 13
+2 3
+10 16
+10 15
+2 10
+10 18
+3 6
+0 6
+1 4
+6 11
+1 3
+8 9
+8 16
+0 2
+8 12
+9 10
+1 4
+0 3
+0 2
+5 14
+3 11
+7 12
+7 17
+5 6
+10 16
+3 4
+0 6
+0 3
+0 1
+3 13
+6 7
+4 9
+7 9
+0 1
+10 13
+8 12
+0 6
+2 8
+10 13
+2 3
+7 13
+9 19
+4 7
+10 16
+1 5
+2 11
+3 13
+8 13
+3 9
+3 9
+3 13
+7 15
+0 2
+2 6
+7 14
+1 4
diff --git a/bottleneck/tests/data/test_354_A b/bottleneck/tests/data/test_354_A
new file mode 100644
index 0000000..c701ef2
--- /dev/null
+++ b/bottleneck/tests/data/test_354_A
@@ -0,0 +1,100 @@
+6 16
+5 15
+0 2
+8 18
+10 15
+0 2
+3 5
+6 14
+1 9
+3 12
+6 8
+2 3
+2 11
+8 14
+10 15
+3 5
+10 12
+1 4
+3 4
+8 15
+10 15
+6 15
+10 16
+10 17
+3 11
+10 17
+2 3
+2 10
+5 9
+5 9
+8 16
+0 7
+7 15
+1 3
+0 1
+10 17
+10 12
+0 8
+4 11
+1 8
+5 8
+0 10
+2 4
+1 2
+7 11
+7 14
+4 5
+7 16
+3 7
+5 7
+8 9
+8 12
+2 3
+6 16
+6 16
+5 7
+5 14
+0 10
+9 16
+9 11
+6 16
+5 14
+5 11
+8 9
+4 10
+5 6
+1 2
+6 15
+1 5
+9 10
+8 9
+0 8
+4 5
+10 19
+7 11
+8 18
+3 4
+7 8
+2 9
+6 11
+1 2
+7 16
+0 2
+1 10
+10 11
+4 5
+9 12
+8 13
+1 11
+4 8
+0 1
+9 15
+0 7
+2 4
+1 6
+1 10
+8 15
+8 18
+8 10
+9 17
diff --git a/bottleneck/tests/data/test_354_B b/bottleneck/tests/data/test_354_B
new file mode 100644
index 0000000..0a21b24
--- /dev/null
+++ b/bottleneck/tests/data/test_354_B
@@ -0,0 +1,100 @@
+7 8
+3 12
+9 19
+5 13
+8 9
+4 14
+10 12
+1 4
+1 5
+8 16
+5 10
+7 10
+5 9
+4 7
+6 9
+6 7
+0 1
+7 8
+1 7
+9 19
+7 8
+3 13
+10 18
+8 13
+3 13
+6 15
+2 3
+3 13
+1 8
+9 18
+4 9
+9 10
+10 18
+6 9
+8 17
+1 5
+3 8
+1 11
+7 12
+0 1
+4 5
+7 16
+6 11
+3 5
+5 14
+6 11
+3 10
+7 8
+8 11
+7 13
+10 17
+1 9
+7 14
+1 10
+3 12
+7 15
+1 4
+7 10
+0 5
+3 9
+5 12
+7 16
+5 6
+0 10
+0 1
+3 5
+0 7
+1 6
+4 5
+3 8
+1 8
+2 3
+10 20
+4 10
+7 11
+0 4
+4 6
+5 8
+10 17
+9 10
+0 3
+0 3
+5 9
+9 19
+8 14
+9 14
+4 11
+10 17
+7 9
+6 7
+10 19
+9 10
+3 8
+2 11
+4 14
+9 16
+2 8
+2 5
+5 11
+10 18
diff --git a/bottleneck/tests/data/test_355_A b/bottleneck/tests/data/test_355_A
new file mode 100644
index 0000000..48d49bd
--- /dev/null
+++ b/bottleneck/tests/data/test_355_A
@@ -0,0 +1,100 @@
+6 9
+0 2
+2 6
+4 6
+5 7
+8 14
+10 15
+8 9
+6 14
+9 15
+6 12
+1 9
+4 7
+1 4
+3 8
+0 2
+6 16
+6 7
+5 7
+9 11
+10 20
+3 11
+9 13
+2 5
+0 3
+7 14
+7 8
+10 18
+5 7
+4 11
+0 10
+7 16
+1 8
+7 15
+3 4
+3 5
+8 13
+9 12
+5 10
+9 13
+5 11
+8 16
+3 4
+4 11
+9 18
+1 3
+10 14
+5 6
+5 10
+8 11
+8 10
+7 14
+3 6
+9 17
+0 3
+0 2
+2 11
+4 8
+0 6
+7 14
+10 11
+5 7
+9 18
+2 8
+4 5
+1 11
+0 9
+9 10
+3 12
+10 19
+3 7
+7 14
+1 3
+8 9
+9 13
+0 8
+5 11
+6 13
+5 10
+10 15
+8 15
+6 12
+2 6
+2 4
+4 9
+3 6
+9 10
+5 10
+10 15
+9 17
+5 10
+6 11
+2 8
+4 5
+5 15
+2 3
+7 14
+4 10
+4 11
+8 10
diff --git a/bottleneck/tests/data/test_355_B b/bottleneck/tests/data/test_355_B
new file mode 100644
index 0000000..cd9cec5
--- /dev/null
+++ b/bottleneck/tests/data/test_355_B
@@ -0,0 +1,100 @@
+4 11
+9 14
+8 12
+3 5
+5 11
+7 15
+7 15
+1 10
+1 6
+4 13
+7 8
+5 7
+1 2
+3 13
+2 5
+4 10
+6 7
+10 11
+2 6
+1 10
+4 5
+10 18
+5 9
+0 3
+8 9
+5 13
+4 5
+1 2
+4 9
+1 11
+5 15
+9 11
+2 3
+0 1
+4 11
+6 10
+8 10
+2 8
+3 5
+4 8
+10 20
+0 5
+3 13
+2 8
+0 10
+2 7
+10 11
+0 2
+8 12
+1 10
+3 9
+2 8
+6 7
+10 17
+4 5
+2 7
+5 8
+10 20
+5 13
+10 19
+4 13
+1 9
+6 12
+3 4
+4 5
+8 18
+7 14
+1 10
+7 14
+5 9
+1 6
+6 14
+7 8
+5 12
+4 14
+1 7
+2 8
+6 11
+7 13
+3 10
+3 4
+3 11
+9 10
+1 11
+9 10
+2 8
+10 19
+3 6
+10 13
+4 5
+7 16
+2 7
+4 7
+9 15
+9 17
+4 8
+5 8
+4 8
+0 1
+10 17
diff --git a/bottleneck/tests/data/test_356_A b/bottleneck/tests/data/test_356_A
new file mode 100644
index 0000000..cb92f38
--- /dev/null
+++ b/bottleneck/tests/data/test_356_A
@@ -0,0 +1,100 @@
+7 12
+5 6
+6 13
+1 6
+9 10
+10 11
+2 9
+4 14
+4 11
+5 14
+4 13
+6 12
+7 13
+8 9
+5 11
+6 14
+9 13
+0 3
+7 11
+3 13
+2 5
+0 6
+1 8
+3 9
+8 17
+1 7
+10 19
+0 4
+8 18
+0 7
+1 3
+1 10
+0 6
+1 5
+3 11
+0 3
+7 13
+10 11
+2 4
+2 5
+4 11
+4 14
+0 6
+2 11
+6 11
+3 4
+2 6
+6 16
+6 8
+9 13
+8 12
+7 16
+9 16
+4 8
+1 8
+9 19
+7 13
+9 19
+5 6
+3 10
+2 10
+2 10
+9 11
+9 18
+7 13
+7 11
+5 8
+8 13
+8 10
+7 13
+7 17
+6 15
+5 8
+5 9
+5 9
+7 10
+4 10
+9 13
+6 16
+4 12
+5 6
+9 17
+1 2
+2 7
+5 11
+2 12
+10 16
+1 10
+10 19
+5 9
+10 19
+5 10
+10 13
+10 13
+6 7
+10 19
+2 10
+4 6
+3 5
+1 11
diff --git a/bottleneck/tests/data/test_356_B b/bottleneck/tests/data/test_356_B
new file mode 100644
index 0000000..365ed3f
--- /dev/null
+++ b/bottleneck/tests/data/test_356_B
@@ -0,0 +1,100 @@
+6 11
+8 12
+7 8
+3 4
+9 12
+8 15
+4 5
+8 18
+2 3
+0 2
+8 11
+1 2
+2 8
+9 13
+6 10
+10 20
+0 3
+7 12
+7 11
+10 20
+6 10
+8 14
+5 6
+5 10
+8 12
+6 16
+1 11
+3 9
+7 17
+8 17
+5 11
+6 16
+5 9
+9 19
+7 11
+0 8
+8 17
+6 13
+0 5
+10 19
+3 8
+0 8
+0 9
+9 16
+8 12
+3 4
+2 3
+1 2
+6 11
+3 4
+2 4
+3 11
+4 11
+8 15
+7 9
+8 10
+4 14
+9 12
+9 16
+1 2
+7 13
+5 11
+1 8
+9 12
+0 5
+10 13
+9 11
+5 14
+0 9
+10 20
+7 8
+4 10
+0 3
+3 12
+8 17
+1 9
+5 9
+2 3
+1 8
+6 7
+3 4
+1 8
+7 10
+1 10
+0 1
+4 6
+8 11
+9 13
+5 6
+10 14
+10 16
+1 6
+5 9
+10 20
+7 13
+3 11
+0 3
+0 7
+6 12
+1 9
diff --git a/bottleneck/tests/data/test_357_A b/bottleneck/tests/data/test_357_A
new file mode 100644
index 0000000..de1e8eb
--- /dev/null
+++ b/bottleneck/tests/data/test_357_A
@@ -0,0 +1,100 @@
+6 11
+4 11
+5 10
+8 9
+4 12
+10 17
+0 1
+9 15
+3 7
+6 13
+7 8
+3 4
+4 12
+8 9
+2 4
+10 20
+3 4
+6 16
+6 16
+4 12
+5 6
+9 12
+1 8
+6 14
+8 13
+2 10
+4 14
+3 5
+7 12
+2 7
+3 6
+1 2
+4 5
+7 13
+3 8
+6 9
+4 9
+6 7
+1 6
+8 10
+10 15
+3 6
+10 19
+8 14
+8 9
+4 7
+7 11
+4 11
+2 5
+0 7
+10 13
+4 6
+5 6
+7 16
+2 10
+8 18
+4 5
+9 10
+8 9
+8 14
+0 1
+5 15
+2 9
+6 7
+8 10
+10 14
+8 11
+5 8
+1 5
+9 15
+3 10
+5 10
+1 5
+4 6
+3 11
+6 7
+9 12
+5 11
+1 6
+6 14
+0 5
+3 12
+2 10
+7 12
+7 15
+1 11
+8 12
+3 7
+10 14
+8 9
+8 9
+9 10
+2 12
+3 4
+1 10
+9 15
+1 7
+10 14
+1 3
+10 14
diff --git a/bottleneck/tests/data/test_357_B b/bottleneck/tests/data/test_357_B
new file mode 100644
index 0000000..1c68b90
--- /dev/null
+++ b/bottleneck/tests/data/test_357_B
@@ -0,0 +1,100 @@
+8 10
+0 5
+6 15
+7 17
+6 14
+3 4
+3 5
+0 9
+1 5
+1 2
+2 3
+6 7
+9 10
+3 13
+9 13
+8 11
+5 7
+2 11
+7 9
+10 11
+9 11
+10 12
+4 10
+8 9
+4 12
+8 11
+5 14
+0 1
+8 9
+9 13
+6 14
+7 10
+10 17
+2 10
+9 17
+8 16
+1 3
+9 19
+0 1
+7 15
+2 8
+1 2
+0 1
+2 3
+7 8
+6 11
+10 20
+3 12
+6 11
+7 9
+5 8
+5 14
+3 12
+8 17
+10 15
+9 14
+8 9
+7 13
+9 12
+1 7
+5 11
+5 11
+6 8
+8 9
+5 6
+3 10
+3 4
+1 3
+3 10
+7 8
+1 9
+3 13
+3 10
+7 14
+4 14
+1 10
+0 10
+9 10
+10 15
+1 2
+8 10
+3 4
+2 4
+2 3
+7 13
+3 6
+8 14
+5 6
+3 11
+8 14
+0 5
+3 10
+7 11
+3 11
+10 19
+8 9
+0 1
+10 20
+7 8
+0 8
diff --git a/bottleneck/tests/data/test_358_A b/bottleneck/tests/data/test_358_A
new file mode 100644
index 0000000..2297dae
--- /dev/null
+++ b/bottleneck/tests/data/test_358_A
@@ -0,0 +1,100 @@
+7 12
+6 15
+1 4
+1 5
+7 9
+7 16
+0 2
+2 3
+6 12
+1 9
+9 12
+6 8
+8 9
+2 3
+6 11
+4 6
+7 11
+7 10
+8 9
+5 8
+6 8
+0 6
+9 18
+0 1
+7 14
+7 9
+7 14
+10 15
+3 10
+7 16
+8 15
+6 12
+7 9
+6 11
+3 8
+3 4
+4 6
+5 11
+10 16
+7 9
+2 8
+1 6
+8 9
+7 8
+7 14
+9 19
+4 9
+0 1
+3 4
+5 11
+2 12
+3 9
+9 16
+3 5
+0 8
+7 13
+7 17
+0 1
+4 12
+7 15
+8 11
+8 18
+4 8
+8 12
+8 18
+4 12
+4 10
+6 12
+9 14
+6 12
+9 11
+6 7
+0 5
+1 6
+8 17
+5 9
+5 14
+5 10
+9 19
+6 11
+3 4
+4 14
+1 11
+1 4
+10 19
+6 13
+3 4
+2 3
+2 7
+1 11
+5 11
+6 14
+1 6
+8 9
+7 8
+1 9
+2 8
+3 10
+10 17
+4 5
diff --git a/bottleneck/tests/data/test_358_B b/bottleneck/tests/data/test_358_B
new file mode 100644
index 0000000..e2d7d03
--- /dev/null
+++ b/bottleneck/tests/data/test_358_B
@@ -0,0 +1,100 @@
+6 7
+6 12
+10 13
+3 6
+9 10
+8 11
+3 13
+3 4
+10 16
+8 9
+3 5
+1 8
+4 5
+8 13
+9 18
+3 11
+3 13
+8 12
+7 11
+0 2
+4 7
+8 13
+7 16
+0 10
+1 9
+8 18
+1 9
+3 12
+1 10
+0 9
+9 16
+8 14
+0 7
+9 10
+0 3
+3 4
+6 8
+8 17
+9 16
+5 7
+0 2
+6 7
+1 6
+6 13
+4 5
+8 12
+9 14
+6 16
+9 14
+10 20
+4 14
+0 3
+9 18
+1 11
+6 13
+3 10
+9 13
+9 17
+6 16
+5 8
+3 4
+2 8
+9 15
+6 10
+8 18
+4 5
+3 5
+2 8
+3 11
+9 10
+3 11
+4 11
+9 12
+1 11
+0 10
+0 9
+8 12
+0 3
+9 14
+8 12
+6 14
+10 16
+3 8
+5 11
+1 6
+10 17
+0 2
+9 17
+8 10
+10 11
+9 13
+0 10
+5 11
+9 10
+4 5
+5 7
+4 14
+0 6
+0 1
+5 15
diff --git a/bottleneck/tests/data/test_359_A b/bottleneck/tests/data/test_359_A
new file mode 100644
index 0000000..6e990e4
--- /dev/null
+++ b/bottleneck/tests/data/test_359_A
@@ -0,0 +1,100 @@
+7 8
+8 11
+7 8
+5 6
+4 5
+4 5
+7 8
+3 8
+2 8
+8 10
+2 3
+6 7
+0 5
+2 4
+8 17
+7 15
+8 9
+6 7
+10 11
+7 14
+9 10
+0 8
+3 7
+3 13
+3 12
+4 10
+9 17
+9 19
+5 14
+2 8
+9 19
+4 11
+2 12
+0 2
+4 12
+5 13
+1 3
+6 15
+2 12
+3 4
+0 10
+1 2
+9 19
+5 14
+3 7
+0 7
+10 12
+1 11
+1 8
+0 1
+5 11
+3 4
+1 4
+2 6
+8 12
+9 13
+10 13
+0 7
+9 18
+5 6
+2 4
+10 14
+7 8
+5 15
+9 10
+5 13
+0 9
+4 6
+2 3
+2 11
+9 15
+4 11
+1 7
+4 9
+6 14
+8 15
+3 11
+3 6
+8 13
+6 12
+7 9
+10 20
+9 19
+6 7
+2 12
+0 10
+10 13
+10 13
+5 15
+4 14
+9 15
+0 7
+7 13
+9 10
+5 10
+8 10
+8 17
+8 17
+0 9
+0 1
diff --git a/bottleneck/tests/data/test_359_B b/bottleneck/tests/data/test_359_B
new file mode 100644
index 0000000..97c1bfe
--- /dev/null
+++ b/bottleneck/tests/data/test_359_B
@@ -0,0 +1,100 @@
+9 12
+2 11
+9 10
+10 12
+2 7
+4 7
+0 1
+9 11
+10 15
+4 12
+9 15
+9 18
+10 20
+7 8
+6 8
+10 20
+9 10
+8 18
+7 17
+3 4
+5 6
+1 8
+3 4
+9 18
+9 13
+5 15
+9 10
+5 11
+5 11
+9 11
+2 5
+9 16
+7 8
+0 4
+3 11
+1 7
+0 10
+5 12
+5 15
+2 3
+10 19
+9 12
+1 3
+5 11
+3 8
+9 15
+2 12
+9 16
+7 9
+1 2
+1 8
+4 13
+4 8
+0 1
+2 6
+1 6
+8 10
+6 12
+8 16
+8 17
+4 12
+9 12
+0 8
+3 10
+6 13
+4 5
+1 9
+5 9
+0 6
+6 7
+1 10
+7 17
+4 7
+5 15
+2 4
+9 14
+7 17
+5 13
+9 11
+0 7
+1 9
+3 8
+5 14
+1 7
+3 11
+1 10
+8 12
+10 11
+0 7
+7 14
+6 14
+0 10
+3 5
+10 18
+3 10
+6 7
+1 3
+1 3
+8 16
+7 16
diff --git a/bottleneck/tests/data/test_360_A b/bottleneck/tests/data/test_360_A
new file mode 100644
index 0000000..d271aaa
--- /dev/null
+++ b/bottleneck/tests/data/test_360_A
@@ -0,0 +1,2 @@
+84 85
+52 129
diff --git a/bottleneck/tests/data/test_360_B b/bottleneck/tests/data/test_360_B
new file mode 100644
index 0000000..2408922
--- /dev/null
+++ b/bottleneck/tests/data/test_360_B
@@ -0,0 +1,2 @@
+74 97
+83 94
diff --git a/bottleneck/tests/data/test_361_A b/bottleneck/tests/data/test_361_A
new file mode 100644
index 0000000..b4eea74
--- /dev/null
+++ b/bottleneck/tests/data/test_361_A
@@ -0,0 +1,2 @@
+97 159
+60 73
diff --git a/bottleneck/tests/data/test_361_B b/bottleneck/tests/data/test_361_B
new file mode 100644
index 0000000..3680b00
--- /dev/null
+++ b/bottleneck/tests/data/test_361_B
@@ -0,0 +1,2 @@
+47 60
+95 167
diff --git a/bottleneck/tests/data/test_362_A b/bottleneck/tests/data/test_362_A
new file mode 100644
index 0000000..1c4803d
--- /dev/null
+++ b/bottleneck/tests/data/test_362_A
@@ -0,0 +1,2 @@
+85 121
+2 61
diff --git a/bottleneck/tests/data/test_362_B b/bottleneck/tests/data/test_362_B
new file mode 100644
index 0000000..37fc7aa
--- /dev/null
+++ b/bottleneck/tests/data/test_362_B
@@ -0,0 +1,2 @@
+41 67
+80 101
diff --git a/bottleneck/tests/data/test_363_A b/bottleneck/tests/data/test_363_A
new file mode 100644
index 0000000..909ac51
--- /dev/null
+++ b/bottleneck/tests/data/test_363_A
@@ -0,0 +1,2 @@
+77 159
+60 118
diff --git a/bottleneck/tests/data/test_363_B b/bottleneck/tests/data/test_363_B
new file mode 100644
index 0000000..4c76429
--- /dev/null
+++ b/bottleneck/tests/data/test_363_B
@@ -0,0 +1,2 @@
+52 73
+71 103
diff --git a/bottleneck/tests/data/test_364_A b/bottleneck/tests/data/test_364_A
new file mode 100644
index 0000000..a6e34b7
--- /dev/null
+++ b/bottleneck/tests/data/test_364_A
@@ -0,0 +1,2 @@
+20 21
+70 88
diff --git a/bottleneck/tests/data/test_364_B b/bottleneck/tests/data/test_364_B
new file mode 100644
index 0000000..ba5c4bf
--- /dev/null
+++ b/bottleneck/tests/data/test_364_B
@@ -0,0 +1,2 @@
+65 72
+81 164
diff --git a/bottleneck/tests/data/test_365_A b/bottleneck/tests/data/test_365_A
new file mode 100644
index 0000000..6c9d44c
--- /dev/null
+++ b/bottleneck/tests/data/test_365_A
@@ -0,0 +1,2 @@
+9 64
+48 115
diff --git a/bottleneck/tests/data/test_365_B b/bottleneck/tests/data/test_365_B
new file mode 100644
index 0000000..f9e51a7
--- /dev/null
+++ b/bottleneck/tests/data/test_365_B
@@ -0,0 +1,2 @@
+87 125
+74 132
diff --git a/bottleneck/tests/data/test_366_A b/bottleneck/tests/data/test_366_A
new file mode 100644
index 0000000..fbf146c
--- /dev/null
+++ b/bottleneck/tests/data/test_366_A
@@ -0,0 +1,2 @@
+97 162
+27 43
diff --git a/bottleneck/tests/data/test_366_B b/bottleneck/tests/data/test_366_B
new file mode 100644
index 0000000..7385b5f
--- /dev/null
+++ b/bottleneck/tests/data/test_366_B
@@ -0,0 +1,2 @@
+51 149
+65 126
diff --git a/bottleneck/tests/data/test_367_A b/bottleneck/tests/data/test_367_A
new file mode 100644
index 0000000..48190bb
--- /dev/null
+++ b/bottleneck/tests/data/test_367_A
@@ -0,0 +1,2 @@
+36 104
+19 85
diff --git a/bottleneck/tests/data/test_367_B b/bottleneck/tests/data/test_367_B
new file mode 100644
index 0000000..7e26c08
--- /dev/null
+++ b/bottleneck/tests/data/test_367_B
@@ -0,0 +1,2 @@
+96 171
+17 21
diff --git a/bottleneck/tests/data/test_368_A b/bottleneck/tests/data/test_368_A
new file mode 100644
index 0000000..4b4767d
--- /dev/null
+++ b/bottleneck/tests/data/test_368_A
@@ -0,0 +1,2 @@
+72 156
+84 129
diff --git a/bottleneck/tests/data/test_368_B b/bottleneck/tests/data/test_368_B
new file mode 100644
index 0000000..3c72417
--- /dev/null
+++ b/bottleneck/tests/data/test_368_B
@@ -0,0 +1,2 @@
+32 71
+88 129
diff --git a/bottleneck/tests/data/test_369_A b/bottleneck/tests/data/test_369_A
new file mode 100644
index 0000000..d8a01b6
--- /dev/null
+++ b/bottleneck/tests/data/test_369_A
@@ -0,0 +1,2 @@
+56 128
+69 161
diff --git a/bottleneck/tests/data/test_369_B b/bottleneck/tests/data/test_369_B
new file mode 100644
index 0000000..9f7da60
--- /dev/null
+++ b/bottleneck/tests/data/test_369_B
@@ -0,0 +1,2 @@
+3 84
+92 119
diff --git a/bottleneck/tests/data/test_370_A b/bottleneck/tests/data/test_370_A
new file mode 100644
index 0000000..bdc8979
--- /dev/null
+++ b/bottleneck/tests/data/test_370_A
@@ -0,0 +1,2 @@
+49 140
+100 135
diff --git a/bottleneck/tests/data/test_370_B b/bottleneck/tests/data/test_370_B
new file mode 100644
index 0000000..e145eb4
--- /dev/null
+++ b/bottleneck/tests/data/test_370_B
@@ -0,0 +1,2 @@
+28 51
+55 70
diff --git a/bottleneck/tests/data/test_371_A b/bottleneck/tests/data/test_371_A
new file mode 100644
index 0000000..208a164
--- /dev/null
+++ b/bottleneck/tests/data/test_371_A
@@ -0,0 +1,2 @@
+93 154
+54 138
diff --git a/bottleneck/tests/data/test_371_B b/bottleneck/tests/data/test_371_B
new file mode 100644
index 0000000..7a2fc8a
--- /dev/null
+++ b/bottleneck/tests/data/test_371_B
@@ -0,0 +1,2 @@
+31 81
+88 143
diff --git a/bottleneck/tests/data/test_372_A b/bottleneck/tests/data/test_372_A
new file mode 100644
index 0000000..dd3597a
--- /dev/null
+++ b/bottleneck/tests/data/test_372_A
@@ -0,0 +1,2 @@
+3 92
+88 127
diff --git a/bottleneck/tests/data/test_372_B b/bottleneck/tests/data/test_372_B
new file mode 100644
index 0000000..225c36e
--- /dev/null
+++ b/bottleneck/tests/data/test_372_B
@@ -0,0 +1,2 @@
+6 95
+54 74
diff --git a/bottleneck/tests/data/test_373_A b/bottleneck/tests/data/test_373_A
new file mode 100644
index 0000000..0a84fd2
--- /dev/null
+++ b/bottleneck/tests/data/test_373_A
@@ -0,0 +1,2 @@
+80 109
+36 96
diff --git a/bottleneck/tests/data/test_373_B b/bottleneck/tests/data/test_373_B
new file mode 100644
index 0000000..b790337
--- /dev/null
+++ b/bottleneck/tests/data/test_373_B
@@ -0,0 +1,2 @@
+64 106
+12 78
diff --git a/bottleneck/tests/data/test_374_A b/bottleneck/tests/data/test_374_A
new file mode 100644
index 0000000..0df06a4
--- /dev/null
+++ b/bottleneck/tests/data/test_374_A
@@ -0,0 +1,2 @@
+91 158
+15 61
diff --git a/bottleneck/tests/data/test_374_B b/bottleneck/tests/data/test_374_B
new file mode 100644
index 0000000..7bd1bdd
--- /dev/null
+++ b/bottleneck/tests/data/test_374_B
@@ -0,0 +1,2 @@
+85 155
+5 64
diff --git a/bottleneck/tests/data/test_375_A b/bottleneck/tests/data/test_375_A
new file mode 100644
index 0000000..77cd274
--- /dev/null
+++ b/bottleneck/tests/data/test_375_A
@@ -0,0 +1,2 @@
+77 154
+15 27
diff --git a/bottleneck/tests/data/test_375_B b/bottleneck/tests/data/test_375_B
new file mode 100644
index 0000000..db3c6ee
--- /dev/null
+++ b/bottleneck/tests/data/test_375_B
@@ -0,0 +1,2 @@
+81 144
+44 79
diff --git a/bottleneck/tests/data/test_376_A b/bottleneck/tests/data/test_376_A
new file mode 100644
index 0000000..aca7402
--- /dev/null
+++ b/bottleneck/tests/data/test_376_A
@@ -0,0 +1,2 @@
+20 47
+61 129
diff --git a/bottleneck/tests/data/test_376_B b/bottleneck/tests/data/test_376_B
new file mode 100644
index 0000000..5bbae78
--- /dev/null
+++ b/bottleneck/tests/data/test_376_B
@@ -0,0 +1,2 @@
+41 98
+76 137
diff --git a/bottleneck/tests/data/test_377_A b/bottleneck/tests/data/test_377_A
new file mode 100644
index 0000000..707adfd
--- /dev/null
+++ b/bottleneck/tests/data/test_377_A
@@ -0,0 +1,2 @@
+91 123
+17 50
diff --git a/bottleneck/tests/data/test_377_B b/bottleneck/tests/data/test_377_B
new file mode 100644
index 0000000..afbe113
--- /dev/null
+++ b/bottleneck/tests/data/test_377_B
@@ -0,0 +1,2 @@
+45 116
+18 98
diff --git a/bottleneck/tests/data/test_378_A b/bottleneck/tests/data/test_378_A
new file mode 100644
index 0000000..7ac23e9
--- /dev/null
+++ b/bottleneck/tests/data/test_378_A
@@ -0,0 +1,2 @@
+98 183
+5 58
diff --git a/bottleneck/tests/data/test_378_B b/bottleneck/tests/data/test_378_B
new file mode 100644
index 0000000..328b726
--- /dev/null
+++ b/bottleneck/tests/data/test_378_B
@@ -0,0 +1,2 @@
+58 154
+82 148
diff --git a/bottleneck/tests/data/test_379_A b/bottleneck/tests/data/test_379_A
new file mode 100644
index 0000000..0f57258
--- /dev/null
+++ b/bottleneck/tests/data/test_379_A
@@ -0,0 +1,2 @@
+73 133
+38 52
diff --git a/bottleneck/tests/data/test_379_B b/bottleneck/tests/data/test_379_B
new file mode 100644
index 0000000..45e35ba
--- /dev/null
+++ b/bottleneck/tests/data/test_379_B
@@ -0,0 +1,2 @@
+46 95
+50 110
diff --git a/bottleneck/tests/data/test_380_A b/bottleneck/tests/data/test_380_A
new file mode 100644
index 0000000..a6d1d31
--- /dev/null
+++ b/bottleneck/tests/data/test_380_A
@@ -0,0 +1,3 @@
+42 50
+67 107
+6 85
diff --git a/bottleneck/tests/data/test_380_B b/bottleneck/tests/data/test_380_B
new file mode 100644
index 0000000..023f533
--- /dev/null
+++ b/bottleneck/tests/data/test_380_B
@@ -0,0 +1,3 @@
+31 126
+78 132
+15 92
diff --git a/bottleneck/tests/data/test_381_A b/bottleneck/tests/data/test_381_A
new file mode 100644
index 0000000..0b5985d
--- /dev/null
+++ b/bottleneck/tests/data/test_381_A
@@ -0,0 +1,3 @@
+7 43
+49 69
+94 119
diff --git a/bottleneck/tests/data/test_381_B b/bottleneck/tests/data/test_381_B
new file mode 100644
index 0000000..1f5ffef
--- /dev/null
+++ b/bottleneck/tests/data/test_381_B
@@ -0,0 +1,3 @@
+98 101
+89 113
+80 157
diff --git a/bottleneck/tests/data/test_382_A b/bottleneck/tests/data/test_382_A
new file mode 100644
index 0000000..e155629
--- /dev/null
+++ b/bottleneck/tests/data/test_382_A
@@ -0,0 +1,3 @@
+60 119
+40 77
+52 101
diff --git a/bottleneck/tests/data/test_382_B b/bottleneck/tests/data/test_382_B
new file mode 100644
index 0000000..5273c5f
--- /dev/null
+++ b/bottleneck/tests/data/test_382_B
@@ -0,0 +1,3 @@
+9 47
+74 170
+88 93
diff --git a/bottleneck/tests/data/test_383_A b/bottleneck/tests/data/test_383_A
new file mode 100644
index 0000000..7579cf6
--- /dev/null
+++ b/bottleneck/tests/data/test_383_A
@@ -0,0 +1,3 @@
+45 55
+12 57
+38 111
diff --git a/bottleneck/tests/data/test_383_B b/bottleneck/tests/data/test_383_B
new file mode 100644
index 0000000..050e76d
--- /dev/null
+++ b/bottleneck/tests/data/test_383_B
@@ -0,0 +1,3 @@
+61 126
+14 94
+58 81
diff --git a/bottleneck/tests/data/test_384_A b/bottleneck/tests/data/test_384_A
new file mode 100644
index 0000000..5ba83b2
--- /dev/null
+++ b/bottleneck/tests/data/test_384_A
@@ -0,0 +1,3 @@
+21 105
+7 55
+95 108
diff --git a/bottleneck/tests/data/test_384_B b/bottleneck/tests/data/test_384_B
new file mode 100644
index 0000000..f1a0074
--- /dev/null
+++ b/bottleneck/tests/data/test_384_B
@@ -0,0 +1,3 @@
+73 93
+20 52
+99 187
diff --git a/bottleneck/tests/data/test_385_A b/bottleneck/tests/data/test_385_A
new file mode 100644
index 0000000..195db5d
--- /dev/null
+++ b/bottleneck/tests/data/test_385_A
@@ -0,0 +1,3 @@
+28 66
+4 72
+57 155
diff --git a/bottleneck/tests/data/test_385_B b/bottleneck/tests/data/test_385_B
new file mode 100644
index 0000000..9234688
--- /dev/null
+++ b/bottleneck/tests/data/test_385_B
@@ -0,0 +1,3 @@
+75 175
+55 79
+89 178
diff --git a/bottleneck/tests/data/test_386_A b/bottleneck/tests/data/test_386_A
new file mode 100644
index 0000000..7a9281c
--- /dev/null
+++ b/bottleneck/tests/data/test_386_A
@@ -0,0 +1,3 @@
+65 87
+11 33
+17 45
diff --git a/bottleneck/tests/data/test_386_B b/bottleneck/tests/data/test_386_B
new file mode 100644
index 0000000..86a3caf
--- /dev/null
+++ b/bottleneck/tests/data/test_386_B
@@ -0,0 +1,3 @@
+83 93
+13 46
+67 68
diff --git a/bottleneck/tests/data/test_387_A b/bottleneck/tests/data/test_387_A
new file mode 100644
index 0000000..ff92400
--- /dev/null
+++ b/bottleneck/tests/data/test_387_A
@@ -0,0 +1,3 @@
+33 68
+20 115
+21 25
diff --git a/bottleneck/tests/data/test_387_B b/bottleneck/tests/data/test_387_B
new file mode 100644
index 0000000..c2e44a4
--- /dev/null
+++ b/bottleneck/tests/data/test_387_B
@@ -0,0 +1,3 @@
+44 45
+24 66
+6 45
diff --git a/bottleneck/tests/data/test_388_A b/bottleneck/tests/data/test_388_A
new file mode 100644
index 0000000..62b75be
--- /dev/null
+++ b/bottleneck/tests/data/test_388_A
@@ -0,0 +1,3 @@
+89 163
+54 98
+45 86
diff --git a/bottleneck/tests/data/test_388_B b/bottleneck/tests/data/test_388_B
new file mode 100644
index 0000000..025fdc6
--- /dev/null
+++ b/bottleneck/tests/data/test_388_B
@@ -0,0 +1,3 @@
+83 139
+91 174
+74 93
diff --git a/bottleneck/tests/data/test_389_A b/bottleneck/tests/data/test_389_A
new file mode 100644
index 0000000..5fa0b26
--- /dev/null
+++ b/bottleneck/tests/data/test_389_A
@@ -0,0 +1,3 @@
+93 165
+72 168
+84 113
diff --git a/bottleneck/tests/data/test_389_B b/bottleneck/tests/data/test_389_B
new file mode 100644
index 0000000..7ebd7f3
--- /dev/null
+++ b/bottleneck/tests/data/test_389_B
@@ -0,0 +1,3 @@
+88 140
+82 133
+69 110
diff --git a/bottleneck/tests/data/test_390_A b/bottleneck/tests/data/test_390_A
new file mode 100644
index 0000000..9f2c33d
--- /dev/null
+++ b/bottleneck/tests/data/test_390_A
@@ -0,0 +1,3 @@
+90 139
+28 95
+66 131
diff --git a/bottleneck/tests/data/test_390_B b/bottleneck/tests/data/test_390_B
new file mode 100644
index 0000000..833af00
--- /dev/null
+++ b/bottleneck/tests/data/test_390_B
@@ -0,0 +1,3 @@
+79 116
+46 68
+39 102
diff --git a/bottleneck/tests/data/test_391_A b/bottleneck/tests/data/test_391_A
new file mode 100644
index 0000000..f353fda
--- /dev/null
+++ b/bottleneck/tests/data/test_391_A
@@ -0,0 +1,3 @@
+38 51
+43 103
+80 129
diff --git a/bottleneck/tests/data/test_391_B b/bottleneck/tests/data/test_391_B
new file mode 100644
index 0000000..edff01f
--- /dev/null
+++ b/bottleneck/tests/data/test_391_B
@@ -0,0 +1,3 @@
+22 116
+2 92
+13 109
diff --git a/bottleneck/tests/data/test_392_A b/bottleneck/tests/data/test_392_A
new file mode 100644
index 0000000..317da32
--- /dev/null
+++ b/bottleneck/tests/data/test_392_A
@@ -0,0 +1,3 @@
+10 15
+48 118
+86 151
diff --git a/bottleneck/tests/data/test_392_B b/bottleneck/tests/data/test_392_B
new file mode 100644
index 0000000..c8cb61c
--- /dev/null
+++ b/bottleneck/tests/data/test_392_B
@@ -0,0 +1,3 @@
+73 173
+27 46
+73 146
diff --git a/bottleneck/tests/data/test_393_A b/bottleneck/tests/data/test_393_A
new file mode 100644
index 0000000..10b537c
--- /dev/null
+++ b/bottleneck/tests/data/test_393_A
@@ -0,0 +1,3 @@
+68 103
+89 121
+98 113
diff --git a/bottleneck/tests/data/test_393_B b/bottleneck/tests/data/test_393_B
new file mode 100644
index 0000000..24bc23a
--- /dev/null
+++ b/bottleneck/tests/data/test_393_B
@@ -0,0 +1,3 @@
+68 100
+41 63
+12 41
diff --git a/bottleneck/tests/data/test_394_A b/bottleneck/tests/data/test_394_A
new file mode 100644
index 0000000..e626e4a
--- /dev/null
+++ b/bottleneck/tests/data/test_394_A
@@ -0,0 +1,3 @@
+16 63
+5 58
+73 84
diff --git a/bottleneck/tests/data/test_394_B b/bottleneck/tests/data/test_394_B
new file mode 100644
index 0000000..24e086f
--- /dev/null
+++ b/bottleneck/tests/data/test_394_B
@@ -0,0 +1,3 @@
+86 134
+41 102
+14 107
diff --git a/bottleneck/tests/data/test_395_A b/bottleneck/tests/data/test_395_A
new file mode 100644
index 0000000..fa5d9e1
--- /dev/null
+++ b/bottleneck/tests/data/test_395_A
@@ -0,0 +1,3 @@
+76 152
+99 166
+91 110
diff --git a/bottleneck/tests/data/test_395_B b/bottleneck/tests/data/test_395_B
new file mode 100644
index 0000000..8cc1049
--- /dev/null
+++ b/bottleneck/tests/data/test_395_B
@@ -0,0 +1,3 @@
+42 109
+54 89
+51 113
diff --git a/bottleneck/tests/data/test_396_A b/bottleneck/tests/data/test_396_A
new file mode 100644
index 0000000..ab2ac42
--- /dev/null
+++ b/bottleneck/tests/data/test_396_A
@@ -0,0 +1,3 @@
+0 22
+81 139
+26 41
diff --git a/bottleneck/tests/data/test_396_B b/bottleneck/tests/data/test_396_B
new file mode 100644
index 0000000..dd8a3d4
--- /dev/null
+++ b/bottleneck/tests/data/test_396_B
@@ -0,0 +1,3 @@
+76 123
+23 24
+23 118
diff --git a/bottleneck/tests/data/test_397_A b/bottleneck/tests/data/test_397_A
new file mode 100644
index 0000000..683bdca
--- /dev/null
+++ b/bottleneck/tests/data/test_397_A
@@ -0,0 +1,3 @@
+53 128
+82 162
+34 127
diff --git a/bottleneck/tests/data/test_397_B b/bottleneck/tests/data/test_397_B
new file mode 100644
index 0000000..a7b2d72
--- /dev/null
+++ b/bottleneck/tests/data/test_397_B
@@ -0,0 +1,3 @@
+49 95
+82 140
+21 92
diff --git a/bottleneck/tests/data/test_398_A b/bottleneck/tests/data/test_398_A
new file mode 100644
index 0000000..d802d50
--- /dev/null
+++ b/bottleneck/tests/data/test_398_A
@@ -0,0 +1,3 @@
+37 98
+42 125
+79 99
diff --git a/bottleneck/tests/data/test_398_B b/bottleneck/tests/data/test_398_B
new file mode 100644
index 0000000..9e5b5e1
--- /dev/null
+++ b/bottleneck/tests/data/test_398_B
@@ -0,0 +1,3 @@
+48 91
+49 115
+65 158
diff --git a/bottleneck/tests/data/test_399_A b/bottleneck/tests/data/test_399_A
new file mode 100644
index 0000000..204dfdf
--- /dev/null
+++ b/bottleneck/tests/data/test_399_A
@@ -0,0 +1,3 @@
+87 153
+22 28
+68 72
diff --git a/bottleneck/tests/data/test_399_B b/bottleneck/tests/data/test_399_B
new file mode 100644
index 0000000..58cb084
--- /dev/null
+++ b/bottleneck/tests/data/test_399_B
@@ -0,0 +1,3 @@
+33 93
+3 10
+21 32
diff --git a/bottleneck/tests/data/test_400_A b/bottleneck/tests/data/test_400_A
new file mode 100644
index 0000000..b867cf5
--- /dev/null
+++ b/bottleneck/tests/data/test_400_A
@@ -0,0 +1,4 @@
+55 89
+35 85
+62 84
+84 151
diff --git a/bottleneck/tests/data/test_400_B b/bottleneck/tests/data/test_400_B
new file mode 100644
index 0000000..18df91d
--- /dev/null
+++ b/bottleneck/tests/data/test_400_B
@@ -0,0 +1,4 @@
+37 89
+45 56
+4 79
+86 139
diff --git a/bottleneck/tests/data/test_401_A b/bottleneck/tests/data/test_401_A
new file mode 100644
index 0000000..0f03308
--- /dev/null
+++ b/bottleneck/tests/data/test_401_A
@@ -0,0 +1,4 @@
+15 34
+2 72
+14 50
+58 86
diff --git a/bottleneck/tests/data/test_401_B b/bottleneck/tests/data/test_401_B
new file mode 100644
index 0000000..b517be8
--- /dev/null
+++ b/bottleneck/tests/data/test_401_B
@@ -0,0 +1,4 @@
+85 97
+24 54
+44 45
+75 171
diff --git a/bottleneck/tests/data/test_402_A b/bottleneck/tests/data/test_402_A
new file mode 100644
index 0000000..6a6f79f
--- /dev/null
+++ b/bottleneck/tests/data/test_402_A
@@ -0,0 +1,4 @@
+97 167
+17 65
+82 157
+88 110
diff --git a/bottleneck/tests/data/test_402_B b/bottleneck/tests/data/test_402_B
new file mode 100644
index 0000000..6585f2b
--- /dev/null
+++ b/bottleneck/tests/data/test_402_B
@@ -0,0 +1,4 @@
+69 87
+32 52
+71 92
+38 91
diff --git a/bottleneck/tests/data/test_403_A b/bottleneck/tests/data/test_403_A
new file mode 100644
index 0000000..8b5929a
--- /dev/null
+++ b/bottleneck/tests/data/test_403_A
@@ -0,0 +1,4 @@
+75 84
+86 184
+46 132
+79 136
diff --git a/bottleneck/tests/data/test_403_B b/bottleneck/tests/data/test_403_B
new file mode 100644
index 0000000..71f089f
--- /dev/null
+++ b/bottleneck/tests/data/test_403_B
@@ -0,0 +1,4 @@
+41 132
+44 72
+6 105
+91 187
diff --git a/bottleneck/tests/data/test_404_A b/bottleneck/tests/data/test_404_A
new file mode 100644
index 0000000..10add8e
--- /dev/null
+++ b/bottleneck/tests/data/test_404_A
@@ -0,0 +1,4 @@
+28 95
+43 126
+75 105
+2 101
diff --git a/bottleneck/tests/data/test_404_B b/bottleneck/tests/data/test_404_B
new file mode 100644
index 0000000..b38a7a7
--- /dev/null
+++ b/bottleneck/tests/data/test_404_B
@@ -0,0 +1,4 @@
+49 56
+50 116
+54 132
+55 94
diff --git a/bottleneck/tests/data/test_405_A b/bottleneck/tests/data/test_405_A
new file mode 100644
index 0000000..6cab1bd
--- /dev/null
+++ b/bottleneck/tests/data/test_405_A
@@ -0,0 +1,4 @@
+53 120
+12 15
+80 83
+79 96
diff --git a/bottleneck/tests/data/test_405_B b/bottleneck/tests/data/test_405_B
new file mode 100644
index 0000000..96645aa
--- /dev/null
+++ b/bottleneck/tests/data/test_405_B
@@ -0,0 +1,4 @@
+41 113
+17 18
+22 39
+89 135
diff --git a/bottleneck/tests/data/test_406_A b/bottleneck/tests/data/test_406_A
new file mode 100644
index 0000000..cf08c48
--- /dev/null
+++ b/bottleneck/tests/data/test_406_A
@@ -0,0 +1,4 @@
+88 168
+26 35
+96 126
+84 102
diff --git a/bottleneck/tests/data/test_406_B b/bottleneck/tests/data/test_406_B
new file mode 100644
index 0000000..b4ca0a0
--- /dev/null
+++ b/bottleneck/tests/data/test_406_B
@@ -0,0 +1,4 @@
+81 173
+76 111
+2 15
+44 142
diff --git a/bottleneck/tests/data/test_407_A b/bottleneck/tests/data/test_407_A
new file mode 100644
index 0000000..2372aba
--- /dev/null
+++ b/bottleneck/tests/data/test_407_A
@@ -0,0 +1,4 @@
+55 92
+95 170
+51 149
+76 156
diff --git a/bottleneck/tests/data/test_407_B b/bottleneck/tests/data/test_407_B
new file mode 100644
index 0000000..bd43334
--- /dev/null
+++ b/bottleneck/tests/data/test_407_B
@@ -0,0 +1,4 @@
+55 100
+17 86
+37 66
+97 131
diff --git a/bottleneck/tests/data/test_408_A b/bottleneck/tests/data/test_408_A
new file mode 100644
index 0000000..91652d4
--- /dev/null
+++ b/bottleneck/tests/data/test_408_A
@@ -0,0 +1,4 @@
+3 9
+50 134
+50 115
+30 82
diff --git a/bottleneck/tests/data/test_408_B b/bottleneck/tests/data/test_408_B
new file mode 100644
index 0000000..5f936a7
--- /dev/null
+++ b/bottleneck/tests/data/test_408_B
@@ -0,0 +1,4 @@
+57 103
+83 173
+20 58
+74 93
diff --git a/bottleneck/tests/data/test_409_A b/bottleneck/tests/data/test_409_A
new file mode 100644
index 0000000..b4d01d2
--- /dev/null
+++ b/bottleneck/tests/data/test_409_A
@@ -0,0 +1,4 @@
+87 144
+33 79
+44 110
+42 92
diff --git a/bottleneck/tests/data/test_409_B b/bottleneck/tests/data/test_409_B
new file mode 100644
index 0000000..4e15e41
--- /dev/null
+++ b/bottleneck/tests/data/test_409_B
@@ -0,0 +1,4 @@
+2 39
+82 170
+1 40
+50 115
diff --git a/bottleneck/tests/data/test_410_A b/bottleneck/tests/data/test_410_A
new file mode 100644
index 0000000..c02ab24
--- /dev/null
+++ b/bottleneck/tests/data/test_410_A
@@ -0,0 +1,4 @@
+15 80
+70 160
+52 144
+100 134
diff --git a/bottleneck/tests/data/test_410_B b/bottleneck/tests/data/test_410_B
new file mode 100644
index 0000000..d000095
--- /dev/null
+++ b/bottleneck/tests/data/test_410_B
@@ -0,0 +1,4 @@
+87 144
+43 91
+68 77
+79 172
diff --git a/bottleneck/tests/data/test_411_A b/bottleneck/tests/data/test_411_A
new file mode 100644
index 0000000..8130c4a
--- /dev/null
+++ b/bottleneck/tests/data/test_411_A
@@ -0,0 +1,4 @@
+81 158
+50 142
+83 129
+74 85
diff --git a/bottleneck/tests/data/test_411_B b/bottleneck/tests/data/test_411_B
new file mode 100644
index 0000000..e53f61f
--- /dev/null
+++ b/bottleneck/tests/data/test_411_B
@@ -0,0 +1,4 @@
+31 115
+57 108
+83 135
+2 26
diff --git a/bottleneck/tests/data/test_412_A b/bottleneck/tests/data/test_412_A
new file mode 100644
index 0000000..34a88b0
--- /dev/null
+++ b/bottleneck/tests/data/test_412_A
@@ -0,0 +1,4 @@
+5 31
+39 91
+24 75
+93 128
diff --git a/bottleneck/tests/data/test_412_B b/bottleneck/tests/data/test_412_B
new file mode 100644
index 0000000..a163ece
--- /dev/null
+++ b/bottleneck/tests/data/test_412_B
@@ -0,0 +1,4 @@
+0 76
+97 144
+55 92
+1 67
diff --git a/bottleneck/tests/data/test_413_A b/bottleneck/tests/data/test_413_A
new file mode 100644
index 0000000..61d6f70
--- /dev/null
+++ b/bottleneck/tests/data/test_413_A
@@ -0,0 +1,4 @@
+44 111
+69 88
+8 80
+78 113
diff --git a/bottleneck/tests/data/test_413_B b/bottleneck/tests/data/test_413_B
new file mode 100644
index 0000000..5b9dc54
--- /dev/null
+++ b/bottleneck/tests/data/test_413_B
@@ -0,0 +1,4 @@
+87 159
+53 114
+70 136
+63 103
diff --git a/bottleneck/tests/data/test_414_A b/bottleneck/tests/data/test_414_A
new file mode 100644
index 0000000..933f1e4
--- /dev/null
+++ b/bottleneck/tests/data/test_414_A
@@ -0,0 +1,4 @@
+39 44
+29 113
+85 158
+59 77
diff --git a/bottleneck/tests/data/test_414_B b/bottleneck/tests/data/test_414_B
new file mode 100644
index 0000000..b54a5fe
--- /dev/null
+++ b/bottleneck/tests/data/test_414_B
@@ -0,0 +1,4 @@
+14 109
+5 90
+85 134
+60 88
diff --git a/bottleneck/tests/data/test_415_A b/bottleneck/tests/data/test_415_A
new file mode 100644
index 0000000..bbce6b8
--- /dev/null
+++ b/bottleneck/tests/data/test_415_A
@@ -0,0 +1,4 @@
+23 70
+40 46
+21 109
+50 149
diff --git a/bottleneck/tests/data/test_415_B b/bottleneck/tests/data/test_415_B
new file mode 100644
index 0000000..3943a46
--- /dev/null
+++ b/bottleneck/tests/data/test_415_B
@@ -0,0 +1,4 @@
+14 80
+74 154
+50 70
+90 173
diff --git a/bottleneck/tests/data/test_416_A b/bottleneck/tests/data/test_416_A
new file mode 100644
index 0000000..c7a9a3d
--- /dev/null
+++ b/bottleneck/tests/data/test_416_A
@@ -0,0 +1,4 @@
+23 53
+20 94
+89 105
+98 146
diff --git a/bottleneck/tests/data/test_416_B b/bottleneck/tests/data/test_416_B
new file mode 100644
index 0000000..6e8c430
--- /dev/null
+++ b/bottleneck/tests/data/test_416_B
@@ -0,0 +1,4 @@
+73 74
+62 124
+95 126
+62 141
diff --git a/bottleneck/tests/data/test_417_A b/bottleneck/tests/data/test_417_A
new file mode 100644
index 0000000..6e5688c
--- /dev/null
+++ b/bottleneck/tests/data/test_417_A
@@ -0,0 +1,4 @@
+66 148
+86 117
+4 32
+95 146
diff --git a/bottleneck/tests/data/test_417_B b/bottleneck/tests/data/test_417_B
new file mode 100644
index 0000000..2bfa9c2
--- /dev/null
+++ b/bottleneck/tests/data/test_417_B
@@ -0,0 +1,4 @@
+87 111
+23 122
+62 95
+12 22
diff --git a/bottleneck/tests/data/test_418_A b/bottleneck/tests/data/test_418_A
new file mode 100644
index 0000000..9ab98de
--- /dev/null
+++ b/bottleneck/tests/data/test_418_A
@@ -0,0 +1,4 @@
+29 122
+71 102
+70 109
+43 120
diff --git a/bottleneck/tests/data/test_418_B b/bottleneck/tests/data/test_418_B
new file mode 100644
index 0000000..f3231de
--- /dev/null
+++ b/bottleneck/tests/data/test_418_B
@@ -0,0 +1,4 @@
+45 121
+58 64
+57 105
+41 138
diff --git a/bottleneck/tests/data/test_419_A b/bottleneck/tests/data/test_419_A
new file mode 100644
index 0000000..825d191
--- /dev/null
+++ b/bottleneck/tests/data/test_419_A
@@ -0,0 +1,4 @@
+28 111
+100 167
+17 59
+10 38
diff --git a/bottleneck/tests/data/test_419_B b/bottleneck/tests/data/test_419_B
new file mode 100644
index 0000000..101be4f
--- /dev/null
+++ b/bottleneck/tests/data/test_419_B
@@ -0,0 +1,4 @@
+63 99
+78 143
+67 150
+24 77
diff --git a/bottleneck/tests/data/test_420_A b/bottleneck/tests/data/test_420_A
new file mode 100644
index 0000000..455d829
--- /dev/null
+++ b/bottleneck/tests/data/test_420_A
@@ -0,0 +1,5 @@
+89 160
+26 36
+37 61
+95 137
+41 68
diff --git a/bottleneck/tests/data/test_420_B b/bottleneck/tests/data/test_420_B
new file mode 100644
index 0000000..27e1c6d
--- /dev/null
+++ b/bottleneck/tests/data/test_420_B
@@ -0,0 +1,5 @@
+100 185
+31 112
+78 129
+49 143
+74 171
diff --git a/bottleneck/tests/data/test_421_A b/bottleneck/tests/data/test_421_A
new file mode 100644
index 0000000..c08ddf1
--- /dev/null
+++ b/bottleneck/tests/data/test_421_A
@@ -0,0 +1,5 @@
+27 127
+2 101
+42 52
+5 81
+4 62
diff --git a/bottleneck/tests/data/test_421_B b/bottleneck/tests/data/test_421_B
new file mode 100644
index 0000000..37cbda8
--- /dev/null
+++ b/bottleneck/tests/data/test_421_B
@@ -0,0 +1,5 @@
+27 40
+67 78
+50 122
+41 95
+1 63
diff --git a/bottleneck/tests/data/test_422_A b/bottleneck/tests/data/test_422_A
new file mode 100644
index 0000000..348a116
--- /dev/null
+++ b/bottleneck/tests/data/test_422_A
@@ -0,0 +1,5 @@
+54 143
+21 24
+96 180
+13 113
+93 134
diff --git a/bottleneck/tests/data/test_422_B b/bottleneck/tests/data/test_422_B
new file mode 100644
index 0000000..0f33ae9
--- /dev/null
+++ b/bottleneck/tests/data/test_422_B
@@ -0,0 +1,5 @@
+5 18
+63 106
+29 94
+59 155
+66 155
diff --git a/bottleneck/tests/data/test_423_A b/bottleneck/tests/data/test_423_A
new file mode 100644
index 0000000..b3b448e
--- /dev/null
+++ b/bottleneck/tests/data/test_423_A
@@ -0,0 +1,5 @@
+47 88
+80 138
+75 129
+2 90
+58 133
diff --git a/bottleneck/tests/data/test_423_B b/bottleneck/tests/data/test_423_B
new file mode 100644
index 0000000..873a875
--- /dev/null
+++ b/bottleneck/tests/data/test_423_B
@@ -0,0 +1,5 @@
+77 129
+99 174
+93 104
+71 93
+18 26
diff --git a/bottleneck/tests/data/test_424_A b/bottleneck/tests/data/test_424_A
new file mode 100644
index 0000000..ab20fc1
--- /dev/null
+++ b/bottleneck/tests/data/test_424_A
@@ -0,0 +1,5 @@
+73 167
+50 133
+25 41
+46 87
+27 93
diff --git a/bottleneck/tests/data/test_424_B b/bottleneck/tests/data/test_424_B
new file mode 100644
index 0000000..a0f5059
--- /dev/null
+++ b/bottleneck/tests/data/test_424_B
@@ -0,0 +1,5 @@
+71 113
+54 63
+0 33
+27 127
+14 79
diff --git a/bottleneck/tests/data/test_425_A b/bottleneck/tests/data/test_425_A
new file mode 100644
index 0000000..7116974
--- /dev/null
+++ b/bottleneck/tests/data/test_425_A
@@ -0,0 +1,5 @@
+90 168
+44 63
+83 88
+80 81
+13 94
diff --git a/bottleneck/tests/data/test_425_B b/bottleneck/tests/data/test_425_B
new file mode 100644
index 0000000..6f1e713
--- /dev/null
+++ b/bottleneck/tests/data/test_425_B
@@ -0,0 +1,5 @@
+66 161
+99 137
+71 147
+58 80
+42 96
diff --git a/bottleneck/tests/data/test_426_A b/bottleneck/tests/data/test_426_A
new file mode 100644
index 0000000..6404cdd
--- /dev/null
+++ b/bottleneck/tests/data/test_426_A
@@ -0,0 +1,5 @@
+90 161
+75 121
+54 111
+21 84
+73 106
diff --git a/bottleneck/tests/data/test_426_B b/bottleneck/tests/data/test_426_B
new file mode 100644
index 0000000..06fbc21
--- /dev/null
+++ b/bottleneck/tests/data/test_426_B
@@ -0,0 +1,5 @@
+82 109
+85 100
+26 92
+52 91
+23 83
diff --git a/bottleneck/tests/data/test_427_A b/bottleneck/tests/data/test_427_A
new file mode 100644
index 0000000..ab36b49
--- /dev/null
+++ b/bottleneck/tests/data/test_427_A
@@ -0,0 +1,5 @@
+15 28
+39 93
+1 43
+16 98
+81 167
diff --git a/bottleneck/tests/data/test_427_B b/bottleneck/tests/data/test_427_B
new file mode 100644
index 0000000..eb34e17
--- /dev/null
+++ b/bottleneck/tests/data/test_427_B
@@ -0,0 +1,5 @@
+57 70
+99 181
+26 81
+13 32
+95 153
diff --git a/bottleneck/tests/data/test_428_A b/bottleneck/tests/data/test_428_A
new file mode 100644
index 0000000..12957ab
--- /dev/null
+++ b/bottleneck/tests/data/test_428_A
@@ -0,0 +1,5 @@
+85 155
+86 173
+63 88
+50 84
+75 85
diff --git a/bottleneck/tests/data/test_428_B b/bottleneck/tests/data/test_428_B
new file mode 100644
index 0000000..b0fd1c4
--- /dev/null
+++ b/bottleneck/tests/data/test_428_B
@@ -0,0 +1,5 @@
+70 113
+92 93
+57 103
+40 81
+9 47
diff --git a/bottleneck/tests/data/test_429_A b/bottleneck/tests/data/test_429_A
new file mode 100644
index 0000000..0cdda41
--- /dev/null
+++ b/bottleneck/tests/data/test_429_A
@@ -0,0 +1,5 @@
+90 165
+83 128
+5 28
+68 121
+1 67
diff --git a/bottleneck/tests/data/test_429_B b/bottleneck/tests/data/test_429_B
new file mode 100644
index 0000000..0180a92
--- /dev/null
+++ b/bottleneck/tests/data/test_429_B
@@ -0,0 +1,5 @@
+31 34
+88 147
+17 91
+46 138
+13 81
diff --git a/bottleneck/tests/data/test_430_A b/bottleneck/tests/data/test_430_A
new file mode 100644
index 0000000..03029c6
--- /dev/null
+++ b/bottleneck/tests/data/test_430_A
@@ -0,0 +1,5 @@
+85 181
+93 118
+77 167
+39 110
+21 22
diff --git a/bottleneck/tests/data/test_430_B b/bottleneck/tests/data/test_430_B
new file mode 100644
index 0000000..9c58f1f
--- /dev/null
+++ b/bottleneck/tests/data/test_430_B
@@ -0,0 +1,5 @@
+59 88
+28 29
+56 57
+3 73
+78 93
diff --git a/bottleneck/tests/data/test_431_A b/bottleneck/tests/data/test_431_A
new file mode 100644
index 0000000..272ec7d
--- /dev/null
+++ b/bottleneck/tests/data/test_431_A
@@ -0,0 +1,5 @@
+26 28
+90 172
+46 118
+25 102
+78 141
diff --git a/bottleneck/tests/data/test_431_B b/bottleneck/tests/data/test_431_B
new file mode 100644
index 0000000..9ccc9d1
--- /dev/null
+++ b/bottleneck/tests/data/test_431_B
@@ -0,0 +1,5 @@
+25 107
+61 128
+24 111
+47 48
+70 96
diff --git a/bottleneck/tests/data/test_432_A b/bottleneck/tests/data/test_432_A
new file mode 100644
index 0000000..91dbacb
--- /dev/null
+++ b/bottleneck/tests/data/test_432_A
@@ -0,0 +1,5 @@
+53 78
+16 74
+6 106
+46 145
+33 41
diff --git a/bottleneck/tests/data/test_432_B b/bottleneck/tests/data/test_432_B
new file mode 100644
index 0000000..47afd85
--- /dev/null
+++ b/bottleneck/tests/data/test_432_B
@@ -0,0 +1,5 @@
+16 100
+70 119
+42 137
+94 164
+94 105
diff --git a/bottleneck/tests/data/test_433_A b/bottleneck/tests/data/test_433_A
new file mode 100644
index 0000000..1577e13
--- /dev/null
+++ b/bottleneck/tests/data/test_433_A
@@ -0,0 +1,5 @@
+30 97
+79 93
+42 97
+88 140
+85 131
diff --git a/bottleneck/tests/data/test_433_B b/bottleneck/tests/data/test_433_B
new file mode 100644
index 0000000..f63aea0
--- /dev/null
+++ b/bottleneck/tests/data/test_433_B
@@ -0,0 +1,5 @@
+38 55
+29 129
+30 97
+11 43
+26 59
diff --git a/bottleneck/tests/data/test_434_A b/bottleneck/tests/data/test_434_A
new file mode 100644
index 0000000..5ef7655
--- /dev/null
+++ b/bottleneck/tests/data/test_434_A
@@ -0,0 +1,5 @@
+63 102
+32 38
+98 179
+89 136
+39 67
diff --git a/bottleneck/tests/data/test_434_B b/bottleneck/tests/data/test_434_B
new file mode 100644
index 0000000..a089420
--- /dev/null
+++ b/bottleneck/tests/data/test_434_B
@@ -0,0 +1,5 @@
+92 101
+9 11
+47 138
+95 176
+8 87
diff --git a/bottleneck/tests/data/test_435_A b/bottleneck/tests/data/test_435_A
new file mode 100644
index 0000000..9021906
--- /dev/null
+++ b/bottleneck/tests/data/test_435_A
@@ -0,0 +1,5 @@
+34 98
+33 80
+18 85
+36 100
+60 64
diff --git a/bottleneck/tests/data/test_435_B b/bottleneck/tests/data/test_435_B
new file mode 100644
index 0000000..225d87c
--- /dev/null
+++ b/bottleneck/tests/data/test_435_B
@@ -0,0 +1,5 @@
+96 175
+12 80
+79 166
+28 88
+81 150
diff --git a/bottleneck/tests/data/test_436_A b/bottleneck/tests/data/test_436_A
new file mode 100644
index 0000000..4004cfe
--- /dev/null
+++ b/bottleneck/tests/data/test_436_A
@@ -0,0 +1,5 @@
+59 101
+23 98
+15 108
+65 119
+67 91
diff --git a/bottleneck/tests/data/test_436_B b/bottleneck/tests/data/test_436_B
new file mode 100644
index 0000000..8fbd097
--- /dev/null
+++ b/bottleneck/tests/data/test_436_B
@@ -0,0 +1,5 @@
+23 86
+58 123
+18 62
+100 165
+6 105
diff --git a/bottleneck/tests/data/test_437_A b/bottleneck/tests/data/test_437_A
new file mode 100644
index 0000000..8210316
--- /dev/null
+++ b/bottleneck/tests/data/test_437_A
@@ -0,0 +1,5 @@
+10 38
+90 165
+35 122
+100 170
+62 93
diff --git a/bottleneck/tests/data/test_437_B b/bottleneck/tests/data/test_437_B
new file mode 100644
index 0000000..c7e55b3
--- /dev/null
+++ b/bottleneck/tests/data/test_437_B
@@ -0,0 +1,5 @@
+27 73
+87 187
+78 176
+44 82
+58 77
diff --git a/bottleneck/tests/data/test_438_A b/bottleneck/tests/data/test_438_A
new file mode 100644
index 0000000..e2f48a4
--- /dev/null
+++ b/bottleneck/tests/data/test_438_A
@@ -0,0 +1,5 @@
+14 74
+65 127
+21 51
+19 42
+58 96
diff --git a/bottleneck/tests/data/test_438_B b/bottleneck/tests/data/test_438_B
new file mode 100644
index 0000000..eb84689
--- /dev/null
+++ b/bottleneck/tests/data/test_438_B
@@ -0,0 +1,5 @@
+97 165
+49 116
+73 83
+6 8
+99 153
diff --git a/bottleneck/tests/data/test_439_A b/bottleneck/tests/data/test_439_A
new file mode 100644
index 0000000..fc36518
--- /dev/null
+++ b/bottleneck/tests/data/test_439_A
@@ -0,0 +1,5 @@
+66 120
+59 119
+40 56
+42 120
+48 140
diff --git a/bottleneck/tests/data/test_439_B b/bottleneck/tests/data/test_439_B
new file mode 100644
index 0000000..b9de5b7
--- /dev/null
+++ b/bottleneck/tests/data/test_439_B
@@ -0,0 +1,5 @@
+25 94
+94 157
+64 156
+79 100
+28 98
diff --git a/bottleneck/tests/data/test_440_A b/bottleneck/tests/data/test_440_A
new file mode 100644
index 0000000..4f0cdc2
--- /dev/null
+++ b/bottleneck/tests/data/test_440_A
@@ -0,0 +1,6 @@
+25 32
+90 153
+23 86
+4 29
+52 124
+17 75
diff --git a/bottleneck/tests/data/test_440_B b/bottleneck/tests/data/test_440_B
new file mode 100644
index 0000000..c06754e
--- /dev/null
+++ b/bottleneck/tests/data/test_440_B
@@ -0,0 +1,6 @@
+47 132
+64 156
+96 149
+31 94
+86 94
+40 63
diff --git a/bottleneck/tests/data/test_441_A b/bottleneck/tests/data/test_441_A
new file mode 100644
index 0000000..f1d7779
--- /dev/null
+++ b/bottleneck/tests/data/test_441_A
@@ -0,0 +1,6 @@
+45 121
+61 95
+57 68
+10 82
+90 147
+80 179
diff --git a/bottleneck/tests/data/test_441_B b/bottleneck/tests/data/test_441_B
new file mode 100644
index 0000000..039c8db
--- /dev/null
+++ b/bottleneck/tests/data/test_441_B
@@ -0,0 +1,6 @@
+97 122
+44 109
+15 48
+49 106
+30 65
+66 70
diff --git a/bottleneck/tests/data/test_442_A b/bottleneck/tests/data/test_442_A
new file mode 100644
index 0000000..9a22bd2
--- /dev/null
+++ b/bottleneck/tests/data/test_442_A
@@ -0,0 +1,6 @@
+44 47
+6 81
+66 163
+74 144
+66 135
+62 63
diff --git a/bottleneck/tests/data/test_442_B b/bottleneck/tests/data/test_442_B
new file mode 100644
index 0000000..9663228
--- /dev/null
+++ b/bottleneck/tests/data/test_442_B
@@ -0,0 +1,6 @@
+41 65
+52 109
+96 175
+80 93
+32 78
+97 124
diff --git a/bottleneck/tests/data/test_443_A b/bottleneck/tests/data/test_443_A
new file mode 100644
index 0000000..27d9885
--- /dev/null
+++ b/bottleneck/tests/data/test_443_A
@@ -0,0 +1,6 @@
+19 38
+86 142
+86 132
+32 118
+73 138
+25 83
diff --git a/bottleneck/tests/data/test_443_B b/bottleneck/tests/data/test_443_B
new file mode 100644
index 0000000..c084218
--- /dev/null
+++ b/bottleneck/tests/data/test_443_B
@@ -0,0 +1,6 @@
+78 165
+88 138
+5 29
+81 109
+4 96
+69 130
diff --git a/bottleneck/tests/data/test_444_A b/bottleneck/tests/data/test_444_A
new file mode 100644
index 0000000..86dfb79
--- /dev/null
+++ b/bottleneck/tests/data/test_444_A
@@ -0,0 +1,6 @@
+22 23
+59 111
+65 91
+0 56
+92 156
+67 69
diff --git a/bottleneck/tests/data/test_444_B b/bottleneck/tests/data/test_444_B
new file mode 100644
index 0000000..b7f54f9
--- /dev/null
+++ b/bottleneck/tests/data/test_444_B
@@ -0,0 +1,6 @@
+20 39
+0 44
+34 84
+3 30
+70 96
+92 127
diff --git a/bottleneck/tests/data/test_445_A b/bottleneck/tests/data/test_445_A
new file mode 100644
index 0000000..6ec29f6
--- /dev/null
+++ b/bottleneck/tests/data/test_445_A
@@ -0,0 +1,6 @@
+49 64
+36 102
+43 120
+98 194
+65 110
+49 89
diff --git a/bottleneck/tests/data/test_445_B b/bottleneck/tests/data/test_445_B
new file mode 100644
index 0000000..7e5ce8e
--- /dev/null
+++ b/bottleneck/tests/data/test_445_B
@@ -0,0 +1,6 @@
+84 88
+42 132
+26 36
+11 91
+17 114
+37 70
diff --git a/bottleneck/tests/data/test_446_A b/bottleneck/tests/data/test_446_A
new file mode 100644
index 0000000..2e66159
--- /dev/null
+++ b/bottleneck/tests/data/test_446_A
@@ -0,0 +1,6 @@
+48 147
+86 146
+42 64
+39 111
+71 113
+59 63
diff --git a/bottleneck/tests/data/test_446_B b/bottleneck/tests/data/test_446_B
new file mode 100644
index 0000000..b4a4baa
--- /dev/null
+++ b/bottleneck/tests/data/test_446_B
@@ -0,0 +1,6 @@
+14 15
+64 163
+23 41
+4 90
+3 23
+66 68
diff --git a/bottleneck/tests/data/test_447_A b/bottleneck/tests/data/test_447_A
new file mode 100644
index 0000000..adbca26
--- /dev/null
+++ b/bottleneck/tests/data/test_447_A
@@ -0,0 +1,6 @@
+91 119
+93 186
+11 53
+85 87
+8 50
+69 84
diff --git a/bottleneck/tests/data/test_447_B b/bottleneck/tests/data/test_447_B
new file mode 100644
index 0000000..c996a99
--- /dev/null
+++ b/bottleneck/tests/data/test_447_B
@@ -0,0 +1,6 @@
+67 71
+77 143
+48 103
+80 121
+73 107
+18 36
diff --git a/bottleneck/tests/data/test_448_A b/bottleneck/tests/data/test_448_A
new file mode 100644
index 0000000..3b1d2ac
--- /dev/null
+++ b/bottleneck/tests/data/test_448_A
@@ -0,0 +1,6 @@
+99 127
+80 81
+72 138
+40 123
+76 120
+13 52
diff --git a/bottleneck/tests/data/test_448_B b/bottleneck/tests/data/test_448_B
new file mode 100644
index 0000000..358c96b
--- /dev/null
+++ b/bottleneck/tests/data/test_448_B
@@ -0,0 +1,6 @@
+94 105
+31 105
+2 50
+91 132
+63 86
+81 116
diff --git a/bottleneck/tests/data/test_449_A b/bottleneck/tests/data/test_449_A
new file mode 100644
index 0000000..1b9fdde
--- /dev/null
+++ b/bottleneck/tests/data/test_449_A
@@ -0,0 +1,6 @@
+99 164
+24 78
+75 119
+62 129
+93 117
+34 124
diff --git a/bottleneck/tests/data/test_449_B b/bottleneck/tests/data/test_449_B
new file mode 100644
index 0000000..39ca7bf
--- /dev/null
+++ b/bottleneck/tests/data/test_449_B
@@ -0,0 +1,6 @@
+5 101
+53 86
+58 92
+99 198
+48 57
+34 102
diff --git a/bottleneck/tests/data/test_450_A b/bottleneck/tests/data/test_450_A
new file mode 100644
index 0000000..c97d1bd
--- /dev/null
+++ b/bottleneck/tests/data/test_450_A
@@ -0,0 +1,6 @@
+98 112
+27 55
+36 69
+5 32
+36 85
+24 90
diff --git a/bottleneck/tests/data/test_450_B b/bottleneck/tests/data/test_450_B
new file mode 100644
index 0000000..038d497
--- /dev/null
+++ b/bottleneck/tests/data/test_450_B
@@ -0,0 +1,6 @@
+66 156
+74 158
+85 136
+4 53
+61 93
+13 37
diff --git a/bottleneck/tests/data/test_451_A b/bottleneck/tests/data/test_451_A
new file mode 100644
index 0000000..1c77ff4
--- /dev/null
+++ b/bottleneck/tests/data/test_451_A
@@ -0,0 +1,6 @@
+83 99
+42 129
+82 117
+35 132
+1 101
+53 115
diff --git a/bottleneck/tests/data/test_451_B b/bottleneck/tests/data/test_451_B
new file mode 100644
index 0000000..37c9b78
--- /dev/null
+++ b/bottleneck/tests/data/test_451_B
@@ -0,0 +1,6 @@
+18 102
+62 111
+17 40
+78 135
+20 23
+69 77
diff --git a/bottleneck/tests/data/test_452_A b/bottleneck/tests/data/test_452_A
new file mode 100644
index 0000000..24159ea
--- /dev/null
+++ b/bottleneck/tests/data/test_452_A
@@ -0,0 +1,6 @@
+12 65
+2 42
+61 93
+22 31
+66 139
+44 106
diff --git a/bottleneck/tests/data/test_452_B b/bottleneck/tests/data/test_452_B
new file mode 100644
index 0000000..602fb45
--- /dev/null
+++ b/bottleneck/tests/data/test_452_B
@@ -0,0 +1,6 @@
+88 156
+1 91
+7 42
+83 94
+50 133
+82 146
diff --git a/bottleneck/tests/data/test_453_A b/bottleneck/tests/data/test_453_A
new file mode 100644
index 0000000..aa29541
--- /dev/null
+++ b/bottleneck/tests/data/test_453_A
@@ -0,0 +1,6 @@
+39 50
+28 76
+83 87
+27 38
+85 120
+57 78
diff --git a/bottleneck/tests/data/test_453_B b/bottleneck/tests/data/test_453_B
new file mode 100644
index 0000000..7cce047
--- /dev/null
+++ b/bottleneck/tests/data/test_453_B
@@ -0,0 +1,6 @@
+59 106
+28 69
+91 189
+43 57
+32 33
+75 156
diff --git a/bottleneck/tests/data/test_454_A b/bottleneck/tests/data/test_454_A
new file mode 100644
index 0000000..3e5e41b
--- /dev/null
+++ b/bottleneck/tests/data/test_454_A
@@ -0,0 +1,6 @@
+32 39
+6 50
+72 153
+38 115
+23 45
+18 34
diff --git a/bottleneck/tests/data/test_454_B b/bottleneck/tests/data/test_454_B
new file mode 100644
index 0000000..e5e2305
--- /dev/null
+++ b/bottleneck/tests/data/test_454_B
@@ -0,0 +1,6 @@
+83 180
+76 118
+76 114
+95 192
+19 53
+42 81
diff --git a/bottleneck/tests/data/test_455_A b/bottleneck/tests/data/test_455_A
new file mode 100644
index 0000000..d06d256
--- /dev/null
+++ b/bottleneck/tests/data/test_455_A
@@ -0,0 +1,6 @@
+80 110
+12 104
+89 151
+71 168
+91 95
+27 55
diff --git a/bottleneck/tests/data/test_455_B b/bottleneck/tests/data/test_455_B
new file mode 100644
index 0000000..afdab0b
--- /dev/null
+++ b/bottleneck/tests/data/test_455_B
@@ -0,0 +1,6 @@
+68 166
+33 38
+66 158
+72 93
+66 96
+82 88
diff --git a/bottleneck/tests/data/test_456_A b/bottleneck/tests/data/test_456_A
new file mode 100644
index 0000000..7a30bf3
--- /dev/null
+++ b/bottleneck/tests/data/test_456_A
@@ -0,0 +1,6 @@
+72 114
+8 79
+19 50
+72 134
+94 108
+5 24
diff --git a/bottleneck/tests/data/test_456_B b/bottleneck/tests/data/test_456_B
new file mode 100644
index 0000000..a1a1329
--- /dev/null
+++ b/bottleneck/tests/data/test_456_B
@@ -0,0 +1,6 @@
+86 114
+38 105
+46 98
+20 90
+98 118
+52 142
diff --git a/bottleneck/tests/data/test_457_A b/bottleneck/tests/data/test_457_A
new file mode 100644
index 0000000..d5339ec
--- /dev/null
+++ b/bottleneck/tests/data/test_457_A
@@ -0,0 +1,6 @@
+70 109
+61 79
+55 152
+88 187
+64 136
+71 110
diff --git a/bottleneck/tests/data/test_457_B b/bottleneck/tests/data/test_457_B
new file mode 100644
index 0000000..e96c110
--- /dev/null
+++ b/bottleneck/tests/data/test_457_B
@@ -0,0 +1,6 @@
+57 128
+47 82
+87 96
+97 132
+23 41
+6 104
diff --git a/bottleneck/tests/data/test_458_A b/bottleneck/tests/data/test_458_A
new file mode 100644
index 0000000..a9287b2
--- /dev/null
+++ b/bottleneck/tests/data/test_458_A
@@ -0,0 +1,6 @@
+43 63
+79 80
+77 142
+50 116
+43 46
+45 139
diff --git a/bottleneck/tests/data/test_458_B b/bottleneck/tests/data/test_458_B
new file mode 100644
index 0000000..63b7c63
--- /dev/null
+++ b/bottleneck/tests/data/test_458_B
@@ -0,0 +1,6 @@
+69 79
+9 64
+29 115
+33 87
+5 100
+24 71
diff --git a/bottleneck/tests/data/test_459_A b/bottleneck/tests/data/test_459_A
new file mode 100644
index 0000000..f8a82f8
--- /dev/null
+++ b/bottleneck/tests/data/test_459_A
@@ -0,0 +1,6 @@
+90 94
+75 107
+80 88
+35 98
+53 84
+78 93
diff --git a/bottleneck/tests/data/test_459_B b/bottleneck/tests/data/test_459_B
new file mode 100644
index 0000000..dc645ee
--- /dev/null
+++ b/bottleneck/tests/data/test_459_B
@@ -0,0 +1,6 @@
+95 101
+29 59
+32 77
+17 19
+92 108
+6 19
diff --git a/bottleneck/tests/data/test_460_A b/bottleneck/tests/data/test_460_A
new file mode 100644
index 0000000..000c14e
--- /dev/null
+++ b/bottleneck/tests/data/test_460_A
@@ -0,0 +1,7 @@
+88 127
+65 145
+59 149
+69 152
+61 146
+28 90
+21 104
diff --git a/bottleneck/tests/data/test_460_B b/bottleneck/tests/data/test_460_B
new file mode 100644
index 0000000..4a7d4a3
--- /dev/null
+++ b/bottleneck/tests/data/test_460_B
@@ -0,0 +1,7 @@
+47 131
+59 153
+24 95
+63 96
+6 102
+91 98
+31 118
diff --git a/bottleneck/tests/data/test_461_A b/bottleneck/tests/data/test_461_A
new file mode 100644
index 0000000..aaebf2d
--- /dev/null
+++ b/bottleneck/tests/data/test_461_A
@@ -0,0 +1,7 @@
+57 67
+75 82
+63 88
+57 139
+67 103
+15 68
+100 117
diff --git a/bottleneck/tests/data/test_461_B b/bottleneck/tests/data/test_461_B
new file mode 100644
index 0000000..183fa51
--- /dev/null
+++ b/bottleneck/tests/data/test_461_B
@@ -0,0 +1,7 @@
+47 127
+9 35
+14 75
+29 92
+76 171
+9 56
+56 86
diff --git a/bottleneck/tests/data/test_462_A b/bottleneck/tests/data/test_462_A
new file mode 100644
index 0000000..df1936d
--- /dev/null
+++ b/bottleneck/tests/data/test_462_A
@@ -0,0 +1,7 @@
+0 90
+50 113
+73 149
+86 105
+20 105
+14 75
+41 115
diff --git a/bottleneck/tests/data/test_462_B b/bottleneck/tests/data/test_462_B
new file mode 100644
index 0000000..5be3bf0
--- /dev/null
+++ b/bottleneck/tests/data/test_462_B
@@ -0,0 +1,7 @@
+88 133
+47 100
+27 48
+54 153
+91 116
+90 150
+0 82
diff --git a/bottleneck/tests/data/test_463_A b/bottleneck/tests/data/test_463_A
new file mode 100644
index 0000000..c8776fe
--- /dev/null
+++ b/bottleneck/tests/data/test_463_A
@@ -0,0 +1,7 @@
+34 67
+34 92
+53 99
+64 155
+92 157
+16 55
+75 156
diff --git a/bottleneck/tests/data/test_463_B b/bottleneck/tests/data/test_463_B
new file mode 100644
index 0000000..a9f1273
--- /dev/null
+++ b/bottleneck/tests/data/test_463_B
@@ -0,0 +1,7 @@
+20 72
+99 146
+70 158
+4 38
+92 102
+20 32
+47 135
diff --git a/bottleneck/tests/data/test_464_A b/bottleneck/tests/data/test_464_A
new file mode 100644
index 0000000..98ff6a9
--- /dev/null
+++ b/bottleneck/tests/data/test_464_A
@@ -0,0 +1,7 @@
+69 149
+52 115
+32 82
+22 60
+55 56
+80 116
+62 72
diff --git a/bottleneck/tests/data/test_464_B b/bottleneck/tests/data/test_464_B
new file mode 100644
index 0000000..0e57b03
--- /dev/null
+++ b/bottleneck/tests/data/test_464_B
@@ -0,0 +1,7 @@
+81 121
+17 86
+57 141
+13 15
+66 80
+66 107
+76 80
diff --git a/bottleneck/tests/data/test_465_A b/bottleneck/tests/data/test_465_A
new file mode 100644
index 0000000..b164c7a
--- /dev/null
+++ b/bottleneck/tests/data/test_465_A
@@ -0,0 +1,7 @@
+8 34
+48 141
+61 122
+56 130
+58 158
+51 81
+32 100
diff --git a/bottleneck/tests/data/test_465_B b/bottleneck/tests/data/test_465_B
new file mode 100644
index 0000000..610a2a5
--- /dev/null
+++ b/bottleneck/tests/data/test_465_B
@@ -0,0 +1,7 @@
+8 89
+62 160
+27 109
+94 112
+59 140
+51 69
+52 136
diff --git a/bottleneck/tests/data/test_466_A b/bottleneck/tests/data/test_466_A
new file mode 100644
index 0000000..3c0052c
--- /dev/null
+++ b/bottleneck/tests/data/test_466_A
@@ -0,0 +1,7 @@
+54 113
+15 32
+94 138
+42 132
+84 136
+81 135
+4 62
diff --git a/bottleneck/tests/data/test_466_B b/bottleneck/tests/data/test_466_B
new file mode 100644
index 0000000..e8c16f8
--- /dev/null
+++ b/bottleneck/tests/data/test_466_B
@@ -0,0 +1,7 @@
+51 116
+81 147
+11 51
+76 148
+90 100
+3 100
+62 138
diff --git a/bottleneck/tests/data/test_467_A b/bottleneck/tests/data/test_467_A
new file mode 100644
index 0000000..69280bb
--- /dev/null
+++ b/bottleneck/tests/data/test_467_A
@@ -0,0 +1,7 @@
+40 43
+46 99
+90 137
+93 122
+38 45
+87 134
+48 146
diff --git a/bottleneck/tests/data/test_467_B b/bottleneck/tests/data/test_467_B
new file mode 100644
index 0000000..c857912
--- /dev/null
+++ b/bottleneck/tests/data/test_467_B
@@ -0,0 +1,7 @@
+22 23
+57 100
+84 162
+30 92
+65 75
+97 133
+47 117
diff --git a/bottleneck/tests/data/test_468_A b/bottleneck/tests/data/test_468_A
new file mode 100644
index 0000000..9f92c43
--- /dev/null
+++ b/bottleneck/tests/data/test_468_A
@@ -0,0 +1,7 @@
+93 128
+20 66
+72 134
+97 111
+64 99
+17 47
+12 58
diff --git a/bottleneck/tests/data/test_468_B b/bottleneck/tests/data/test_468_B
new file mode 100644
index 0000000..b20cdf4
--- /dev/null
+++ b/bottleneck/tests/data/test_468_B
@@ -0,0 +1,7 @@
+84 156
+42 142
+28 43
+83 179
+15 81
+51 113
+56 136
diff --git a/bottleneck/tests/data/test_469_A b/bottleneck/tests/data/test_469_A
new file mode 100644
index 0000000..842bb69
--- /dev/null
+++ b/bottleneck/tests/data/test_469_A
@@ -0,0 +1,7 @@
+60 115
+77 137
+40 98
+11 59
+16 29
+60 98
+86 149
diff --git a/bottleneck/tests/data/test_469_B b/bottleneck/tests/data/test_469_B
new file mode 100644
index 0000000..e6de4fe
--- /dev/null
+++ b/bottleneck/tests/data/test_469_B
@@ -0,0 +1,7 @@
+28 101
+15 65
+55 67
+40 73
+14 69
+87 117
+83 137
diff --git a/bottleneck/tests/data/test_470_A b/bottleneck/tests/data/test_470_A
new file mode 100644
index 0000000..5f2fd6b
--- /dev/null
+++ b/bottleneck/tests/data/test_470_A
@@ -0,0 +1,7 @@
+1 17
+80 137
+31 128
+78 83
+95 188
+94 150
+7 103
diff --git a/bottleneck/tests/data/test_470_B b/bottleneck/tests/data/test_470_B
new file mode 100644
index 0000000..5db84e8
--- /dev/null
+++ b/bottleneck/tests/data/test_470_B
@@ -0,0 +1,7 @@
+85 178
+3 52
+99 189
+95 115
+98 183
+0 60
+22 120
diff --git a/bottleneck/tests/data/test_471_A b/bottleneck/tests/data/test_471_A
new file mode 100644
index 0000000..e88e5ff
--- /dev/null
+++ b/bottleneck/tests/data/test_471_A
@@ -0,0 +1,7 @@
+58 107
+6 86
+44 47
+12 97
+48 133
+89 111
+94 155
diff --git a/bottleneck/tests/data/test_471_B b/bottleneck/tests/data/test_471_B
new file mode 100644
index 0000000..26065c0
--- /dev/null
+++ b/bottleneck/tests/data/test_471_B
@@ -0,0 +1,7 @@
+51 115
+25 51
+77 165
+21 116
+19 21
+11 77
+5 9
diff --git a/bottleneck/tests/data/test_472_A b/bottleneck/tests/data/test_472_A
new file mode 100644
index 0000000..bd2ec1a
--- /dev/null
+++ b/bottleneck/tests/data/test_472_A
@@ -0,0 +1,7 @@
+68 75
+12 88
+15 84
+33 120
+76 160
+23 56
+16 116
diff --git a/bottleneck/tests/data/test_472_B b/bottleneck/tests/data/test_472_B
new file mode 100644
index 0000000..3914a18
--- /dev/null
+++ b/bottleneck/tests/data/test_472_B
@@ -0,0 +1,7 @@
+75 129
+58 68
+36 119
+11 59
+25 42
+50 65
+12 28
diff --git a/bottleneck/tests/data/test_473_A b/bottleneck/tests/data/test_473_A
new file mode 100644
index 0000000..d8e4ed1
--- /dev/null
+++ b/bottleneck/tests/data/test_473_A
@@ -0,0 +1,7 @@
+86 119
+34 71
+91 182
+97 170
+73 104
+71 160
+26 120
diff --git a/bottleneck/tests/data/test_473_B b/bottleneck/tests/data/test_473_B
new file mode 100644
index 0000000..1ce2c2f
--- /dev/null
+++ b/bottleneck/tests/data/test_473_B
@@ -0,0 +1,7 @@
+53 111
+78 111
+99 134
+42 70
+70 84
+52 85
+55 154
diff --git a/bottleneck/tests/data/test_474_A b/bottleneck/tests/data/test_474_A
new file mode 100644
index 0000000..30c9ad1
--- /dev/null
+++ b/bottleneck/tests/data/test_474_A
@@ -0,0 +1,7 @@
+84 139
+74 167
+0 76
+6 33
+73 165
+80 173
+28 38
diff --git a/bottleneck/tests/data/test_474_B b/bottleneck/tests/data/test_474_B
new file mode 100644
index 0000000..35c507a
--- /dev/null
+++ b/bottleneck/tests/data/test_474_B
@@ -0,0 +1,7 @@
+76 134
+38 118
+37 87
+61 110
+59 79
+67 75
+45 100
diff --git a/bottleneck/tests/data/test_475_A b/bottleneck/tests/data/test_475_A
new file mode 100644
index 0000000..05023db
--- /dev/null
+++ b/bottleneck/tests/data/test_475_A
@@ -0,0 +1,7 @@
+17 92
+69 112
+37 83
+62 116
+69 85
+63 92
+31 55
diff --git a/bottleneck/tests/data/test_475_B b/bottleneck/tests/data/test_475_B
new file mode 100644
index 0000000..0fcc2d0
--- /dev/null
+++ b/bottleneck/tests/data/test_475_B
@@ -0,0 +1,7 @@
+18 105
+66 104
+36 67
+50 61
+44 118
+75 99
+41 49
diff --git a/bottleneck/tests/data/test_476_A b/bottleneck/tests/data/test_476_A
new file mode 100644
index 0000000..0c4ede1
--- /dev/null
+++ b/bottleneck/tests/data/test_476_A
@@ -0,0 +1,7 @@
+14 109
+64 142
+98 152
+34 115
+47 100
+85 99
+0 7
diff --git a/bottleneck/tests/data/test_476_B b/bottleneck/tests/data/test_476_B
new file mode 100644
index 0000000..ae68bae
--- /dev/null
+++ b/bottleneck/tests/data/test_476_B
@@ -0,0 +1,7 @@
+99 172
+23 91
+0 80
+89 102
+21 56
+86 169
+48 116
diff --git a/bottleneck/tests/data/test_477_A b/bottleneck/tests/data/test_477_A
new file mode 100644
index 0000000..719e1b7
--- /dev/null
+++ b/bottleneck/tests/data/test_477_A
@@ -0,0 +1,7 @@
+2 87
+9 51
+78 81
+26 122
+54 126
+66 128
+88 139
diff --git a/bottleneck/tests/data/test_477_B b/bottleneck/tests/data/test_477_B
new file mode 100644
index 0000000..6c2e706
--- /dev/null
+++ b/bottleneck/tests/data/test_477_B
@@ -0,0 +1,7 @@
+9 55
+60 64
+26 57
+6 74
+70 103
+84 87
+35 56
diff --git a/bottleneck/tests/data/test_478_A b/bottleneck/tests/data/test_478_A
new file mode 100644
index 0000000..61b09a8
--- /dev/null
+++ b/bottleneck/tests/data/test_478_A
@@ -0,0 +1,7 @@
+76 114
+41 48
+16 34
+28 80
+100 119
+57 64
+53 104
diff --git a/bottleneck/tests/data/test_478_B b/bottleneck/tests/data/test_478_B
new file mode 100644
index 0000000..a302122
--- /dev/null
+++ b/bottleneck/tests/data/test_478_B
@@ -0,0 +1,7 @@
+81 179
+64 112
+9 49
+64 132
+15 81
+97 137
+17 39
diff --git a/bottleneck/tests/data/test_479_A b/bottleneck/tests/data/test_479_A
new file mode 100644
index 0000000..b956a54
--- /dev/null
+++ b/bottleneck/tests/data/test_479_A
@@ -0,0 +1,7 @@
+31 104
+56 83
+21 87
+76 135
+63 126
+89 134
+74 159
diff --git a/bottleneck/tests/data/test_479_B b/bottleneck/tests/data/test_479_B
new file mode 100644
index 0000000..10d8948
--- /dev/null
+++ b/bottleneck/tests/data/test_479_B
@@ -0,0 +1,7 @@
+98 131
+8 98
+96 101
+78 146
+6 35
+88 116
+82 88
diff --git a/bottleneck/tests/data/test_480_A b/bottleneck/tests/data/test_480_A
new file mode 100644
index 0000000..6ad5182
--- /dev/null
+++ b/bottleneck/tests/data/test_480_A
@@ -0,0 +1,8 @@
+75 137
+100 185
+65 142
+7 8
+25 44
+39 108
+94 99
+6 78
diff --git a/bottleneck/tests/data/test_480_B b/bottleneck/tests/data/test_480_B
new file mode 100644
index 0000000..246f278
--- /dev/null
+++ b/bottleneck/tests/data/test_480_B
@@ -0,0 +1,8 @@
+80 156
+94 180
+55 143
+39 93
+72 170
+76 176
+72 160
+36 59
diff --git a/bottleneck/tests/data/test_481_A b/bottleneck/tests/data/test_481_A
new file mode 100644
index 0000000..8e414ab
--- /dev/null
+++ b/bottleneck/tests/data/test_481_A
@@ -0,0 +1,8 @@
+4 61
+27 91
+83 153
+1 25
+25 33
+71 76
+5 103
+8 34
diff --git a/bottleneck/tests/data/test_481_B b/bottleneck/tests/data/test_481_B
new file mode 100644
index 0000000..5596312
--- /dev/null
+++ b/bottleneck/tests/data/test_481_B
@@ -0,0 +1,8 @@
+59 143
+99 148
+21 32
+60 71
+16 51
+78 90
+11 77
+56 145
diff --git a/bottleneck/tests/data/test_482_A b/bottleneck/tests/data/test_482_A
new file mode 100644
index 0000000..b40bc32
--- /dev/null
+++ b/bottleneck/tests/data/test_482_A
@@ -0,0 +1,8 @@
+56 139
+4 18
+16 47
+99 186
+16 63
+44 50
+99 187
+30 85
diff --git a/bottleneck/tests/data/test_482_B b/bottleneck/tests/data/test_482_B
new file mode 100644
index 0000000..04b23b5
--- /dev/null
+++ b/bottleneck/tests/data/test_482_B
@@ -0,0 +1,8 @@
+84 162
+22 52
+12 98
+59 106
+86 155
+93 108
+75 119
+18 20
diff --git a/bottleneck/tests/data/test_483_A b/bottleneck/tests/data/test_483_A
new file mode 100644
index 0000000..7ef0f99
--- /dev/null
+++ b/bottleneck/tests/data/test_483_A
@@ -0,0 +1,8 @@
+10 13
+53 81
+57 151
+81 148
+91 132
+9 89
+11 65
+29 85
diff --git a/bottleneck/tests/data/test_483_B b/bottleneck/tests/data/test_483_B
new file mode 100644
index 0000000..eabdee1
--- /dev/null
+++ b/bottleneck/tests/data/test_483_B
@@ -0,0 +1,8 @@
+87 187
+79 111
+41 93
+54 76
+27 86
+97 150
+97 185
+36 37
diff --git a/bottleneck/tests/data/test_484_A b/bottleneck/tests/data/test_484_A
new file mode 100644
index 0000000..11fa5dd
--- /dev/null
+++ b/bottleneck/tests/data/test_484_A
@@ -0,0 +1,8 @@
+58 147
+24 70
+83 171
+78 91
+55 86
+83 168
+40 125
+75 121
diff --git a/bottleneck/tests/data/test_484_B b/bottleneck/tests/data/test_484_B
new file mode 100644
index 0000000..2dda740
--- /dev/null
+++ b/bottleneck/tests/data/test_484_B
@@ -0,0 +1,8 @@
+55 66
+48 100
+69 123
+84 152
+56 155
+87 99
+83 167
+39 49
diff --git a/bottleneck/tests/data/test_485_A b/bottleneck/tests/data/test_485_A
new file mode 100644
index 0000000..bd500dd
--- /dev/null
+++ b/bottleneck/tests/data/test_485_A
@@ -0,0 +1,8 @@
+64 81
+52 69
+62 74
+3 79
+24 117
+81 133
+5 37
+53 90
diff --git a/bottleneck/tests/data/test_485_B b/bottleneck/tests/data/test_485_B
new file mode 100644
index 0000000..a117670
--- /dev/null
+++ b/bottleneck/tests/data/test_485_B
@@ -0,0 +1,8 @@
+80 97
+10 69
+49 123
+28 123
+92 135
+19 107
+7 53
+99 165
diff --git a/bottleneck/tests/data/test_486_A b/bottleneck/tests/data/test_486_A
new file mode 100644
index 0000000..4dcc3ca
--- /dev/null
+++ b/bottleneck/tests/data/test_486_A
@@ -0,0 +1,8 @@
+76 162
+58 117
+91 152
+96 137
+45 49
+64 156
+35 64
+42 114
diff --git a/bottleneck/tests/data/test_486_B b/bottleneck/tests/data/test_486_B
new file mode 100644
index 0000000..c808dc5
--- /dev/null
+++ b/bottleneck/tests/data/test_486_B
@@ -0,0 +1,8 @@
+35 95
+0 78
+61 78
+100 110
+100 106
+56 91
+97 133
+87 176
diff --git a/bottleneck/tests/data/test_487_A b/bottleneck/tests/data/test_487_A
new file mode 100644
index 0000000..7250b20
--- /dev/null
+++ b/bottleneck/tests/data/test_487_A
@@ -0,0 +1,8 @@
+78 114
+95 110
+22 47
+95 181
+6 76
+47 89
+10 27
+69 102
diff --git a/bottleneck/tests/data/test_487_B b/bottleneck/tests/data/test_487_B
new file mode 100644
index 0000000..b0a4119
--- /dev/null
+++ b/bottleneck/tests/data/test_487_B
@@ -0,0 +1,8 @@
+31 113
+71 115
+10 97
+97 101
+30 61
+79 157
+56 89
+96 184
diff --git a/bottleneck/tests/data/test_488_A b/bottleneck/tests/data/test_488_A
new file mode 100644
index 0000000..92f19ab
--- /dev/null
+++ b/bottleneck/tests/data/test_488_A
@@ -0,0 +1,8 @@
+7 28
+32 59
+64 84
+71 156
+89 166
+67 154
+54 89
+49 78
diff --git a/bottleneck/tests/data/test_488_B b/bottleneck/tests/data/test_488_B
new file mode 100644
index 0000000..712480d
--- /dev/null
+++ b/bottleneck/tests/data/test_488_B
@@ -0,0 +1,8 @@
+54 128
+20 59
+64 135
+80 106
+35 88
+93 187
+4 5
+73 126
diff --git a/bottleneck/tests/data/test_489_A b/bottleneck/tests/data/test_489_A
new file mode 100644
index 0000000..f1c9abf
--- /dev/null
+++ b/bottleneck/tests/data/test_489_A
@@ -0,0 +1,8 @@
+52 74
+59 74
+83 84
+51 135
+41 132
+29 113
+7 65
+97 176
diff --git a/bottleneck/tests/data/test_489_B b/bottleneck/tests/data/test_489_B
new file mode 100644
index 0000000..5c5316f
--- /dev/null
+++ b/bottleneck/tests/data/test_489_B
@@ -0,0 +1,8 @@
+43 126
+23 64
+16 111
+96 97
+84 112
+39 85
+33 74
+39 97
diff --git a/bottleneck/tests/data/test_490_A b/bottleneck/tests/data/test_490_A
new file mode 100644
index 0000000..e907d09
--- /dev/null
+++ b/bottleneck/tests/data/test_490_A
@@ -0,0 +1,8 @@
+93 146
+47 99
+6 55
+19 66
+15 28
+2 93
+97 143
+52 125
diff --git a/bottleneck/tests/data/test_490_B b/bottleneck/tests/data/test_490_B
new file mode 100644
index 0000000..6368e47
--- /dev/null
+++ b/bottleneck/tests/data/test_490_B
@@ -0,0 +1,8 @@
+82 172
+98 155
+73 119
+50 133
+13 84
+53 73
+5 21
+82 83
diff --git a/bottleneck/tests/data/test_491_A b/bottleneck/tests/data/test_491_A
new file mode 100644
index 0000000..9fdc2fb
--- /dev/null
+++ b/bottleneck/tests/data/test_491_A
@@ -0,0 +1,8 @@
+12 35
+75 82
+45 91
+18 27
+99 178
+35 37
+46 113
+70 94
diff --git a/bottleneck/tests/data/test_491_B b/bottleneck/tests/data/test_491_B
new file mode 100644
index 0000000..09cd4ac
--- /dev/null
+++ b/bottleneck/tests/data/test_491_B
@@ -0,0 +1,8 @@
+76 121
+84 172
+70 167
+57 143
+4 52
+69 159
+10 100
+96 153
diff --git a/bottleneck/tests/data/test_492_A b/bottleneck/tests/data/test_492_A
new file mode 100644
index 0000000..434683d
--- /dev/null
+++ b/bottleneck/tests/data/test_492_A
@@ -0,0 +1,8 @@
+21 92
+42 105
+79 166
+41 78
+72 87
+25 49
+78 104
+60 115
diff --git a/bottleneck/tests/data/test_492_B b/bottleneck/tests/data/test_492_B
new file mode 100644
index 0000000..3f6f5fa
--- /dev/null
+++ b/bottleneck/tests/data/test_492_B
@@ -0,0 +1,8 @@
+80 94
+66 106
+36 79
+12 20
+28 36
+94 155
+62 100
+77 136
diff --git a/bottleneck/tests/data/test_493_A b/bottleneck/tests/data/test_493_A
new file mode 100644
index 0000000..12cfc64
--- /dev/null
+++ b/bottleneck/tests/data/test_493_A
@@ -0,0 +1,8 @@
+14 46
+79 109
+49 92
+100 181
+32 44
+15 16
+59 62
+66 127
diff --git a/bottleneck/tests/data/test_493_B b/bottleneck/tests/data/test_493_B
new file mode 100644
index 0000000..43dcf08
--- /dev/null
+++ b/bottleneck/tests/data/test_493_B
@@ -0,0 +1,8 @@
+18 21
+74 155
+36 57
+28 41
+15 40
+94 133
+72 153
+42 135
diff --git a/bottleneck/tests/data/test_494_A b/bottleneck/tests/data/test_494_A
new file mode 100644
index 0000000..b35b505
--- /dev/null
+++ b/bottleneck/tests/data/test_494_A
@@ -0,0 +1,8 @@
+31 40
+44 129
+74 92
+41 132
+79 105
+18 58
+93 123
+8 39
diff --git a/bottleneck/tests/data/test_494_B b/bottleneck/tests/data/test_494_B
new file mode 100644
index 0000000..fb70ed6
--- /dev/null
+++ b/bottleneck/tests/data/test_494_B
@@ -0,0 +1,8 @@
+86 165
+30 101
+85 185
+15 71
+75 175
+61 141
+43 81
+90 128
diff --git a/bottleneck/tests/data/test_495_A b/bottleneck/tests/data/test_495_A
new file mode 100644
index 0000000..c244b7a
--- /dev/null
+++ b/bottleneck/tests/data/test_495_A
@@ -0,0 +1,8 @@
+90 133
+48 84
+48 126
+0 80
+8 17
+60 82
+17 48
+9 74
diff --git a/bottleneck/tests/data/test_495_B b/bottleneck/tests/data/test_495_B
new file mode 100644
index 0000000..4bd121d
--- /dev/null
+++ b/bottleneck/tests/data/test_495_B
@@ -0,0 +1,8 @@
+19 25
+39 63
+0 3
+39 86
+72 91
+27 85
+97 141
+79 174
diff --git a/bottleneck/tests/data/test_496_A b/bottleneck/tests/data/test_496_A
new file mode 100644
index 0000000..cc2cc0b
--- /dev/null
+++ b/bottleneck/tests/data/test_496_A
@@ -0,0 +1,8 @@
+79 127
+84 146
+58 143
+28 68
+35 100
+38 126
+24 89
+32 70
diff --git a/bottleneck/tests/data/test_496_B b/bottleneck/tests/data/test_496_B
new file mode 100644
index 0000000..5b8aeaa
--- /dev/null
+++ b/bottleneck/tests/data/test_496_B
@@ -0,0 +1,8 @@
+9 61
+68 125
+4 98
+98 99
+49 67
+41 50
+38 61
+24 44
diff --git a/bottleneck/tests/data/test_497_A b/bottleneck/tests/data/test_497_A
new file mode 100644
index 0000000..b3b511d
--- /dev/null
+++ b/bottleneck/tests/data/test_497_A
@@ -0,0 +1,8 @@
+19 24
+89 174
+47 137
+93 131
+50 127
+6 34
+99 118
+86 98
diff --git a/bottleneck/tests/data/test_497_B b/bottleneck/tests/data/test_497_B
new file mode 100644
index 0000000..8870c73
--- /dev/null
+++ b/bottleneck/tests/data/test_497_B
@@ -0,0 +1,8 @@
+0 69
+39 100
+58 156
+37 74
+47 62
+81 172
+81 175
+56 147
diff --git a/bottleneck/tests/data/test_498_A b/bottleneck/tests/data/test_498_A
new file mode 100644
index 0000000..5bef5fa
--- /dev/null
+++ b/bottleneck/tests/data/test_498_A
@@ -0,0 +1,8 @@
+55 140
+94 160
+22 35
+42 89
+50 127
+8 59
+25 87
+35 103
diff --git a/bottleneck/tests/data/test_498_B b/bottleneck/tests/data/test_498_B
new file mode 100644
index 0000000..b1ed38a
--- /dev/null
+++ b/bottleneck/tests/data/test_498_B
@@ -0,0 +1,8 @@
+88 164
+14 29
+13 19
+3 49
+86 107
+62 138
+72 77
+2 22
diff --git a/bottleneck/tests/data/test_499_A b/bottleneck/tests/data/test_499_A
new file mode 100644
index 0000000..a24f367
--- /dev/null
+++ b/bottleneck/tests/data/test_499_A
@@ -0,0 +1,8 @@
+35 68
+22 25
+87 132
+23 119
+64 131
+13 106
+8 22
+83 169
diff --git a/bottleneck/tests/data/test_499_B b/bottleneck/tests/data/test_499_B
new file mode 100644
index 0000000..24d0d92
--- /dev/null
+++ b/bottleneck/tests/data/test_499_B
@@ -0,0 +1,8 @@
+27 105
+66 84
+76 101
+96 126
+40 103
+82 159
+41 45
+58 97
diff --git a/bottleneck/tests/data/test_500_A b/bottleneck/tests/data/test_500_A
new file mode 100644
index 0000000..ed86941
--- /dev/null
+++ b/bottleneck/tests/data/test_500_A
@@ -0,0 +1,9 @@
+96 120
+81 139
+35 58
+14 38
+23 33
+44 97
+26 61
+47 74
+75 124
diff --git a/bottleneck/tests/data/test_500_B b/bottleneck/tests/data/test_500_B
new file mode 100644
index 0000000..58f0cd6
--- /dev/null
+++ b/bottleneck/tests/data/test_500_B
@@ -0,0 +1,9 @@
+57 153
+7 107
+56 78
+67 90
+14 86
+97 112
+5 45
+55 151
+51 133
diff --git a/bottleneck/tests/data/test_501_A b/bottleneck/tests/data/test_501_A
new file mode 100644
index 0000000..b6f9335
--- /dev/null
+++ b/bottleneck/tests/data/test_501_A
@@ -0,0 +1,9 @@
+57 145
+1 34
+98 129
+25 26
+19 94
+90 187
+62 160
+70 115
+88 160
diff --git a/bottleneck/tests/data/test_501_B b/bottleneck/tests/data/test_501_B
new file mode 100644
index 0000000..af0d32b
--- /dev/null
+++ b/bottleneck/tests/data/test_501_B
@@ -0,0 +1,9 @@
+77 100
+34 41
+79 99
+27 65
+30 69
+58 96
+98 195
+45 144
+82 147
diff --git a/bottleneck/tests/data/test_502_A b/bottleneck/tests/data/test_502_A
new file mode 100644
index 0000000..64c4bfe
--- /dev/null
+++ b/bottleneck/tests/data/test_502_A
@@ -0,0 +1,9 @@
+78 102
+66 134
+42 104
+17 68
+33 113
+84 160
+86 119
+32 73
+6 19
diff --git a/bottleneck/tests/data/test_502_B b/bottleneck/tests/data/test_502_B
new file mode 100644
index 0000000..4b1bb48
--- /dev/null
+++ b/bottleneck/tests/data/test_502_B
@@ -0,0 +1,9 @@
+2 25
+80 119
+56 147
+94 99
+51 116
+29 109
+89 180
+45 75
+93 170
diff --git a/bottleneck/tests/data/test_503_A b/bottleneck/tests/data/test_503_A
new file mode 100644
index 0000000..7686e8d
--- /dev/null
+++ b/bottleneck/tests/data/test_503_A
@@ -0,0 +1,9 @@
+53 55
+1 67
+100 128
+27 39
+17 62
+66 98
+49 85
+13 14
+72 91
diff --git a/bottleneck/tests/data/test_503_B b/bottleneck/tests/data/test_503_B
new file mode 100644
index 0000000..c662290
--- /dev/null
+++ b/bottleneck/tests/data/test_503_B
@@ -0,0 +1,9 @@
+74 110
+99 192
+22 56
+19 40
+63 99
+31 44
+28 122
+89 161
+85 184
diff --git a/bottleneck/tests/data/test_504_A b/bottleneck/tests/data/test_504_A
new file mode 100644
index 0000000..7b0bcd8
--- /dev/null
+++ b/bottleneck/tests/data/test_504_A
@@ -0,0 +1,9 @@
+52 60
+30 76
+55 91
+83 91
+23 53
+64 68
+12 106
+54 99
+0 83
diff --git a/bottleneck/tests/data/test_504_B b/bottleneck/tests/data/test_504_B
new file mode 100644
index 0000000..1fb9704
--- /dev/null
+++ b/bottleneck/tests/data/test_504_B
@@ -0,0 +1,9 @@
+10 57
+0 87
+74 85
+13 91
+48 59
+21 109
+85 141
+70 151
+24 103
diff --git a/bottleneck/tests/data/test_505_A b/bottleneck/tests/data/test_505_A
new file mode 100644
index 0000000..fd80b53
--- /dev/null
+++ b/bottleneck/tests/data/test_505_A
@@ -0,0 +1,9 @@
+90 183
+100 112
+33 120
+94 114
+96 190
+70 109
+22 102
+71 126
+99 150
diff --git a/bottleneck/tests/data/test_505_B b/bottleneck/tests/data/test_505_B
new file mode 100644
index 0000000..9bd046e
--- /dev/null
+++ b/bottleneck/tests/data/test_505_B
@@ -0,0 +1,9 @@
+18 83
+61 159
+73 138
+51 137
+20 96
+89 185
+13 52
+54 134
+24 35
diff --git a/bottleneck/tests/data/test_506_A b/bottleneck/tests/data/test_506_A
new file mode 100644
index 0000000..1f5e9ac
--- /dev/null
+++ b/bottleneck/tests/data/test_506_A
@@ -0,0 +1,9 @@
+95 117
+41 138
+52 118
+82 163
+9 22
+58 156
+7 74
+24 42
+96 158
diff --git a/bottleneck/tests/data/test_506_B b/bottleneck/tests/data/test_506_B
new file mode 100644
index 0000000..0dc89b8
--- /dev/null
+++ b/bottleneck/tests/data/test_506_B
@@ -0,0 +1,9 @@
+91 134
+78 119
+94 141
+5 57
+34 55
+43 101
+27 116
+41 72
+98 126
diff --git a/bottleneck/tests/data/test_507_A b/bottleneck/tests/data/test_507_A
new file mode 100644
index 0000000..a6d164e
--- /dev/null
+++ b/bottleneck/tests/data/test_507_A
@@ -0,0 +1,9 @@
+34 62
+21 105
+41 63
+74 99
+52 95
+89 100
+11 82
+74 83
+78 132
diff --git a/bottleneck/tests/data/test_507_B b/bottleneck/tests/data/test_507_B
new file mode 100644
index 0000000..b39a7fe
--- /dev/null
+++ b/bottleneck/tests/data/test_507_B
@@ -0,0 +1,9 @@
+49 76
+24 57
+25 101
+9 99
+65 146
+23 43
+89 165
+63 138
+50 76
diff --git a/bottleneck/tests/data/test_508_A b/bottleneck/tests/data/test_508_A
new file mode 100644
index 0000000..c837ce3
--- /dev/null
+++ b/bottleneck/tests/data/test_508_A
@@ -0,0 +1,9 @@
+59 141
+59 74
+0 5
+11 105
+15 58
+43 117
+47 93
+60 149
+69 92
diff --git a/bottleneck/tests/data/test_508_B b/bottleneck/tests/data/test_508_B
new file mode 100644
index 0000000..733b5a0
--- /dev/null
+++ b/bottleneck/tests/data/test_508_B
@@ -0,0 +1,9 @@
+29 104
+50 67
+43 82
+86 102
+45 81
+19 106
+74 124
+77 150
+80 104
diff --git a/bottleneck/tests/data/test_509_A b/bottleneck/tests/data/test_509_A
new file mode 100644
index 0000000..98137f3
--- /dev/null
+++ b/bottleneck/tests/data/test_509_A
@@ -0,0 +1,9 @@
+40 74
+89 138
+20 44
+56 65
+12 14
+87 149
+23 123
+12 28
+56 146
diff --git a/bottleneck/tests/data/test_509_B b/bottleneck/tests/data/test_509_B
new file mode 100644
index 0000000..1edd08c
--- /dev/null
+++ b/bottleneck/tests/data/test_509_B
@@ -0,0 +1,9 @@
+89 153
+20 65
+87 128
+27 101
+23 71
+6 53
+50 128
+16 108
+92 157
diff --git a/bottleneck/tests/data/test_510_A b/bottleneck/tests/data/test_510_A
new file mode 100644
index 0000000..b1e0e68
--- /dev/null
+++ b/bottleneck/tests/data/test_510_A
@@ -0,0 +1,9 @@
+67 70
+99 197
+62 111
+25 59
+61 131
+34 108
+99 185
+73 125
+76 130
diff --git a/bottleneck/tests/data/test_510_B b/bottleneck/tests/data/test_510_B
new file mode 100644
index 0000000..8e48152
--- /dev/null
+++ b/bottleneck/tests/data/test_510_B
@@ -0,0 +1,9 @@
+72 74
+57 126
+32 106
+55 88
+75 167
+5 34
+46 72
+86 104
+30 129
diff --git a/bottleneck/tests/data/test_511_A b/bottleneck/tests/data/test_511_A
new file mode 100644
index 0000000..a2c6b34
--- /dev/null
+++ b/bottleneck/tests/data/test_511_A
@@ -0,0 +1,9 @@
+10 56
+84 163
+34 131
+32 106
+61 84
+71 106
+17 32
+23 43
+44 79
diff --git a/bottleneck/tests/data/test_511_B b/bottleneck/tests/data/test_511_B
new file mode 100644
index 0000000..ff48216
--- /dev/null
+++ b/bottleneck/tests/data/test_511_B
@@ -0,0 +1,9 @@
+57 66
+89 124
+93 120
+72 119
+83 125
+1 17
+25 97
+32 90
+89 135
diff --git a/bottleneck/tests/data/test_512_A b/bottleneck/tests/data/test_512_A
new file mode 100644
index 0000000..8f875d8
--- /dev/null
+++ b/bottleneck/tests/data/test_512_A
@@ -0,0 +1,9 @@
+88 136
+21 65
+12 82
+35 48
+97 127
+38 89
+69 71
+47 107
+91 127
diff --git a/bottleneck/tests/data/test_512_B b/bottleneck/tests/data/test_512_B
new file mode 100644
index 0000000..c6988c1
--- /dev/null
+++ b/bottleneck/tests/data/test_512_B
@@ -0,0 +1,9 @@
+59 98
+88 114
+90 122
+83 147
+95 153
+9 56
+14 54
+25 70
+47 60
diff --git a/bottleneck/tests/data/test_513_A b/bottleneck/tests/data/test_513_A
new file mode 100644
index 0000000..844c16d
--- /dev/null
+++ b/bottleneck/tests/data/test_513_A
@@ -0,0 +1,9 @@
+34 45
+64 149
+94 147
+34 73
+15 91
+2 53
+46 99
+70 100
+28 62
diff --git a/bottleneck/tests/data/test_513_B b/bottleneck/tests/data/test_513_B
new file mode 100644
index 0000000..ee75f8c
--- /dev/null
+++ b/bottleneck/tests/data/test_513_B
@@ -0,0 +1,9 @@
+14 50
+76 112
+46 60
+45 94
+73 150
+79 128
+5 72
+44 87
+25 97
diff --git a/bottleneck/tests/data/test_514_A b/bottleneck/tests/data/test_514_A
new file mode 100644
index 0000000..9b58831
--- /dev/null
+++ b/bottleneck/tests/data/test_514_A
@@ -0,0 +1,9 @@
+4 78
+32 82
+56 106
+56 135
+0 1
+18 103
+29 65
+50 82
+68 82
diff --git a/bottleneck/tests/data/test_514_B b/bottleneck/tests/data/test_514_B
new file mode 100644
index 0000000..39c6534
--- /dev/null
+++ b/bottleneck/tests/data/test_514_B
@@ -0,0 +1,9 @@
+34 63
+63 145
+40 63
+3 93
+57 123
+32 51
+100 115
+23 32
+21 23
diff --git a/bottleneck/tests/data/test_515_A b/bottleneck/tests/data/test_515_A
new file mode 100644
index 0000000..fc2578b
--- /dev/null
+++ b/bottleneck/tests/data/test_515_A
@@ -0,0 +1,9 @@
+32 33
+77 131
+64 160
+26 35
+77 106
+69 70
+98 106
+29 107
+65 69
diff --git a/bottleneck/tests/data/test_515_B b/bottleneck/tests/data/test_515_B
new file mode 100644
index 0000000..715f6e5
--- /dev/null
+++ b/bottleneck/tests/data/test_515_B
@@ -0,0 +1,9 @@
+86 101
+89 138
+100 133
+81 103
+9 16
+79 133
+30 113
+98 195
+2 86
diff --git a/bottleneck/tests/data/test_516_A b/bottleneck/tests/data/test_516_A
new file mode 100644
index 0000000..bd37e5d
--- /dev/null
+++ b/bottleneck/tests/data/test_516_A
@@ -0,0 +1,9 @@
+80 178
+95 153
+66 133
+12 74
+59 87
+85 165
+36 89
+57 145
+85 177
diff --git a/bottleneck/tests/data/test_516_B b/bottleneck/tests/data/test_516_B
new file mode 100644
index 0000000..8d23127
--- /dev/null
+++ b/bottleneck/tests/data/test_516_B
@@ -0,0 +1,9 @@
+29 85
+39 41
+50 99
+16 76
+82 131
+20 107
+20 25
+91 105
+98 172
diff --git a/bottleneck/tests/data/test_517_A b/bottleneck/tests/data/test_517_A
new file mode 100644
index 0000000..17ca01c
--- /dev/null
+++ b/bottleneck/tests/data/test_517_A
@@ -0,0 +1,9 @@
+39 41
+60 128
+14 32
+52 138
+74 79
+52 100
+4 39
+53 145
+33 127
diff --git a/bottleneck/tests/data/test_517_B b/bottleneck/tests/data/test_517_B
new file mode 100644
index 0000000..ba82599
--- /dev/null
+++ b/bottleneck/tests/data/test_517_B
@@ -0,0 +1,9 @@
+31 113
+54 116
+69 151
+9 18
+60 62
+0 22
+93 162
+15 62
+63 148
diff --git a/bottleneck/tests/data/test_518_A b/bottleneck/tests/data/test_518_A
new file mode 100644
index 0000000..bb1711c
--- /dev/null
+++ b/bottleneck/tests/data/test_518_A
@@ -0,0 +1,9 @@
+49 70
+63 113
+60 158
+17 111
+37 112
+35 101
+3 51
+89 126
+91 129
diff --git a/bottleneck/tests/data/test_518_B b/bottleneck/tests/data/test_518_B
new file mode 100644
index 0000000..5b2e95a
--- /dev/null
+++ b/bottleneck/tests/data/test_518_B
@@ -0,0 +1,9 @@
+7 97
+72 146
+59 147
+89 103
+72 169
+43 65
+29 98
+28 44
+14 40
diff --git a/bottleneck/tests/data/test_519_A b/bottleneck/tests/data/test_519_A
new file mode 100644
index 0000000..f0cb6ea
--- /dev/null
+++ b/bottleneck/tests/data/test_519_A
@@ -0,0 +1,9 @@
+6 92
+25 100
+99 156
+12 89
+3 102
+32 107
+13 40
+79 94
+33 118
diff --git a/bottleneck/tests/data/test_519_B b/bottleneck/tests/data/test_519_B
new file mode 100644
index 0000000..03396db
--- /dev/null
+++ b/bottleneck/tests/data/test_519_B
@@ -0,0 +1,9 @@
+32 46
+61 155
+98 180
+10 89
+86 127
+0 4
+51 65
+9 85
+32 85
diff --git a/bottleneck/tests/data/test_520_A b/bottleneck/tests/data/test_520_A
new file mode 100644
index 0000000..9353285
--- /dev/null
+++ b/bottleneck/tests/data/test_520_A
@@ -0,0 +1,10 @@
+91 117
+68 132
+36 70
+20 75
+47 97
+50 84
+9 79
+63 70
+0 48
+15 75
diff --git a/bottleneck/tests/data/test_520_B b/bottleneck/tests/data/test_520_B
new file mode 100644
index 0000000..1e328cd
--- /dev/null
+++ b/bottleneck/tests/data/test_520_B
@@ -0,0 +1,10 @@
+35 51
+16 23
+4 91
+69 133
+21 30
+80 169
+55 100
+34 76
+24 30
+97 167
diff --git a/bottleneck/tests/data/test_521_A b/bottleneck/tests/data/test_521_A
new file mode 100644
index 0000000..d0bea91
--- /dev/null
+++ b/bottleneck/tests/data/test_521_A
@@ -0,0 +1,10 @@
+22 45
+99 100
+34 81
+41 104
+1 25
+3 93
+26 88
+4 23
+97 159
+7 19
diff --git a/bottleneck/tests/data/test_521_B b/bottleneck/tests/data/test_521_B
new file mode 100644
index 0000000..5e584b0
--- /dev/null
+++ b/bottleneck/tests/data/test_521_B
@@ -0,0 +1,10 @@
+2 40
+31 85
+57 105
+28 61
+18 111
+95 115
+0 66
+81 167
+96 174
+85 170
diff --git a/bottleneck/tests/data/test_522_A b/bottleneck/tests/data/test_522_A
new file mode 100644
index 0000000..5631735
--- /dev/null
+++ b/bottleneck/tests/data/test_522_A
@@ -0,0 +1,10 @@
+99 187
+92 127
+69 157
+82 161
+94 141
+97 108
+70 94
+20 39
+87 172
+87 122
diff --git a/bottleneck/tests/data/test_522_B b/bottleneck/tests/data/test_522_B
new file mode 100644
index 0000000..903bcdc
--- /dev/null
+++ b/bottleneck/tests/data/test_522_B
@@ -0,0 +1,10 @@
+39 51
+28 81
+77 78
+17 52
+42 124
+34 37
+96 117
+39 98
+65 142
+4 72
diff --git a/bottleneck/tests/data/test_523_A b/bottleneck/tests/data/test_523_A
new file mode 100644
index 0000000..b4da958
--- /dev/null
+++ b/bottleneck/tests/data/test_523_A
@@ -0,0 +1,10 @@
+73 158
+5 34
+4 67
+88 109
+46 137
+86 152
+61 113
+61 93
+71 77
+65 157
diff --git a/bottleneck/tests/data/test_523_B b/bottleneck/tests/data/test_523_B
new file mode 100644
index 0000000..bcc7438
--- /dev/null
+++ b/bottleneck/tests/data/test_523_B
@@ -0,0 +1,10 @@
+54 78
+6 86
+63 130
+90 183
+59 89
+96 151
+93 117
+74 147
+20 93
+26 110
diff --git a/bottleneck/tests/data/test_524_A b/bottleneck/tests/data/test_524_A
new file mode 100644
index 0000000..e260687
--- /dev/null
+++ b/bottleneck/tests/data/test_524_A
@@ -0,0 +1,10 @@
+25 116
+12 34
+31 39
+56 152
+47 147
+67 112
+60 146
+77 112
+71 120
+67 75
diff --git a/bottleneck/tests/data/test_524_B b/bottleneck/tests/data/test_524_B
new file mode 100644
index 0000000..92a2d76
--- /dev/null
+++ b/bottleneck/tests/data/test_524_B
@@ -0,0 +1,10 @@
+2 10
+32 42
+24 123
+24 32
+84 135
+49 148
+100 181
+81 137
+63 96
+13 16
diff --git a/bottleneck/tests/data/test_525_A b/bottleneck/tests/data/test_525_A
new file mode 100644
index 0000000..25d9d8f
--- /dev/null
+++ b/bottleneck/tests/data/test_525_A
@@ -0,0 +1,10 @@
+51 101
+67 155
+84 155
+67 151
+39 122
+93 167
+83 117
+20 67
+39 136
+54 116
diff --git a/bottleneck/tests/data/test_525_B b/bottleneck/tests/data/test_525_B
new file mode 100644
index 0000000..d61ee84
--- /dev/null
+++ b/bottleneck/tests/data/test_525_B
@@ -0,0 +1,10 @@
+69 120
+93 141
+65 96
+8 81
+27 110
+94 178
+9 89
+1 91
+77 86
+33 49
diff --git a/bottleneck/tests/data/test_526_A b/bottleneck/tests/data/test_526_A
new file mode 100644
index 0000000..985ba29
--- /dev/null
+++ b/bottleneck/tests/data/test_526_A
@@ -0,0 +1,10 @@
+10 27
+53 116
+71 93
+88 122
+45 87
+82 167
+89 105
+20 101
+25 71
+61 124
diff --git a/bottleneck/tests/data/test_526_B b/bottleneck/tests/data/test_526_B
new file mode 100644
index 0000000..2ebf00a
--- /dev/null
+++ b/bottleneck/tests/data/test_526_B
@@ -0,0 +1,10 @@
+70 95
+68 69
+13 105
+58 156
+51 97
+64 106
+87 95
+63 85
+62 79
+82 87
diff --git a/bottleneck/tests/data/test_527_A b/bottleneck/tests/data/test_527_A
new file mode 100644
index 0000000..802b177
--- /dev/null
+++ b/bottleneck/tests/data/test_527_A
@@ -0,0 +1,10 @@
+5 27
+91 164
+68 91
+11 72
+37 66
+12 27
+30 47
+54 58
+34 80
+43 133
diff --git a/bottleneck/tests/data/test_527_B b/bottleneck/tests/data/test_527_B
new file mode 100644
index 0000000..a04d9f1
--- /dev/null
+++ b/bottleneck/tests/data/test_527_B
@@ -0,0 +1,10 @@
+88 156
+74 105
+64 69
+96 127
+10 93
+52 107
+58 134
+18 108
+80 108
+93 161
diff --git a/bottleneck/tests/data/test_528_A b/bottleneck/tests/data/test_528_A
new file mode 100644
index 0000000..da776dc
--- /dev/null
+++ b/bottleneck/tests/data/test_528_A
@@ -0,0 +1,10 @@
+36 107
+14 86
+45 96
+22 58
+57 103
+92 138
+65 150
+33 94
+40 79
+50 54
diff --git a/bottleneck/tests/data/test_528_B b/bottleneck/tests/data/test_528_B
new file mode 100644
index 0000000..5329277
--- /dev/null
+++ b/bottleneck/tests/data/test_528_B
@@ -0,0 +1,10 @@
+39 122
+19 43
+88 130
+48 106
+27 69
+93 140
+1 23
+50 94
+87 139
+97 151
diff --git a/bottleneck/tests/data/test_529_A b/bottleneck/tests/data/test_529_A
new file mode 100644
index 0000000..ebbf6fa
--- /dev/null
+++ b/bottleneck/tests/data/test_529_A
@@ -0,0 +1,10 @@
+80 140
+0 97
+28 29
+15 85
+21 35
+34 74
+26 27
+91 135
+21 36
+33 117
diff --git a/bottleneck/tests/data/test_529_B b/bottleneck/tests/data/test_529_B
new file mode 100644
index 0000000..6e0f836
--- /dev/null
+++ b/bottleneck/tests/data/test_529_B
@@ -0,0 +1,10 @@
+22 46
+0 79
+33 86
+14 99
+71 108
+83 91
+40 69
+36 45
+42 112
+44 75
diff --git a/bottleneck/tests/data/test_530_A b/bottleneck/tests/data/test_530_A
new file mode 100644
index 0000000..904eac4
--- /dev/null
+++ b/bottleneck/tests/data/test_530_A
@@ -0,0 +1,10 @@
+89 119
+35 104
+90 95
+6 77
+44 71
+46 100
+40 127
+11 52
+28 81
+39 73
diff --git a/bottleneck/tests/data/test_530_B b/bottleneck/tests/data/test_530_B
new file mode 100644
index 0000000..f4cfc4c
--- /dev/null
+++ b/bottleneck/tests/data/test_530_B
@@ -0,0 +1,10 @@
+79 179
+39 89
+5 67
+39 66
+88 162
+82 97
+80 156
+91 182
+44 110
+56 67
diff --git a/bottleneck/tests/data/test_531_A b/bottleneck/tests/data/test_531_A
new file mode 100644
index 0000000..416eb0a
--- /dev/null
+++ b/bottleneck/tests/data/test_531_A
@@ -0,0 +1,10 @@
+33 133
+73 98
+77 129
+21 118
+9 21
+68 166
+13 46
+53 84
+48 75
+24 90
diff --git a/bottleneck/tests/data/test_531_B b/bottleneck/tests/data/test_531_B
new file mode 100644
index 0000000..afb424a
--- /dev/null
+++ b/bottleneck/tests/data/test_531_B
@@ -0,0 +1,10 @@
+89 148
+25 112
+86 132
+78 106
+57 70
+92 160
+67 86
+94 123
+12 26
+65 117
diff --git a/bottleneck/tests/data/test_532_A b/bottleneck/tests/data/test_532_A
new file mode 100644
index 0000000..7eb97c1
--- /dev/null
+++ b/bottleneck/tests/data/test_532_A
@@ -0,0 +1,10 @@
+8 62
+77 140
+23 60
+13 93
+67 74
+59 152
+22 65
+16 17
+97 98
+76 91
diff --git a/bottleneck/tests/data/test_532_B b/bottleneck/tests/data/test_532_B
new file mode 100644
index 0000000..e86a6a0
--- /dev/null
+++ b/bottleneck/tests/data/test_532_B
@@ -0,0 +1,10 @@
+66 111
+54 74
+95 142
+96 167
+63 84
+76 84
+53 59
+97 130
+20 68
+5 58
diff --git a/bottleneck/tests/data/test_533_A b/bottleneck/tests/data/test_533_A
new file mode 100644
index 0000000..0462a89
--- /dev/null
+++ b/bottleneck/tests/data/test_533_A
@@ -0,0 +1,10 @@
+66 103
+20 42
+30 31
+61 90
+31 129
+49 53
+2 3
+78 122
+36 103
+59 63
diff --git a/bottleneck/tests/data/test_533_B b/bottleneck/tests/data/test_533_B
new file mode 100644
index 0000000..d077aa2
--- /dev/null
+++ b/bottleneck/tests/data/test_533_B
@@ -0,0 +1,10 @@
+51 121
+9 63
+71 121
+66 100
+89 111
+15 23
+98 110
+15 96
+4 52
+96 119
diff --git a/bottleneck/tests/data/test_534_A b/bottleneck/tests/data/test_534_A
new file mode 100644
index 0000000..a5c6b69
--- /dev/null
+++ b/bottleneck/tests/data/test_534_A
@@ -0,0 +1,10 @@
+84 177
+8 103
+81 176
+0 71
+4 80
+59 123
+42 63
+1 98
+86 169
+31 97
diff --git a/bottleneck/tests/data/test_534_B b/bottleneck/tests/data/test_534_B
new file mode 100644
index 0000000..10d4e7b
--- /dev/null
+++ b/bottleneck/tests/data/test_534_B
@@ -0,0 +1,10 @@
+8 56
+35 95
+62 104
+26 105
+32 52
+1 48
+87 150
+61 77
+12 66
+62 96
diff --git a/bottleneck/tests/data/test_535_A b/bottleneck/tests/data/test_535_A
new file mode 100644
index 0000000..faaf29f
--- /dev/null
+++ b/bottleneck/tests/data/test_535_A
@@ -0,0 +1,10 @@
+40 53
+9 46
+94 119
+85 113
+2 97
+62 162
+74 89
+87 118
+76 120
+33 39
diff --git a/bottleneck/tests/data/test_535_B b/bottleneck/tests/data/test_535_B
new file mode 100644
index 0000000..108c8a3
--- /dev/null
+++ b/bottleneck/tests/data/test_535_B
@@ -0,0 +1,10 @@
+6 82
+22 100
+2 82
+71 123
+91 179
+14 107
+28 38
+71 83
+6 60
+1 5
diff --git a/bottleneck/tests/data/test_536_A b/bottleneck/tests/data/test_536_A
new file mode 100644
index 0000000..320f5af
--- /dev/null
+++ b/bottleneck/tests/data/test_536_A
@@ -0,0 +1,10 @@
+87 179
+24 37
+14 64
+10 103
+92 160
+96 136
+86 171
+21 54
+22 32
+71 169
diff --git a/bottleneck/tests/data/test_536_B b/bottleneck/tests/data/test_536_B
new file mode 100644
index 0000000..9ce91f5
--- /dev/null
+++ b/bottleneck/tests/data/test_536_B
@@ -0,0 +1,10 @@
+73 151
+54 87
+79 166
+69 149
+77 132
+49 149
+86 107
+72 119
+35 77
+52 56
diff --git a/bottleneck/tests/data/test_537_A b/bottleneck/tests/data/test_537_A
new file mode 100644
index 0000000..c41e293
--- /dev/null
+++ b/bottleneck/tests/data/test_537_A
@@ -0,0 +1,10 @@
+4 80
+18 78
+55 56
+32 118
+79 151
+5 78
+11 12
+89 113
+99 120
+26 85
diff --git a/bottleneck/tests/data/test_537_B b/bottleneck/tests/data/test_537_B
new file mode 100644
index 0000000..a10f64d
--- /dev/null
+++ b/bottleneck/tests/data/test_537_B
@@ -0,0 +1,10 @@
+53 138
+80 135
+34 112
+20 46
+79 122
+21 87
+82 83
+91 112
+59 139
+9 97
diff --git a/bottleneck/tests/data/test_538_A b/bottleneck/tests/data/test_538_A
new file mode 100644
index 0000000..0d98495
--- /dev/null
+++ b/bottleneck/tests/data/test_538_A
@@ -0,0 +1,10 @@
+68 91
+38 132
+6 57
+24 46
+71 79
+61 129
+59 82
+15 105
+77 79
+44 117
diff --git a/bottleneck/tests/data/test_538_B b/bottleneck/tests/data/test_538_B
new file mode 100644
index 0000000..6dde6f3
--- /dev/null
+++ b/bottleneck/tests/data/test_538_B
@@ -0,0 +1,10 @@
+0 89
+73 128
+54 150
+79 98
+62 137
+51 66
+67 99
+31 100
+68 105
+19 30
diff --git a/bottleneck/tests/data/test_539_A b/bottleneck/tests/data/test_539_A
new file mode 100644
index 0000000..a844d1c
--- /dev/null
+++ b/bottleneck/tests/data/test_539_A
@@ -0,0 +1,10 @@
+72 140
+32 108
+64 99
+78 130
+74 122
+92 134
+71 75
+14 89
+86 134
+1 36
diff --git a/bottleneck/tests/data/test_539_B b/bottleneck/tests/data/test_539_B
new file mode 100644
index 0000000..824a004
--- /dev/null
+++ b/bottleneck/tests/data/test_539_B
@@ -0,0 +1,10 @@
+2 56
+57 82
+6 38
+60 68
+80 101
+27 57
+56 133
+45 75
+42 103
+38 78
diff --git a/bottleneck/tests/data/test_540_A b/bottleneck/tests/data/test_540_A
new file mode 100644
index 0000000..26bd782
--- /dev/null
+++ b/bottleneck/tests/data/test_540_A
@@ -0,0 +1,20 @@
+98 163
+65 109
+99 135
+11 83
+36 76
+57 84
+97 180
+22 87
+27 51
+92 190
+66 102
+32 76
+78 125
+70 144
+72 127
+50 51
+34 112
+3 39
+37 79
+55 143
diff --git a/bottleneck/tests/data/test_540_B b/bottleneck/tests/data/test_540_B
new file mode 100644
index 0000000..224839d
--- /dev/null
+++ b/bottleneck/tests/data/test_540_B
@@ -0,0 +1,20 @@
+90 182
+48 122
+34 109
+78 115
+60 110
+78 134
+58 59
+14 27
+48 94
+63 100
+88 171
+29 123
+20 61
+66 115
+46 61
+5 74
+94 189
+46 80
+85 88
+9 75
diff --git a/bottleneck/tests/data/test_541_A b/bottleneck/tests/data/test_541_A
new file mode 100644
index 0000000..fe8039b
--- /dev/null
+++ b/bottleneck/tests/data/test_541_A
@@ -0,0 +1,20 @@
+79 102
+50 71
+80 116
+35 44
+54 112
+89 90
+16 90
+14 30
+44 122
+98 135
+45 68
+46 125
+0 11
+46 94
+75 79
+76 89
+15 82
+84 95
+49 61
+68 123
diff --git a/bottleneck/tests/data/test_541_B b/bottleneck/tests/data/test_541_B
new file mode 100644
index 0000000..c33af0e
--- /dev/null
+++ b/bottleneck/tests/data/test_541_B
@@ -0,0 +1,20 @@
+39 108
+72 146
+49 50
+31 72
+84 104
+72 90
+57 81
+14 74
+69 74
+88 157
+9 65
+34 46
+44 87
+39 65
+14 77
+22 116
+5 58
+43 113
+62 120
+85 118
diff --git a/bottleneck/tests/data/test_542_A b/bottleneck/tests/data/test_542_A
new file mode 100644
index 0000000..d45ea52
--- /dev/null
+++ b/bottleneck/tests/data/test_542_A
@@ -0,0 +1,20 @@
+17 49
+64 156
+91 96
+83 142
+90 118
+20 59
+26 69
+82 118
+94 179
+1 20
+81 123
+89 165
+17 71
+60 85
+56 147
+94 175
+82 148
+31 118
+51 95
+12 41
diff --git a/bottleneck/tests/data/test_542_B b/bottleneck/tests/data/test_542_B
new file mode 100644
index 0000000..9dcdf8a
--- /dev/null
+++ b/bottleneck/tests/data/test_542_B
@@ -0,0 +1,20 @@
+21 47
+41 90
+78 121
+36 93
+8 108
+78 117
+31 92
+97 102
+12 96
+83 89
+36 85
+2 81
+24 86
+26 105
+10 99
+59 101
+45 98
+94 162
+57 60
+29 81
diff --git a/bottleneck/tests/data/test_543_A b/bottleneck/tests/data/test_543_A
new file mode 100644
index 0000000..511fbc1
--- /dev/null
+++ b/bottleneck/tests/data/test_543_A
@@ -0,0 +1,20 @@
+92 188
+94 159
+77 175
+13 23
+92 186
+85 144
+100 191
+34 48
+58 103
+74 113
+73 95
+34 66
+2 98
+80 95
+82 140
+38 133
+67 121
+65 70
+83 86
+90 143
diff --git a/bottleneck/tests/data/test_543_B b/bottleneck/tests/data/test_543_B
new file mode 100644
index 0000000..879080c
--- /dev/null
+++ b/bottleneck/tests/data/test_543_B
@@ -0,0 +1,20 @@
+100 168
+52 97
+35 39
+4 38
+42 55
+47 117
+49 145
+16 48
+99 145
+45 54
+69 129
+8 103
+47 108
+25 70
+93 148
+96 133
+44 49
+94 115
+48 53
+44 109
diff --git a/bottleneck/tests/data/test_544_A b/bottleneck/tests/data/test_544_A
new file mode 100644
index 0000000..a355d41
--- /dev/null
+++ b/bottleneck/tests/data/test_544_A
@@ -0,0 +1,20 @@
+31 114
+22 94
+10 88
+82 134
+28 106
+90 188
+78 130
+87 176
+99 155
+71 116
+39 105
+8 40
+96 184
+53 100
+77 79
+26 96
+30 116
+82 167
+62 122
+95 152
diff --git a/bottleneck/tests/data/test_544_B b/bottleneck/tests/data/test_544_B
new file mode 100644
index 0000000..83587cf
--- /dev/null
+++ b/bottleneck/tests/data/test_544_B
@@ -0,0 +1,20 @@
+75 125
+7 26
+61 102
+98 99
+12 88
+49 63
+46 61
+77 111
+13 56
+37 89
+7 84
+51 69
+86 142
+98 140
+91 122
+10 65
+9 33
+6 70
+95 101
+26 111
diff --git a/bottleneck/tests/data/test_545_A b/bottleneck/tests/data/test_545_A
new file mode 100644
index 0000000..c5351d7
--- /dev/null
+++ b/bottleneck/tests/data/test_545_A
@@ -0,0 +1,20 @@
+52 89
+34 54
+44 124
+82 128
+75 104
+26 120
+77 159
+11 42
+75 153
+89 189
+52 73
+43 128
+45 132
+80 160
+53 55
+76 122
+96 114
+64 109
+20 119
+99 145
diff --git a/bottleneck/tests/data/test_545_B b/bottleneck/tests/data/test_545_B
new file mode 100644
index 0000000..0c60c17
--- /dev/null
+++ b/bottleneck/tests/data/test_545_B
@@ -0,0 +1,20 @@
+74 118
+29 69
+19 82
+50 124
+82 155
+15 63
+35 51
+38 52
+11 105
+70 114
+19 86
+91 157
+98 151
+14 83
+39 126
+38 52
+57 68
+79 137
+21 66
+68 92
diff --git a/bottleneck/tests/data/test_546_A b/bottleneck/tests/data/test_546_A
new file mode 100644
index 0000000..4391c84
--- /dev/null
+++ b/bottleneck/tests/data/test_546_A
@@ -0,0 +1,20 @@
+60 91
+46 132
+27 127
+4 36
+66 116
+73 113
+56 98
+29 66
+38 88
+18 24
+19 52
+32 119
+39 81
+71 110
+24 46
+81 90
+80 111
+47 88
+94 142
+42 47
diff --git a/bottleneck/tests/data/test_546_B b/bottleneck/tests/data/test_546_B
new file mode 100644
index 0000000..3d3dec6
--- /dev/null
+++ b/bottleneck/tests/data/test_546_B
@@ -0,0 +1,20 @@
+82 101
+14 80
+56 78
+28 113
+61 125
+70 88
+30 47
+88 176
+84 169
+15 92
+17 19
+33 61
+33 34
+60 142
+7 8
+5 34
+99 140
+35 113
+14 46
+74 112
diff --git a/bottleneck/tests/data/test_547_A b/bottleneck/tests/data/test_547_A
new file mode 100644
index 0000000..1388d05
--- /dev/null
+++ b/bottleneck/tests/data/test_547_A
@@ -0,0 +1,20 @@
+36 57
+27 86
+11 103
+73 132
+5 58
+59 66
+26 35
+0 18
+47 138
+49 118
+23 79
+12 99
+9 35
+15 79
+18 25
+94 137
+8 50
+68 78
+79 179
+31 121
diff --git a/bottleneck/tests/data/test_547_B b/bottleneck/tests/data/test_547_B
new file mode 100644
index 0000000..dbb925d
--- /dev/null
+++ b/bottleneck/tests/data/test_547_B
@@ -0,0 +1,20 @@
+24 75
+28 29
+35 81
+81 178
+25 79
+78 106
+23 93
+57 151
+96 135
+85 151
+73 149
+37 98
+10 24
+30 61
+39 67
+68 74
+57 79
+66 160
+60 151
+66 139
diff --git a/bottleneck/tests/data/test_548_A b/bottleneck/tests/data/test_548_A
new file mode 100644
index 0000000..08c858e
--- /dev/null
+++ b/bottleneck/tests/data/test_548_A
@@ -0,0 +1,20 @@
+15 24
+24 72
+67 142
+71 97
+26 61
+99 158
+61 82
+100 198
+51 114
+10 98
+46 93
+74 171
+14 75
+85 101
+30 40
+37 42
+2 16
+48 64
+48 99
+77 170
diff --git a/bottleneck/tests/data/test_548_B b/bottleneck/tests/data/test_548_B
new file mode 100644
index 0000000..b6dda3a
--- /dev/null
+++ b/bottleneck/tests/data/test_548_B
@@ -0,0 +1,20 @@
+51 59
+99 108
+89 148
+82 96
+55 117
+52 148
+74 133
+37 99
+6 71
+0 15
+100 170
+28 56
+12 39
+61 98
+24 92
+18 88
+63 158
+91 129
+79 154
+39 85
diff --git a/bottleneck/tests/data/test_549_A b/bottleneck/tests/data/test_549_A
new file mode 100644
index 0000000..b0d5ddf
--- /dev/null
+++ b/bottleneck/tests/data/test_549_A
@@ -0,0 +1,20 @@
+35 44
+1 25
+100 168
+81 169
+40 84
+28 37
+50 58
+60 122
+4 27
+2 99
+67 145
+51 111
+96 148
+47 65
+64 159
+54 114
+90 113
+4 36
+94 178
+19 20
diff --git a/bottleneck/tests/data/test_549_B b/bottleneck/tests/data/test_549_B
new file mode 100644
index 0000000..a44a982
--- /dev/null
+++ b/bottleneck/tests/data/test_549_B
@@ -0,0 +1,20 @@
+68 146
+8 27
+6 64
+76 113
+71 89
+29 65
+74 133
+52 57
+21 26
+2 39
+95 194
+67 113
+14 20
+90 160
+93 171
+72 97
+57 157
+23 42
+13 70
+17 44
diff --git a/bottleneck/tests/data/test_550_A b/bottleneck/tests/data/test_550_A
new file mode 100644
index 0000000..b8ba8e8
--- /dev/null
+++ b/bottleneck/tests/data/test_550_A
@@ -0,0 +1,20 @@
+76 145
+38 79
+44 90
+71 155
+48 63
+88 125
+36 107
+91 136
+25 33
+49 57
+37 70
+69 116
+63 64
+70 118
+43 115
+80 99
+42 71
+86 91
+96 166
+69 121
diff --git a/bottleneck/tests/data/test_550_B b/bottleneck/tests/data/test_550_B
new file mode 100644
index 0000000..ed900f0
--- /dev/null
+++ b/bottleneck/tests/data/test_550_B
@@ -0,0 +1,20 @@
+25 66
+55 107
+62 87
+15 49
+46 99
+25 39
+73 94
+43 126
+85 163
+12 96
+48 127
+21 26
+40 45
+88 188
+77 109
+38 44
+0 66
+57 59
+85 104
+32 54
diff --git a/bottleneck/tests/data/test_551_A b/bottleneck/tests/data/test_551_A
new file mode 100644
index 0000000..3002ec2
--- /dev/null
+++ b/bottleneck/tests/data/test_551_A
@@ -0,0 +1,20 @@
+68 98
+42 48
+4 5
+6 82
+41 83
+94 141
+17 48
+33 105
+71 162
+55 95
+43 132
+81 162
+6 32
+88 101
+76 85
+36 70
+42 45
+60 122
+83 127
+100 148
diff --git a/bottleneck/tests/data/test_551_B b/bottleneck/tests/data/test_551_B
new file mode 100644
index 0000000..5a9b2de
--- /dev/null
+++ b/bottleneck/tests/data/test_551_B
@@ -0,0 +1,20 @@
+58 109
+88 154
+56 66
+76 142
+86 125
+95 181
+46 85
+15 43
+55 79
+77 104
+45 113
+66 74
+64 100
+45 138
+6 62
+36 79
+77 106
+82 115
+15 110
+62 156
diff --git a/bottleneck/tests/data/test_552_A b/bottleneck/tests/data/test_552_A
new file mode 100644
index 0000000..19de840
--- /dev/null
+++ b/bottleneck/tests/data/test_552_A
@@ -0,0 +1,20 @@
+10 104
+23 89
+7 13
+66 150
+92 157
+22 43
+35 62
+96 187
+84 89
+75 160
+88 118
+74 99
+43 138
+20 37
+90 176
+85 157
+90 168
+63 157
+59 106
+68 92
diff --git a/bottleneck/tests/data/test_552_B b/bottleneck/tests/data/test_552_B
new file mode 100644
index 0000000..54b3e00
--- /dev/null
+++ b/bottleneck/tests/data/test_552_B
@@ -0,0 +1,20 @@
+57 121
+94 173
+84 133
+61 106
+71 130
+44 114
+55 73
+100 144
+91 126
+60 109
+44 92
+23 87
+52 116
+24 25
+10 93
+60 140
+11 55
+96 155
+76 165
+38 129
diff --git a/bottleneck/tests/data/test_553_A b/bottleneck/tests/data/test_553_A
new file mode 100644
index 0000000..deff96a
--- /dev/null
+++ b/bottleneck/tests/data/test_553_A
@@ -0,0 +1,20 @@
+1 4
+23 91
+97 103
+6 68
+13 25
+9 18
+65 122
+91 154
+41 76
+86 132
+31 62
+93 167
+45 50
+70 166
+38 113
+52 132
+77 161
+13 60
+39 65
+60 69
diff --git a/bottleneck/tests/data/test_553_B b/bottleneck/tests/data/test_553_B
new file mode 100644
index 0000000..ee7ce9b
--- /dev/null
+++ b/bottleneck/tests/data/test_553_B
@@ -0,0 +1,20 @@
+51 60
+76 151
+87 157
+49 110
+78 112
+3 59
+55 98
+26 121
+69 158
+15 63
+70 109
+30 46
+23 75
+65 138
+87 120
+7 46
+99 187
+43 69
+73 161
+37 93
diff --git a/bottleneck/tests/data/test_554_A b/bottleneck/tests/data/test_554_A
new file mode 100644
index 0000000..da38226
--- /dev/null
+++ b/bottleneck/tests/data/test_554_A
@@ -0,0 +1,20 @@
+69 134
+81 159
+100 168
+96 111
+46 134
+56 61
+8 31
+63 119
+57 137
+16 84
+5 51
+79 128
+20 117
+85 136
+34 88
+23 73
+3 87
+10 34
+72 120
+36 71
diff --git a/bottleneck/tests/data/test_554_B b/bottleneck/tests/data/test_554_B
new file mode 100644
index 0000000..8583236
--- /dev/null
+++ b/bottleneck/tests/data/test_554_B
@@ -0,0 +1,20 @@
+14 62
+54 74
+87 164
+57 87
+70 113
+5 75
+86 185
+3 69
+36 52
+31 93
+85 104
+4 97
+89 149
+19 92
+70 120
+13 18
+48 72
+100 152
+35 48
+94 191
diff --git a/bottleneck/tests/data/test_555_A b/bottleneck/tests/data/test_555_A
new file mode 100644
index 0000000..87cd93d
--- /dev/null
+++ b/bottleneck/tests/data/test_555_A
@@ -0,0 +1,20 @@
+23 58
+71 106
+56 155
+37 85
+88 186
+12 75
+23 86
+17 92
+30 96
+13 54
+53 152
+84 153
+15 22
+67 86
+93 147
+17 117
+99 170
+75 108
+18 118
+71 131
diff --git a/bottleneck/tests/data/test_555_B b/bottleneck/tests/data/test_555_B
new file mode 100644
index 0000000..2b8c351
--- /dev/null
+++ b/bottleneck/tests/data/test_555_B
@@ -0,0 +1,20 @@
+9 71
+95 131
+85 156
+86 142
+10 54
+56 119
+49 100
+30 50
+7 64
+27 82
+14 85
+33 35
+22 52
+92 171
+36 62
+85 133
+4 14
+47 124
+70 131
+14 29
diff --git a/bottleneck/tests/data/test_556_A b/bottleneck/tests/data/test_556_A
new file mode 100644
index 0000000..182965d
--- /dev/null
+++ b/bottleneck/tests/data/test_556_A
@@ -0,0 +1,20 @@
+79 147
+83 144
+20 30
+92 185
+29 40
+46 90
+21 106
+15 24
+16 63
+62 67
+18 106
+52 127
+47 64
+15 84
+10 87
+16 102
+89 139
+64 68
+57 128
+37 120
diff --git a/bottleneck/tests/data/test_556_B b/bottleneck/tests/data/test_556_B
new file mode 100644
index 0000000..f2e3409
--- /dev/null
+++ b/bottleneck/tests/data/test_556_B
@@ -0,0 +1,20 @@
+84 125
+37 84
+38 46
+32 59
+36 76
+95 107
+82 144
+81 121
+72 145
+1 100
+70 143
+76 167
+8 26
+51 90
+74 165
+88 89
+56 155
+95 165
+24 109
+45 141
diff --git a/bottleneck/tests/data/test_557_A b/bottleneck/tests/data/test_557_A
new file mode 100644
index 0000000..ac233bb
--- /dev/null
+++ b/bottleneck/tests/data/test_557_A
@@ -0,0 +1,20 @@
+47 91
+57 100
+93 157
+12 91
+95 109
+26 103
+55 78
+58 106
+5 96
+25 85
+76 97
+20 78
+85 160
+71 144
+81 145
+58 59
+49 86
+31 35
+89 156
+15 82
diff --git a/bottleneck/tests/data/test_557_B b/bottleneck/tests/data/test_557_B
new file mode 100644
index 0000000..f838403
--- /dev/null
+++ b/bottleneck/tests/data/test_557_B
@@ -0,0 +1,20 @@
+31 112
+70 120
+12 49
+95 96
+27 87
+50 120
+78 115
+22 108
+54 82
+31 109
+51 74
+55 140
+7 92
+88 133
+61 82
+90 183
+33 64
+90 121
+26 47
+98 120
diff --git a/bottleneck/tests/data/test_558_A b/bottleneck/tests/data/test_558_A
new file mode 100644
index 0000000..7108d09
--- /dev/null
+++ b/bottleneck/tests/data/test_558_A
@@ -0,0 +1,20 @@
+57 115
+32 131
+32 111
+46 104
+8 12
+20 69
+65 89
+8 37
+88 153
+61 63
+86 139
+74 88
+3 62
+58 104
+31 100
+29 81
+55 59
+11 18
+63 103
+56 110
diff --git a/bottleneck/tests/data/test_558_B b/bottleneck/tests/data/test_558_B
new file mode 100644
index 0000000..dd19869
--- /dev/null
+++ b/bottleneck/tests/data/test_558_B
@@ -0,0 +1,20 @@
+43 134
+43 44
+56 124
+97 118
+34 68
+56 140
+41 140
+24 95
+57 91
+22 28
+94 158
+69 141
+94 110
+7 41
+39 59
+69 107
+76 163
+30 105
+96 142
+46 127
diff --git a/bottleneck/tests/data/test_559_A b/bottleneck/tests/data/test_559_A
new file mode 100644
index 0000000..46f07b4
--- /dev/null
+++ b/bottleneck/tests/data/test_559_A
@@ -0,0 +1,20 @@
+21 99
+7 104
+89 130
+91 181
+19 90
+57 146
+15 60
+66 123
+13 58
+3 57
+39 114
+4 53
+80 125
+83 132
+81 98
+14 99
+81 175
+49 92
+39 125
+31 111
diff --git a/bottleneck/tests/data/test_559_B b/bottleneck/tests/data/test_559_B
new file mode 100644
index 0000000..b747fb8
--- /dev/null
+++ b/bottleneck/tests/data/test_559_B
@@ -0,0 +1,20 @@
+13 43
+81 86
+45 84
+84 111
+39 83
+85 115
+70 150
+97 192
+70 107
+21 74
+71 73
+98 184
+14 114
+63 126
+21 59
+53 147
+70 114
+30 56
+34 35
+61 133
diff --git a/bottleneck/tests/data/test_560_A b/bottleneck/tests/data/test_560_A
new file mode 100644
index 0000000..9b704ae
--- /dev/null
+++ b/bottleneck/tests/data/test_560_A
@@ -0,0 +1,30 @@
+35 126
+34 37
+78 84
+70 127
+97 106
+42 49
+49 105
+50 150
+80 140
+30 128
+90 136
+77 173
+42 98
+17 97
+100 181
+30 45
+6 40
+30 75
+66 148
+13 66
+39 113
+53 106
+65 133
+1 17
+61 123
+37 114
+1 77
+6 19
+8 11
+20 95
diff --git a/bottleneck/tests/data/test_560_B b/bottleneck/tests/data/test_560_B
new file mode 100644
index 0000000..d4ece9d
--- /dev/null
+++ b/bottleneck/tests/data/test_560_B
@@ -0,0 +1,30 @@
+100 150
+25 32
+99 187
+42 117
+60 84
+22 104
+15 113
+29 58
+91 185
+92 120
+95 133
+42 67
+62 148
+79 122
+27 66
+14 75
+44 142
+10 25
+54 149
+31 38
+97 161
+63 115
+29 76
+100 102
+59 72
+54 140
+8 108
+12 83
+54 127
+43 95
diff --git a/bottleneck/tests/data/test_561_A b/bottleneck/tests/data/test_561_A
new file mode 100644
index 0000000..81a3e31
--- /dev/null
+++ b/bottleneck/tests/data/test_561_A
@@ -0,0 +1,30 @@
+13 66
+67 124
+99 163
+91 163
+42 140
+96 153
+6 77
+6 83
+84 166
+48 79
+50 79
+63 111
+21 85
+55 117
+62 160
+4 101
+30 75
+42 87
+58 60
+88 178
+43 54
+90 120
+72 147
+30 70
+13 66
+89 166
+83 149
+69 160
+66 83
+89 142
diff --git a/bottleneck/tests/data/test_561_B b/bottleneck/tests/data/test_561_B
new file mode 100644
index 0000000..c60b08c
--- /dev/null
+++ b/bottleneck/tests/data/test_561_B
@@ -0,0 +1,30 @@
+61 97
+8 94
+32 68
+55 101
+24 56
+25 30
+33 79
+16 111
+72 82
+42 86
+93 143
+94 163
+69 168
+68 100
+3 102
+9 72
+6 74
+4 46
+97 130
+15 27
+12 33
+62 67
+37 74
+0 76
+14 102
+33 95
+46 131
+89 90
+79 97
+100 109
diff --git a/bottleneck/tests/data/test_562_A b/bottleneck/tests/data/test_562_A
new file mode 100644
index 0000000..6dadf55
--- /dev/null
+++ b/bottleneck/tests/data/test_562_A
@@ -0,0 +1,30 @@
+12 41
+99 100
+15 60
+95 108
+9 108
+4 5
+96 161
+88 168
+12 106
+78 167
+80 164
+69 130
+88 161
+49 134
+18 76
+54 134
+45 136
+22 50
+21 78
+17 88
+46 117
+97 174
+25 95
+8 9
+43 123
+25 107
+58 73
+2 7
+89 152
+81 114
diff --git a/bottleneck/tests/data/test_562_B b/bottleneck/tests/data/test_562_B
new file mode 100644
index 0000000..48eaf77
--- /dev/null
+++ b/bottleneck/tests/data/test_562_B
@@ -0,0 +1,30 @@
+5 104
+17 105
+43 120
+87 88
+35 71
+47 55
+57 87
+66 119
+26 114
+4 9
+29 70
+40 95
+61 73
+20 31
+85 148
+47 59
+34 43
+36 50
+70 77
+30 47
+36 56
+9 55
+35 127
+36 84
+83 118
+90 98
+69 85
+34 104
+76 127
+78 99
diff --git a/bottleneck/tests/data/test_563_A b/bottleneck/tests/data/test_563_A
new file mode 100644
index 0000000..954685e
--- /dev/null
+++ b/bottleneck/tests/data/test_563_A
@@ -0,0 +1,30 @@
+51 145
+19 119
+94 179
+8 35
+90 155
+34 39
+55 96
+19 27
+84 95
+12 52
+14 101
+72 143
+1 14
+88 138
+95 109
+85 134
+54 149
+35 85
+50 55
+93 173
+81 108
+14 112
+23 67
+13 14
+21 37
+89 177
+63 163
+2 89
+5 61
+18 76
diff --git a/bottleneck/tests/data/test_563_B b/bottleneck/tests/data/test_563_B
new file mode 100644
index 0000000..c3d7844
--- /dev/null
+++ b/bottleneck/tests/data/test_563_B
@@ -0,0 +1,30 @@
+40 75
+52 88
+0 33
+63 134
+19 77
+34 106
+67 164
+6 61
+67 144
+41 105
+30 108
+17 24
+97 105
+61 90
+45 80
+34 52
+58 140
+46 52
+4 13
+43 143
+74 168
+85 148
+24 55
+80 84
+3 56
+39 138
+1 30
+14 20
+14 91
+42 48
diff --git a/bottleneck/tests/data/test_564_A b/bottleneck/tests/data/test_564_A
new file mode 100644
index 0000000..a39b7ae
--- /dev/null
+++ b/bottleneck/tests/data/test_564_A
@@ -0,0 +1,30 @@
+85 112
+83 119
+84 128
+36 100
+18 112
+83 89
+17 80
+68 147
+32 76
+42 46
+29 89
+9 49
+40 135
+65 75
+69 113
+87 184
+81 103
+13 81
+44 99
+17 51
+99 102
+86 89
+29 124
+52 140
+19 54
+73 173
+89 172
+6 33
+80 139
+52 58
diff --git a/bottleneck/tests/data/test_564_B b/bottleneck/tests/data/test_564_B
new file mode 100644
index 0000000..22adad2
--- /dev/null
+++ b/bottleneck/tests/data/test_564_B
@@ -0,0 +1,30 @@
+56 66
+92 164
+7 68
+87 135
+45 70
+94 109
+32 103
+44 73
+36 124
+50 139
+88 102
+17 116
+3 61
+90 149
+41 62
+13 42
+19 51
+96 105
+55 143
+67 165
+44 129
+72 171
+20 51
+36 119
+35 96
+33 107
+48 106
+9 30
+36 110
+90 114
diff --git a/bottleneck/tests/data/test_565_A b/bottleneck/tests/data/test_565_A
new file mode 100644
index 0000000..34eb265
--- /dev/null
+++ b/bottleneck/tests/data/test_565_A
@@ -0,0 +1,30 @@
+33 61
+68 78
+90 98
+66 127
+93 152
+21 29
+49 52
+78 171
+42 55
+95 159
+82 141
+85 152
+22 25
+71 132
+24 75
+3 82
+42 131
+24 73
+89 155
+32 132
+77 159
+97 165
+89 92
+50 82
+52 102
+11 64
+47 135
+45 89
+11 52
+11 25
diff --git a/bottleneck/tests/data/test_565_B b/bottleneck/tests/data/test_565_B
new file mode 100644
index 0000000..da5ed1d
--- /dev/null
+++ b/bottleneck/tests/data/test_565_B
@@ -0,0 +1,30 @@
+46 66
+86 178
+19 102
+97 140
+22 97
+49 97
+6 48
+23 105
+92 157
+85 103
+67 167
+29 44
+88 183
+85 184
+90 93
+23 113
+30 106
+32 130
+81 154
+76 141
+75 101
+26 84
+9 77
+53 73
+23 84
+83 85
+6 44
+29 31
+26 107
+61 114
diff --git a/bottleneck/tests/data/test_566_A b/bottleneck/tests/data/test_566_A
new file mode 100644
index 0000000..55d0a13
--- /dev/null
+++ b/bottleneck/tests/data/test_566_A
@@ -0,0 +1,30 @@
+4 34
+20 53
+59 101
+40 70
+29 58
+67 107
+92 122
+35 120
+34 98
+34 79
+17 20
+12 53
+69 167
+19 88
+92 118
+21 73
+54 78
+0 83
+41 127
+34 59
+41 106
+4 102
+46 48
+99 189
+15 25
+17 19
+25 33
+25 108
+25 105
+64 99
diff --git a/bottleneck/tests/data/test_566_B b/bottleneck/tests/data/test_566_B
new file mode 100644
index 0000000..57c08b6
--- /dev/null
+++ b/bottleneck/tests/data/test_566_B
@@ -0,0 +1,30 @@
+36 121
+5 33
+47 137
+95 158
+43 105
+4 15
+0 59
+30 36
+29 106
+58 126
+81 129
+63 108
+52 147
+80 163
+93 94
+32 122
+12 92
+74 135
+25 28
+11 107
+91 182
+68 90
+90 106
+96 126
+83 117
+57 147
+89 181
+36 107
+24 68
+83 131
diff --git a/bottleneck/tests/data/test_567_A b/bottleneck/tests/data/test_567_A
new file mode 100644
index 0000000..3304c25
--- /dev/null
+++ b/bottleneck/tests/data/test_567_A
@@ -0,0 +1,30 @@
+67 79
+12 58
+33 85
+25 70
+79 128
+34 59
+22 45
+100 102
+25 57
+30 113
+77 89
+74 83
+43 138
+30 81
+26 64
+91 94
+83 149
+83 119
+44 46
+79 105
+49 140
+58 110
+92 104
+8 65
+40 52
+46 60
+9 17
+25 47
+25 125
+95 109
diff --git a/bottleneck/tests/data/test_567_B b/bottleneck/tests/data/test_567_B
new file mode 100644
index 0000000..4a8f5fa
--- /dev/null
+++ b/bottleneck/tests/data/test_567_B
@@ -0,0 +1,30 @@
+46 93
+85 165
+2 24
+29 81
+88 99
+94 109
+78 82
+54 69
+43 139
+3 40
+37 117
+98 138
+12 71
+75 84
+9 100
+56 65
+97 146
+56 105
+17 82
+11 44
+93 100
+6 99
+32 128
+9 35
+9 41
+66 123
+66 163
+34 110
+47 82
+15 97
diff --git a/bottleneck/tests/data/test_568_A b/bottleneck/tests/data/test_568_A
new file mode 100644
index 0000000..e6e0ecb
--- /dev/null
+++ b/bottleneck/tests/data/test_568_A
@@ -0,0 +1,30 @@
+20 98
+14 51
+82 116
+80 117
+96 109
+61 101
+44 75
+76 80
+64 96
+100 158
+13 89
+84 138
+0 16
+94 138
+32 117
+68 157
+7 24
+1 56
+72 101
+47 128
+85 90
+66 155
+33 106
+97 144
+50 139
+10 54
+23 77
+87 106
+37 104
+11 37
diff --git a/bottleneck/tests/data/test_568_B b/bottleneck/tests/data/test_568_B
new file mode 100644
index 0000000..081ff5e
--- /dev/null
+++ b/bottleneck/tests/data/test_568_B
@@ -0,0 +1,30 @@
+49 147
+26 112
+32 71
+30 50
+77 136
+10 110
+50 71
+14 110
+4 24
+64 125
+54 121
+58 142
+50 51
+0 63
+7 96
+49 146
+64 111
+53 122
+2 84
+56 102
+44 102
+5 78
+61 90
+32 92
+99 157
+100 188
+37 70
+6 7
+58 139
+52 138
diff --git a/bottleneck/tests/data/test_569_A b/bottleneck/tests/data/test_569_A
new file mode 100644
index 0000000..7fc96cf
--- /dev/null
+++ b/bottleneck/tests/data/test_569_A
@@ -0,0 +1,30 @@
+83 116
+33 112
+58 86
+3 65
+21 46
+51 58
+47 138
+88 112
+4 84
+4 8
+46 74
+74 132
+54 120
+2 68
+99 119
+5 43
+5 61
+54 75
+83 169
+100 192
+47 133
+27 28
+44 128
+19 77
+60 160
+46 55
+78 169
+16 82
+60 97
+57 60
diff --git a/bottleneck/tests/data/test_569_B b/bottleneck/tests/data/test_569_B
new file mode 100644
index 0000000..b732aac
--- /dev/null
+++ b/bottleneck/tests/data/test_569_B
@@ -0,0 +1,30 @@
+51 97
+59 91
+9 11
+49 50
+54 111
+44 132
+22 53
+11 80
+22 101
+76 79
+29 112
+99 123
+67 116
+69 110
+27 51
+22 55
+3 58
+43 84
+18 68
+88 134
+28 29
+70 137
+36 37
+85 168
+4 69
+50 99
+27 117
+12 69
+55 127
+23 28
diff --git a/bottleneck/tests/data/test_570_A b/bottleneck/tests/data/test_570_A
new file mode 100644
index 0000000..371835b
--- /dev/null
+++ b/bottleneck/tests/data/test_570_A
@@ -0,0 +1,30 @@
+30 76
+17 43
+84 85
+45 52
+85 117
+95 172
+36 58
+6 12
+70 147
+82 114
+67 163
+1 85
+1 92
+23 80
+58 60
+42 123
+100 148
+52 127
+45 49
+33 47
+48 124
+77 169
+5 64
+24 49
+16 40
+83 130
+86 121
+73 157
+88 124
+59 80
diff --git a/bottleneck/tests/data/test_570_B b/bottleneck/tests/data/test_570_B
new file mode 100644
index 0000000..3ce3450
--- /dev/null
+++ b/bottleneck/tests/data/test_570_B
@@ -0,0 +1,30 @@
+44 134
+28 120
+0 58
+32 41
+64 82
+7 91
+32 123
+22 46
+87 159
+3 13
+79 102
+37 80
+77 91
+64 126
+43 128
+53 107
+50 89
+15 111
+37 101
+6 51
+11 41
+66 110
+99 191
+8 53
+12 59
+53 91
+9 51
+47 57
+35 88
+83 134
diff --git a/bottleneck/tests/data/test_571_A b/bottleneck/tests/data/test_571_A
new file mode 100644
index 0000000..6b58a17
--- /dev/null
+++ b/bottleneck/tests/data/test_571_A
@@ -0,0 +1,30 @@
+73 83
+85 94
+20 39
+62 71
+100 146
+84 95
+21 64
+62 136
+49 90
+39 129
+92 156
+27 105
+48 66
+5 100
+86 186
+74 118
+93 173
+93 143
+91 173
+5 59
+75 78
+98 106
+37 125
+24 60
+24 117
+83 131
+69 137
+1 54
+81 154
+26 124
diff --git a/bottleneck/tests/data/test_571_B b/bottleneck/tests/data/test_571_B
new file mode 100644
index 0000000..0bb3b3e
--- /dev/null
+++ b/bottleneck/tests/data/test_571_B
@@ -0,0 +1,30 @@
+90 159
+93 97
+57 109
+87 127
+96 185
+53 142
+59 125
+54 132
+26 48
+54 150
+63 65
+36 50
+3 19
+19 95
+47 76
+25 36
+34 70
+63 126
+99 199
+11 38
+96 120
+89 162
+55 125
+3 98
+11 31
+18 103
+68 101
+47 68
+45 48
+36 59
diff --git a/bottleneck/tests/data/test_572_A b/bottleneck/tests/data/test_572_A
new file mode 100644
index 0000000..052ddfe
--- /dev/null
+++ b/bottleneck/tests/data/test_572_A
@@ -0,0 +1,30 @@
+83 96
+59 158
+99 133
+98 139
+71 163
+95 138
+83 97
+46 72
+23 29
+49 133
+60 63
+6 84
+33 86
+33 71
+99 188
+51 61
+79 150
+38 61
+68 147
+98 170
+77 131
+32 97
+57 119
+36 37
+66 75
+37 68
+72 150
+42 99
+28 90
+56 123
diff --git a/bottleneck/tests/data/test_572_B b/bottleneck/tests/data/test_572_B
new file mode 100644
index 0000000..d816eab
--- /dev/null
+++ b/bottleneck/tests/data/test_572_B
@@ -0,0 +1,30 @@
+44 61
+72 88
+8 15
+78 155
+90 99
+87 106
+50 57
+60 126
+75 175
+81 135
+94 181
+6 52
+64 152
+63 79
+23 105
+88 104
+68 145
+9 26
+23 68
+49 144
+5 9
+62 156
+6 94
+61 159
+82 130
+26 84
+78 110
+27 75
+41 123
+56 147
diff --git a/bottleneck/tests/data/test_573_A b/bottleneck/tests/data/test_573_A
new file mode 100644
index 0000000..fe68d64
--- /dev/null
+++ b/bottleneck/tests/data/test_573_A
@@ -0,0 +1,30 @@
+43 94
+41 75
+26 69
+43 58
+64 94
+54 98
+19 106
+99 119
+52 115
+79 88
+77 84
+96 118
+55 80
+47 114
+64 137
+79 158
+38 60
+79 136
+57 82
+17 103
+28 82
+28 35
+74 86
+99 121
+96 176
+0 55
+2 76
+85 155
+9 40
+76 118
diff --git a/bottleneck/tests/data/test_573_B b/bottleneck/tests/data/test_573_B
new file mode 100644
index 0000000..9824068
--- /dev/null
+++ b/bottleneck/tests/data/test_573_B
@@ -0,0 +1,30 @@
+60 107
+11 66
+34 94
+40 87
+1 4
+43 67
+25 76
+73 108
+86 178
+25 58
+95 99
+82 97
+13 54
+58 88
+38 78
+44 131
+92 99
+5 88
+98 120
+56 112
+45 112
+69 110
+48 121
+53 83
+20 52
+3 45
+49 126
+13 17
+30 83
+97 121
diff --git a/bottleneck/tests/data/test_574_A b/bottleneck/tests/data/test_574_A
new file mode 100644
index 0000000..9dbb066
--- /dev/null
+++ b/bottleneck/tests/data/test_574_A
@@ -0,0 +1,30 @@
+21 109
+12 79
+44 58
+0 97
+30 124
+58 154
+91 150
+1 92
+34 43
+18 109
+10 11
+0 84
+30 56
+66 166
+43 80
+77 167
+61 94
+58 136
+20 110
+84 144
+100 182
+8 80
+79 124
+89 164
+61 84
+69 129
+30 111
+67 105
+69 70
+38 108
diff --git a/bottleneck/tests/data/test_574_B b/bottleneck/tests/data/test_574_B
new file mode 100644
index 0000000..dc0f4c7
--- /dev/null
+++ b/bottleneck/tests/data/test_574_B
@@ -0,0 +1,30 @@
+24 53
+49 112
+58 149
+49 136
+66 149
+10 87
+36 113
+66 144
+87 150
+20 40
+41 136
+80 111
+99 199
+76 131
+7 72
+99 122
+93 124
+5 8
+97 105
+23 27
+82 102
+30 84
+62 143
+8 48
+40 119
+29 62
+11 68
+75 128
+68 124
+23 26
diff --git a/bottleneck/tests/data/test_575_A b/bottleneck/tests/data/test_575_A
new file mode 100644
index 0000000..7703382
--- /dev/null
+++ b/bottleneck/tests/data/test_575_A
@@ -0,0 +1,30 @@
+78 141
+24 58
+30 120
+71 72
+4 21
+30 61
+7 52
+16 91
+58 109
+28 97
+46 86
+65 134
+86 151
+77 134
+6 32
+31 83
+84 180
+53 118
+78 108
+88 115
+75 137
+92 149
+57 120
+94 109
+59 131
+5 36
+39 91
+65 138
+96 167
+87 164
diff --git a/bottleneck/tests/data/test_575_B b/bottleneck/tests/data/test_575_B
new file mode 100644
index 0000000..a5ba6b7
--- /dev/null
+++ b/bottleneck/tests/data/test_575_B
@@ -0,0 +1,30 @@
+77 176
+11 43
+38 70
+64 163
+70 101
+18 66
+50 119
+30 48
+18 88
+85 106
+50 56
+42 134
+25 92
+5 53
+86 101
+44 91
+61 127
+42 55
+31 103
+15 23
+93 117
+45 68
+39 84
+64 135
+86 109
+82 174
+72 73
+43 73
+37 41
+71 76
diff --git a/bottleneck/tests/data/test_576_A b/bottleneck/tests/data/test_576_A
new file mode 100644
index 0000000..57eb281
--- /dev/null
+++ b/bottleneck/tests/data/test_576_A
@@ -0,0 +1,30 @@
+61 135
+79 123
+27 28
+4 48
+44 120
+40 69
+28 82
+4 45
+28 82
+70 145
+14 102
+84 169
+89 121
+67 137
+65 141
+39 60
+97 162
+90 187
+23 78
+71 168
+76 98
+85 101
+9 86
+57 89
+86 109
+55 62
+90 101
+82 110
+100 153
+33 67
diff --git a/bottleneck/tests/data/test_576_B b/bottleneck/tests/data/test_576_B
new file mode 100644
index 0000000..fa63de8
--- /dev/null
+++ b/bottleneck/tests/data/test_576_B
@@ -0,0 +1,30 @@
+83 145
+27 62
+71 125
+78 175
+11 55
+81 94
+91 141
+27 103
+68 97
+54 89
+68 143
+50 100
+65 85
+84 179
+83 96
+44 121
+13 86
+29 86
+72 172
+95 140
+83 161
+83 100
+98 167
+8 66
+75 101
+6 50
+10 58
+5 57
+51 77
+87 140
diff --git a/bottleneck/tests/data/test_577_A b/bottleneck/tests/data/test_577_A
new file mode 100644
index 0000000..d086e3f
--- /dev/null
+++ b/bottleneck/tests/data/test_577_A
@@ -0,0 +1,30 @@
+65 94
+1 2
+30 31
+91 131
+75 170
+38 85
+51 73
+78 155
+43 141
+54 109
+53 54
+36 74
+75 80
+51 144
+33 127
+31 89
+0 10
+18 87
+11 18
+51 126
+64 91
+7 51
+26 71
+92 160
+24 44
+0 58
+3 78
+2 67
+12 88
+68 130
diff --git a/bottleneck/tests/data/test_577_B b/bottleneck/tests/data/test_577_B
new file mode 100644
index 0000000..e48e09a
--- /dev/null
+++ b/bottleneck/tests/data/test_577_B
@@ -0,0 +1,30 @@
+90 189
+96 195
+64 91
+81 84
+42 76
+17 19
+76 77
+64 149
+85 99
+90 147
+60 95
+59 155
+29 121
+27 104
+10 72
+32 79
+44 129
+9 70
+68 136
+9 75
+27 89
+70 148
+77 149
+8 91
+24 84
+90 123
+86 105
+64 94
+84 109
+31 51
diff --git a/bottleneck/tests/data/test_578_A b/bottleneck/tests/data/test_578_A
new file mode 100644
index 0000000..8b9a6fe
--- /dev/null
+++ b/bottleneck/tests/data/test_578_A
@@ -0,0 +1,30 @@
+9 99
+58 83
+62 110
+32 102
+86 169
+95 131
+1 6
+1 55
+88 154
+67 95
+21 22
+31 118
+15 52
+64 92
+36 87
+18 106
+71 150
+10 55
+67 97
+53 145
+31 40
+33 62
+79 116
+70 110
+96 145
+86 182
+43 116
+54 145
+100 172
+74 84
diff --git a/bottleneck/tests/data/test_578_B b/bottleneck/tests/data/test_578_B
new file mode 100644
index 0000000..636f20d
--- /dev/null
+++ b/bottleneck/tests/data/test_578_B
@@ -0,0 +1,30 @@
+33 36
+89 175
+83 151
+61 138
+4 15
+9 58
+38 111
+29 117
+22 79
+26 86
+48 55
+65 134
+60 84
+23 96
+69 149
+29 48
+38 137
+39 51
+88 112
+14 41
+29 119
+52 56
+55 96
+58 127
+78 148
+44 64
+35 108
+69 124
+6 80
+43 77
diff --git a/bottleneck/tests/data/test_579_A b/bottleneck/tests/data/test_579_A
new file mode 100644
index 0000000..99bbb96
--- /dev/null
+++ b/bottleneck/tests/data/test_579_A
@@ -0,0 +1,30 @@
+90 170
+5 32
+49 116
+37 88
+19 64
+81 177
+39 77
+37 123
+53 127
+31 76
+67 114
+51 125
+48 121
+59 62
+31 119
+35 90
+100 117
+33 130
+22 74
+23 41
+71 159
+3 57
+22 61
+86 123
+91 115
+66 92
+39 104
+85 134
+72 160
+6 94
diff --git a/bottleneck/tests/data/test_579_B b/bottleneck/tests/data/test_579_B
new file mode 100644
index 0000000..6d3e9b6
--- /dev/null
+++ b/bottleneck/tests/data/test_579_B
@@ -0,0 +1,30 @@
+76 123
+2 17
+41 123
+62 138
+40 70
+92 164
+70 105
+63 109
+14 23
+26 109
+78 141
+85 162
+37 49
+27 96
+62 68
+80 136
+30 72
+44 85
+59 122
+42 137
+67 140
+81 181
+43 84
+91 108
+71 86
+30 45
+76 94
+25 57
+25 71
+70 90
diff --git a/bottleneck/tests/data/test_580_A b/bottleneck/tests/data/test_580_A
new file mode 100644
index 0000000..b8d1c86
--- /dev/null
+++ b/bottleneck/tests/data/test_580_A
@@ -0,0 +1,50 @@
+34 78
+25 82
+42 132
+77 154
+15 52
+54 69
+68 78
+36 111
+9 24
+30 53
+53 117
+84 163
+91 124
+13 76
+20 59
+67 151
+17 103
+76 156
+3 41
+2 37
+65 158
+67 75
+42 125
+83 115
+47 147
+13 44
+83 133
+92 146
+57 125
+66 103
+55 69
+39 63
+16 63
+98 108
+23 93
+12 30
+7 70
+70 131
+49 127
+83 90
+97 171
+35 81
+78 130
+88 143
+62 124
+2 40
+66 110
+51 61
+2 25
+69 74
diff --git a/bottleneck/tests/data/test_580_B b/bottleneck/tests/data/test_580_B
new file mode 100644
index 0000000..1fd48af
--- /dev/null
+++ b/bottleneck/tests/data/test_580_B
@@ -0,0 +1,50 @@
+60 156
+65 78
+70 102
+52 113
+64 154
+45 126
+45 86
+6 49
+7 93
+99 127
+15 33
+1 36
+12 30
+30 89
+41 84
+66 131
+8 23
+0 9
+95 149
+47 83
+69 165
+79 91
+74 125
+59 77
+93 137
+33 119
+24 113
+98 116
+10 70
+57 124
+97 126
+48 113
+30 67
+2 15
+56 86
+75 111
+81 82
+99 196
+69 105
+51 147
+5 69
+40 136
+79 147
+44 136
+95 194
+67 93
+0 46
+26 90
+58 115
+40 87
diff --git a/bottleneck/tests/data/test_581_A b/bottleneck/tests/data/test_581_A
new file mode 100644
index 0000000..cf1555c
--- /dev/null
+++ b/bottleneck/tests/data/test_581_A
@@ -0,0 +1,50 @@
+79 87
+81 162
+7 74
+53 79
+19 50
+30 106
+68 155
+17 79
+75 90
+55 71
+30 127
+57 145
+78 80
+11 96
+16 47
+56 131
+45 46
+75 136
+17 75
+72 74
+27 114
+28 112
+31 123
+37 110
+89 159
+57 85
+49 52
+72 130
+68 86
+88 152
+5 66
+67 71
+51 91
+72 82
+3 21
+21 38
+47 86
+37 108
+35 123
+49 119
+36 97
+36 119
+9 48
+16 36
+32 37
+38 68
+82 147
+39 79
+23 101
+33 104
diff --git a/bottleneck/tests/data/test_581_B b/bottleneck/tests/data/test_581_B
new file mode 100644
index 0000000..853ac92
--- /dev/null
+++ b/bottleneck/tests/data/test_581_B
@@ -0,0 +1,50 @@
+94 181
+38 90
+83 137
+36 93
+8 53
+59 118
+21 110
+94 175
+18 40
+94 120
+46 81
+54 145
+13 37
+36 100
+73 86
+67 166
+91 187
+11 15
+45 124
+23 29
+89 125
+78 101
+83 98
+52 73
+39 62
+15 86
+80 140
+100 181
+50 55
+80 124
+27 29
+19 76
+92 167
+12 57
+63 134
+45 46
+42 110
+93 179
+31 130
+59 137
+7 99
+77 107
+59 127
+82 160
+27 70
+100 200
+80 101
+16 97
+93 184
+15 48
diff --git a/bottleneck/tests/data/test_582_A b/bottleneck/tests/data/test_582_A
new file mode 100644
index 0000000..dcabc9f
--- /dev/null
+++ b/bottleneck/tests/data/test_582_A
@@ -0,0 +1,50 @@
+85 106
+23 89
+31 90
+4 42
+45 104
+100 137
+32 115
+65 112
+25 82
+75 158
+74 147
+6 106
+92 179
+91 110
+94 150
+9 19
+91 110
+82 108
+39 90
+49 69
+73 89
+61 68
+22 85
+13 57
+86 102
+23 43
+29 65
+3 72
+85 131
+71 80
+83 89
+73 119
+28 46
+33 101
+18 24
+38 69
+50 51
+84 85
+75 175
+99 153
+84 86
+97 100
+68 115
+91 108
+62 77
+54 80
+7 49
+26 29
+53 101
+64 73
diff --git a/bottleneck/tests/data/test_582_B b/bottleneck/tests/data/test_582_B
new file mode 100644
index 0000000..9420fa9
--- /dev/null
+++ b/bottleneck/tests/data/test_582_B
@@ -0,0 +1,50 @@
+99 153
+54 92
+64 65
+40 117
+28 70
+33 105
+70 105
+72 109
+9 34
+72 151
+1 46
+57 133
+51 72
+52 119
+44 92
+13 71
+96 191
+80 123
+47 121
+84 162
+69 111
+15 35
+41 45
+23 86
+36 107
+6 18
+63 118
+4 50
+84 107
+90 132
+74 127
+14 37
+75 167
+42 81
+53 76
+32 88
+2 70
+87 129
+7 8
+6 35
+70 115
+69 137
+80 174
+24 107
+66 116
+22 110
+4 90
+0 41
+63 160
+99 142
diff --git a/bottleneck/tests/data/test_583_A b/bottleneck/tests/data/test_583_A
new file mode 100644
index 0000000..cc36f56
--- /dev/null
+++ b/bottleneck/tests/data/test_583_A
@@ -0,0 +1,50 @@
+99 127
+62 97
+4 61
+70 121
+74 149
+79 158
+98 193
+22 53
+66 89
+45 58
+49 80
+56 89
+48 124
+100 166
+76 143
+32 33
+15 59
+16 91
+32 33
+1 21
+73 169
+84 171
+49 69
+52 146
+10 57
+26 112
+54 76
+92 125
+47 49
+53 107
+2 69
+99 186
+67 79
+13 113
+54 73
+1 72
+4 20
+43 112
+0 89
+77 150
+31 61
+24 29
+75 169
+56 143
+88 133
+37 38
+90 160
+97 189
+39 72
+30 38
diff --git a/bottleneck/tests/data/test_583_B b/bottleneck/tests/data/test_583_B
new file mode 100644
index 0000000..d021fb3
--- /dev/null
+++ b/bottleneck/tests/data/test_583_B
@@ -0,0 +1,50 @@
+26 43
+87 160
+74 100
+69 139
+72 87
+22 58
+0 3
+67 133
+52 56
+67 97
+42 117
+30 44
+67 119
+91 164
+45 65
+35 127
+80 91
+75 160
+11 68
+86 92
+24 79
+90 156
+91 94
+64 114
+55 66
+72 80
+36 78
+85 114
+27 69
+40 75
+65 152
+48 106
+72 105
+63 109
+37 108
+48 84
+81 147
+14 91
+46 94
+6 14
+28 100
+41 103
+21 92
+40 111
+42 106
+86 136
+97 113
+24 79
+77 99
+80 89
diff --git a/bottleneck/tests/data/test_584_A b/bottleneck/tests/data/test_584_A
new file mode 100644
index 0000000..c934a50
--- /dev/null
+++ b/bottleneck/tests/data/test_584_A
@@ -0,0 +1,50 @@
+15 100
+30 70
+46 69
+99 128
+25 93
+75 90
+6 31
+47 141
+51 99
+98 133
+50 69
+3 27
+16 91
+36 95
+29 73
+26 76
+24 45
+9 105
+21 103
+46 81
+91 156
+77 141
+36 72
+92 122
+48 98
+34 105
+80 172
+92 136
+16 81
+30 100
+13 111
+1 51
+1 52
+66 140
+81 96
+18 69
+37 123
+82 132
+64 114
+6 26
+46 70
+39 74
+20 108
+70 128
+43 86
+50 71
+73 98
+42 74
+52 79
+42 101
diff --git a/bottleneck/tests/data/test_584_B b/bottleneck/tests/data/test_584_B
new file mode 100644
index 0000000..9f07efc
--- /dev/null
+++ b/bottleneck/tests/data/test_584_B
@@ -0,0 +1,50 @@
+99 143
+58 93
+32 121
+23 112
+64 102
+73 110
+76 128
+18 108
+17 97
+82 97
+40 138
+43 92
+18 33
+36 60
+2 27
+67 132
+45 79
+40 78
+90 97
+98 163
+16 86
+74 83
+98 154
+7 74
+3 41
+43 55
+69 123
+54 154
+96 143
+66 98
+26 52
+6 47
+45 84
+17 50
+32 78
+15 25
+46 133
+41 115
+54 144
+19 39
+71 150
+77 133
+42 90
+100 165
+73 113
+63 67
+19 106
+11 18
+11 73
+67 69
diff --git a/bottleneck/tests/data/test_585_A b/bottleneck/tests/data/test_585_A
new file mode 100644
index 0000000..903e5b1
--- /dev/null
+++ b/bottleneck/tests/data/test_585_A
@@ -0,0 +1,50 @@
+50 147
+39 41
+59 153
+79 105
+90 122
+21 31
+34 51
+27 64
+77 125
+46 115
+92 164
+81 167
+91 182
+15 87
+39 115
+43 113
+29 115
+9 60
+81 95
+45 89
+36 101
+29 41
+68 132
+40 110
+33 92
+2 3
+27 113
+90 152
+35 109
+48 90
+63 160
+46 102
+61 146
+48 68
+23 98
+53 91
+80 101
+50 55
+78 163
+89 126
+62 145
+64 129
+18 31
+27 110
+58 91
+6 20
+84 103
+54 120
+87 162
+97 144
diff --git a/bottleneck/tests/data/test_585_B b/bottleneck/tests/data/test_585_B
new file mode 100644
index 0000000..69f116a
--- /dev/null
+++ b/bottleneck/tests/data/test_585_B
@@ -0,0 +1,50 @@
+41 56
+85 176
+84 155
+25 40
+33 60
+84 92
+66 123
+63 66
+24 60
+4 51
+74 84
+13 70
+4 15
+86 102
+29 120
+62 70
+29 94
+11 20
+71 162
+87 165
+24 118
+65 93
+28 97
+54 151
+42 126
+55 86
+50 150
+5 35
+80 103
+94 158
+85 147
+73 95
+26 96
+67 151
+38 102
+42 72
+8 36
+78 165
+15 16
+35 67
+0 64
+35 70
+15 69
+75 96
+17 44
+42 66
+41 68
+80 88
+35 128
+34 113
diff --git a/bottleneck/tests/data/test_586_A b/bottleneck/tests/data/test_586_A
new file mode 100644
index 0000000..ed8b673
--- /dev/null
+++ b/bottleneck/tests/data/test_586_A
@@ -0,0 +1,50 @@
+62 74
+15 108
+49 131
+94 134
+5 6
+24 120
+35 79
+48 73
+84 170
+67 86
+30 98
+6 12
+60 107
+8 106
+6 57
+69 74
+24 120
+20 52
+78 147
+24 124
+76 87
+7 46
+20 115
+68 98
+51 87
+87 147
+83 93
+15 108
+70 103
+63 65
+70 90
+52 112
+54 107
+86 114
+58 137
+93 148
+43 120
+3 55
+20 97
+14 25
+59 111
+68 119
+78 165
+16 50
+3 5
+89 173
+84 181
+93 184
+89 185
+23 61
diff --git a/bottleneck/tests/data/test_586_B b/bottleneck/tests/data/test_586_B
new file mode 100644
index 0000000..715be5e
--- /dev/null
+++ b/bottleneck/tests/data/test_586_B
@@ -0,0 +1,50 @@
+5 85
+46 116
+51 79
+20 36
+51 96
+83 170
+40 116
+40 128
+55 92
+51 127
+45 111
+56 65
+16 56
+30 52
+38 84
+56 70
+48 88
+0 6
+99 148
+64 159
+30 101
+14 51
+49 116
+66 71
+9 78
+4 35
+84 128
+39 58
+85 96
+54 60
+14 89
+2 46
+40 120
+76 117
+14 80
+47 118
+86 175
+35 126
+77 112
+75 150
+14 52
+90 169
+25 32
+73 95
+92 157
+5 34
+62 131
+16 26
+5 103
+73 106
diff --git a/bottleneck/tests/data/test_587_A b/bottleneck/tests/data/test_587_A
new file mode 100644
index 0000000..883ddd7
--- /dev/null
+++ b/bottleneck/tests/data/test_587_A
@@ -0,0 +1,50 @@
+66 164
+74 81
+56 140
+77 143
+72 139
+77 113
+59 106
+37 42
+58 158
+46 52
+7 30
+73 107
+46 70
+35 120
+74 103
+71 117
+26 93
+11 68
+35 60
+91 151
+33 122
+30 106
+43 134
+90 131
+32 95
+8 72
+4 39
+17 115
+22 32
+28 100
+37 126
+84 152
+72 107
+68 157
+95 193
+93 191
+56 154
+39 42
+5 45
+62 121
+73 166
+14 51
+89 140
+76 166
+85 150
+18 112
+22 103
+65 147
+96 181
+55 123
diff --git a/bottleneck/tests/data/test_587_B b/bottleneck/tests/data/test_587_B
new file mode 100644
index 0000000..589512c
--- /dev/null
+++ b/bottleneck/tests/data/test_587_B
@@ -0,0 +1,50 @@
+4 57
+12 64
+65 153
+73 111
+37 134
+11 54
+78 176
+33 77
+31 131
+14 101
+25 107
+83 112
+17 92
+59 139
+4 104
+82 114
+18 64
+13 72
+1 96
+72 112
+19 90
+23 34
+46 63
+45 79
+88 89
+16 105
+100 191
+31 46
+45 133
+86 119
+17 18
+59 140
+49 97
+31 47
+98 154
+70 99
+61 75
+31 34
+4 19
+46 122
+55 57
+81 171
+25 61
+18 89
+0 11
+48 79
+94 128
+73 122
+17 56
+19 39
diff --git a/bottleneck/tests/data/test_588_A b/bottleneck/tests/data/test_588_A
new file mode 100644
index 0000000..c486b96
--- /dev/null
+++ b/bottleneck/tests/data/test_588_A
@@ -0,0 +1,50 @@
+96 166
+5 58
+87 143
+50 104
+31 106
+80 106
+99 106
+46 52
+42 127
+10 86
+17 18
+20 94
+49 65
+10 75
+85 132
+13 54
+75 123
+8 13
+83 153
+25 47
+57 135
+14 57
+1 37
+29 34
+13 26
+52 94
+62 97
+93 153
+69 84
+87 88
+73 100
+54 97
+11 72
+51 143
+66 94
+85 178
+60 73
+36 126
+99 134
+23 68
+72 134
+81 138
+28 42
+65 84
+11 28
+15 38
+18 51
+79 149
+76 114
+33 53
diff --git a/bottleneck/tests/data/test_588_B b/bottleneck/tests/data/test_588_B
new file mode 100644
index 0000000..13829bc
--- /dev/null
+++ b/bottleneck/tests/data/test_588_B
@@ -0,0 +1,50 @@
+87 173
+41 85
+10 87
+43 78
+99 128
+35 64
+28 66
+9 67
+100 194
+22 89
+0 15
+77 90
+59 60
+92 93
+32 84
+62 112
+54 151
+46 47
+52 94
+17 113
+21 100
+5 48
+87 114
+71 112
+2 67
+65 120
+26 74
+69 132
+47 83
+14 20
+5 13
+56 137
+57 79
+76 132
+30 31
+89 145
+84 130
+78 158
+44 76
+70 125
+95 127
+6 53
+17 110
+93 158
+61 94
+32 111
+20 113
+26 105
+63 112
+36 37
diff --git a/bottleneck/tests/data/test_589_A b/bottleneck/tests/data/test_589_A
new file mode 100644
index 0000000..7743778
--- /dev/null
+++ b/bottleneck/tests/data/test_589_A
@@ -0,0 +1,50 @@
+71 126
+62 78
+69 164
+34 56
+82 167
+61 138
+63 94
+17 27
+81 135
+94 145
+24 39
+93 134
+99 152
+38 91
+27 100
+21 115
+69 120
+8 42
+93 122
+87 155
+18 104
+0 2
+41 104
+63 159
+93 139
+74 167
+3 94
+68 92
+30 44
+24 101
+8 104
+8 61
+59 111
+53 91
+43 68
+52 143
+11 48
+74 152
+20 115
+27 100
+65 81
+63 67
+84 85
+16 30
+71 80
+58 116
+95 188
+96 106
+7 94
+38 45
diff --git a/bottleneck/tests/data/test_589_B b/bottleneck/tests/data/test_589_B
new file mode 100644
index 0000000..bbd5038
--- /dev/null
+++ b/bottleneck/tests/data/test_589_B
@@ -0,0 +1,50 @@
+28 114
+87 171
+0 35
+94 100
+98 147
+53 68
+64 95
+54 145
+45 76
+22 98
+83 155
+31 89
+27 79
+32 37
+28 58
+77 139
+87 143
+80 152
+25 28
+61 123
+0 4
+25 42
+64 159
+34 37
+84 153
+13 93
+25 69
+80 112
+89 163
+18 77
+35 119
+35 114
+39 60
+90 187
+0 33
+11 80
+52 140
+59 73
+92 168
+76 91
+49 88
+80 130
+37 104
+65 146
+14 56
+66 95
+87 182
+12 102
+78 135
+73 143
diff --git a/bottleneck/tests/data/test_590_A b/bottleneck/tests/data/test_590_A
new file mode 100644
index 0000000..3dfb2df
--- /dev/null
+++ b/bottleneck/tests/data/test_590_A
@@ -0,0 +1,50 @@
+31 67
+88 180
+59 105
+31 117
+19 50
+43 59
+9 60
+4 58
+80 144
+47 71
+63 139
+14 68
+38 136
+8 52
+35 81
+56 116
+81 168
+56 99
+95 142
+24 121
+29 100
+88 174
+47 95
+40 93
+7 25
+3 84
+48 94
+90 128
+59 137
+96 164
+95 115
+69 105
+81 139
+59 65
+66 71
+53 84
+20 59
+29 61
+77 150
+48 138
+41 125
+53 86
+5 86
+42 69
+17 54
+70 105
+69 148
+18 58
+72 100
+67 77
diff --git a/bottleneck/tests/data/test_590_B b/bottleneck/tests/data/test_590_B
new file mode 100644
index 0000000..18d6a7f
--- /dev/null
+++ b/bottleneck/tests/data/test_590_B
@@ -0,0 +1,50 @@
+79 84
+10 56
+10 18
+78 175
+50 74
+8 104
+77 116
+5 45
+48 116
+17 92
+72 159
+66 113
+51 140
+60 101
+76 120
+52 75
+3 71
+31 53
+75 156
+93 172
+4 93
+11 42
+89 167
+19 49
+62 119
+55 97
+39 68
+74 140
+64 97
+97 154
+30 98
+16 59
+18 68
+66 139
+9 44
+56 74
+61 82
+51 115
+45 51
+89 121
+71 134
+82 119
+13 113
+36 43
+21 121
+24 115
+37 65
+99 100
+36 135
+37 96
diff --git a/bottleneck/tests/data/test_591_A b/bottleneck/tests/data/test_591_A
new file mode 100644
index 0000000..411c1bb
--- /dev/null
+++ b/bottleneck/tests/data/test_591_A
@@ -0,0 +1,50 @@
+13 93
+48 89
+12 53
+4 87
+91 181
+15 16
+29 59
+38 57
+8 29
+73 165
+29 44
+45 67
+24 74
+50 91
+88 162
+30 105
+80 134
+58 61
+69 135
+31 107
+0 15
+17 115
+72 74
+45 50
+75 115
+76 97
+61 89
+45 112
+59 97
+32 50
+85 88
+35 124
+95 112
+76 147
+69 84
+12 47
+100 154
+92 163
+4 55
+23 76
+85 100
+96 170
+28 87
+17 116
+44 57
+22 118
+51 134
+32 91
+8 14
+25 80
diff --git a/bottleneck/tests/data/test_591_B b/bottleneck/tests/data/test_591_B
new file mode 100644
index 0000000..cc96d2f
--- /dev/null
+++ b/bottleneck/tests/data/test_591_B
@@ -0,0 +1,50 @@
+85 150
+85 96
+57 94
+13 112
+48 89
+7 17
+47 136
+96 173
+100 144
+12 76
+75 90
+51 116
+33 72
+21 65
+41 66
+80 104
+4 53
+71 72
+52 77
+93 94
+20 76
+29 101
+47 104
+33 87
+47 48
+73 161
+32 37
+4 74
+30 57
+56 109
+95 138
+76 135
+70 160
+59 136
+29 105
+75 169
+100 154
+67 139
+28 104
+89 121
+1 18
+7 47
+100 134
+3 4
+29 85
+79 129
+48 89
+97 191
+60 153
+100 199
diff --git a/bottleneck/tests/data/test_592_A b/bottleneck/tests/data/test_592_A
new file mode 100644
index 0000000..bac0698
--- /dev/null
+++ b/bottleneck/tests/data/test_592_A
@@ -0,0 +1,50 @@
+59 132
+83 149
+50 62
+45 103
+28 32
+74 163
+78 151
+19 85
+26 113
+42 136
+87 123
+49 108
+7 69
+45 84
+96 153
+50 112
+3 72
+91 136
+16 79
+56 105
+92 170
+92 177
+15 57
+13 104
+90 112
+16 87
+99 154
+91 174
+49 76
+39 137
+38 59
+25 33
+88 113
+85 136
+38 67
+44 73
+75 166
+60 131
+56 155
+86 105
+69 75
+54 108
+8 79
+68 103
+56 133
+29 91
+57 77
+42 109
+97 170
+89 92
diff --git a/bottleneck/tests/data/test_592_B b/bottleneck/tests/data/test_592_B
new file mode 100644
index 0000000..bc8a8c6
--- /dev/null
+++ b/bottleneck/tests/data/test_592_B
@@ -0,0 +1,50 @@
+73 140
+34 69
+82 101
+44 70
+26 87
+76 151
+18 43
+14 83
+35 126
+31 86
+59 125
+89 160
+33 38
+38 79
+54 77
+51 91
+75 87
+4 94
+2 23
+75 152
+1 8
+65 100
+60 80
+62 96
+40 116
+0 66
+10 99
+21 48
+98 161
+0 35
+18 25
+61 68
+58 152
+97 161
+43 99
+25 35
+55 59
+78 151
+6 94
+17 60
+98 142
+81 119
+2 29
+0 95
+55 141
+29 99
+14 44
+32 68
+31 107
+26 74
diff --git a/bottleneck/tests/data/test_593_A b/bottleneck/tests/data/test_593_A
new file mode 100644
index 0000000..e62ec21
--- /dev/null
+++ b/bottleneck/tests/data/test_593_A
@@ -0,0 +1,50 @@
+15 96
+50 89
+53 59
+42 45
+76 150
+24 110
+27 126
+26 79
+93 132
+65 100
+38 134
+14 68
+88 130
+92 120
+36 122
+24 77
+11 102
+56 91
+12 77
+89 131
+57 137
+86 173
+38 66
+7 27
+49 134
+38 81
+100 122
+85 98
+96 147
+25 80
+49 88
+32 127
+42 122
+3 11
+25 59
+11 31
+82 151
+97 187
+55 99
+11 71
+14 28
+80 105
+4 74
+89 113
+99 127
+40 75
+86 121
+44 52
+74 123
+51 105
diff --git a/bottleneck/tests/data/test_593_B b/bottleneck/tests/data/test_593_B
new file mode 100644
index 0000000..a5150da
--- /dev/null
+++ b/bottleneck/tests/data/test_593_B
@@ -0,0 +1,50 @@
+70 127
+81 175
+6 42
+67 74
+18 95
+32 33
+98 188
+25 67
+99 170
+60 119
+35 79
+20 42
+28 64
+92 129
+26 110
+95 123
+37 130
+25 97
+44 136
+30 78
+42 72
+52 139
+80 177
+44 143
+79 122
+100 198
+74 90
+15 73
+48 63
+66 146
+77 168
+28 66
+72 103
+23 77
+84 133
+37 127
+70 139
+85 129
+13 32
+57 151
+26 83
+7 45
+14 16
+23 70
+94 117
+71 148
+9 89
+20 109
+64 85
+27 106
diff --git a/bottleneck/tests/data/test_594_A b/bottleneck/tests/data/test_594_A
new file mode 100644
index 0000000..ca81d4c
--- /dev/null
+++ b/bottleneck/tests/data/test_594_A
@@ -0,0 +1,50 @@
+49 127
+45 58
+50 143
+52 55
+32 102
+79 154
+36 134
+61 161
+41 134
+31 71
+51 86
+88 135
+68 93
+30 68
+8 80
+3 68
+36 101
+15 73
+51 132
+95 180
+27 43
+28 56
+58 73
+32 108
+85 179
+11 17
+65 159
+6 40
+27 53
+72 151
+66 114
+17 56
+84 95
+35 80
+85 110
+97 167
+74 84
+96 134
+76 117
+61 99
+20 91
+89 114
+1 32
+0 29
+71 138
+53 123
+78 96
+57 138
+7 89
+92 105
diff --git a/bottleneck/tests/data/test_594_B b/bottleneck/tests/data/test_594_B
new file mode 100644
index 0000000..d366e85
--- /dev/null
+++ b/bottleneck/tests/data/test_594_B
@@ -0,0 +1,50 @@
+46 86
+23 69
+40 50
+66 89
+63 123
+23 108
+61 79
+59 144
+60 156
+49 88
+60 92
+65 101
+56 64
+3 53
+84 141
+39 79
+36 101
+8 82
+61 138
+29 78
+14 108
+29 122
+93 124
+53 95
+70 89
+10 102
+10 104
+23 27
+6 53
+8 41
+86 164
+8 41
+51 120
+27 63
+33 60
+62 99
+56 119
+58 84
+39 118
+25 86
+6 67
+50 56
+91 173
+71 121
+28 51
+88 142
+90 186
+69 149
+87 102
+60 129
diff --git a/bottleneck/tests/data/test_595_A b/bottleneck/tests/data/test_595_A
new file mode 100644
index 0000000..805de28
--- /dev/null
+++ b/bottleneck/tests/data/test_595_A
@@ -0,0 +1,50 @@
+39 91
+72 162
+80 123
+46 113
+51 65
+80 149
+72 132
+27 124
+17 111
+17 71
+86 120
+82 102
+71 117
+33 86
+15 84
+76 146
+69 102
+97 153
+91 185
+5 53
+61 95
+85 107
+92 101
+80 113
+12 63
+62 111
+29 109
+33 77
+91 134
+49 138
+30 57
+70 106
+98 110
+87 168
+76 140
+20 109
+58 71
+56 99
+49 117
+60 118
+63 149
+9 92
+14 94
+12 52
+21 37
+37 91
+65 107
+98 101
+71 131
+54 108
diff --git a/bottleneck/tests/data/test_595_B b/bottleneck/tests/data/test_595_B
new file mode 100644
index 0000000..c458a54
--- /dev/null
+++ b/bottleneck/tests/data/test_595_B
@@ -0,0 +1,50 @@
+92 101
+74 76
+47 115
+99 119
+19 44
+57 156
+21 59
+12 86
+92 168
+73 148
+92 164
+47 130
+32 96
+22 116
+58 99
+85 169
+66 147
+31 117
+17 107
+83 158
+10 54
+95 129
+88 158
+72 78
+98 125
+99 170
+22 79
+10 16
+2 31
+52 62
+16 40
+31 103
+38 100
+32 82
+71 133
+55 135
+74 158
+13 45
+6 12
+13 43
+44 57
+25 51
+88 112
+35 66
+31 83
+28 59
+44 103
+40 131
+100 124
+21 107
diff --git a/bottleneck/tests/data/test_596_A b/bottleneck/tests/data/test_596_A
new file mode 100644
index 0000000..3a32cf7
--- /dev/null
+++ b/bottleneck/tests/data/test_596_A
@@ -0,0 +1,50 @@
+95 140
+26 108
+52 84
+39 95
+18 48
+29 105
+64 114
+75 103
+59 80
+11 95
+41 52
+43 123
+51 77
+31 54
+64 130
+23 79
+82 102
+53 94
+13 14
+19 74
+74 109
+71 140
+93 94
+76 82
+43 48
+46 70
+53 121
+35 68
+30 32
+13 53
+28 60
+51 111
+64 142
+84 153
+15 79
+89 140
+39 136
+15 37
+35 115
+15 105
+16 62
+3 77
+93 107
+88 104
+56 113
+59 142
+11 52
+22 64
+66 138
+32 75
diff --git a/bottleneck/tests/data/test_596_B b/bottleneck/tests/data/test_596_B
new file mode 100644
index 0000000..1b9c765
--- /dev/null
+++ b/bottleneck/tests/data/test_596_B
@@ -0,0 +1,50 @@
+73 154
+65 99
+56 77
+56 70
+67 75
+4 26
+31 64
+89 106
+73 91
+31 43
+98 185
+50 138
+79 131
+47 73
+16 55
+35 98
+24 100
+67 72
+44 95
+66 101
+40 91
+53 90
+6 67
+57 67
+15 111
+2 43
+3 18
+35 116
+44 138
+46 85
+31 41
+16 17
+61 96
+90 100
+45 129
+97 172
+38 70
+47 136
+26 56
+0 95
+100 155
+48 110
+4 60
+16 29
+74 103
+63 113
+93 98
+73 94
+15 86
+40 86
diff --git a/bottleneck/tests/data/test_597_A b/bottleneck/tests/data/test_597_A
new file mode 100644
index 0000000..984cc9f
--- /dev/null
+++ b/bottleneck/tests/data/test_597_A
@@ -0,0 +1,50 @@
+75 141
+50 130
+82 143
+98 128
+15 107
+9 22
+27 64
+2 51
+14 42
+15 27
+39 110
+50 95
+62 91
+80 85
+89 92
+56 78
+94 114
+68 130
+80 93
+12 25
+86 88
+33 73
+38 79
+28 100
+65 139
+22 59
+70 169
+45 118
+77 87
+46 49
+87 122
+50 109
+6 101
+8 21
+0 32
+16 81
+89 167
+83 85
+91 185
+85 120
+87 128
+20 58
+76 112
+13 60
+8 15
+93 172
+12 92
+51 132
+92 140
+83 167
diff --git a/bottleneck/tests/data/test_597_B b/bottleneck/tests/data/test_597_B
new file mode 100644
index 0000000..d84920c
--- /dev/null
+++ b/bottleneck/tests/data/test_597_B
@@ -0,0 +1,50 @@
+89 118
+56 104
+78 101
+56 103
+13 94
+98 186
+99 137
+58 90
+61 154
+0 12
+7 23
+77 158
+66 157
+70 91
+10 38
+14 23
+21 92
+89 189
+84 105
+79 130
+17 27
+93 102
+62 82
+60 84
+18 28
+49 143
+70 157
+54 119
+32 124
+17 89
+1 49
+4 53
+76 109
+61 113
+71 90
+4 95
+78 125
+21 110
+2 72
+26 106
+35 55
+76 90
+80 127
+80 137
+30 63
+12 81
+48 93
+27 123
+24 57
+56 120
diff --git a/bottleneck/tests/data/test_598_A b/bottleneck/tests/data/test_598_A
new file mode 100644
index 0000000..4c4fa46
--- /dev/null
+++ b/bottleneck/tests/data/test_598_A
@@ -0,0 +1,50 @@
+62 152
+79 161
+64 158
+93 154
+51 99
+69 113
+21 62
+66 156
+48 137
+66 121
+78 165
+56 107
+87 141
+87 159
+42 50
+61 72
+31 61
+26 125
+33 118
+32 88
+98 110
+75 103
+67 130
+94 192
+97 153
+3 4
+48 136
+56 57
+43 53
+29 113
+82 110
+90 103
+54 93
+53 106
+75 143
+32 44
+85 147
+50 72
+22 71
+49 96
+49 132
+32 113
+24 58
+58 142
+60 106
+100 163
+45 123
+27 31
+41 76
+14 40
diff --git a/bottleneck/tests/data/test_598_B b/bottleneck/tests/data/test_598_B
new file mode 100644
index 0000000..974d069
--- /dev/null
+++ b/bottleneck/tests/data/test_598_B
@@ -0,0 +1,50 @@
+8 45
+47 75
+81 128
+60 100
+13 40
+47 96
+97 169
+28 93
+36 92
+80 175
+41 121
+24 55
+94 100
+69 82
+53 97
+64 119
+53 151
+30 51
+11 82
+77 118
+66 113
+54 92
+23 100
+79 82
+44 122
+93 185
+75 169
+98 99
+69 163
+28 100
+66 70
+69 98
+80 99
+23 79
+100 134
+67 126
+57 138
+79 116
+25 44
+48 142
+26 123
+14 51
+93 151
+68 71
+6 27
+4 64
+63 128
+88 166
+59 70
+19 80
diff --git a/bottleneck/tests/data/test_599_A b/bottleneck/tests/data/test_599_A
new file mode 100644
index 0000000..984a0ed
--- /dev/null
+++ b/bottleneck/tests/data/test_599_A
@@ -0,0 +1,50 @@
+6 64
+55 70
+74 171
+88 144
+91 170
+61 75
+1 42
+69 72
+99 112
+100 113
+97 165
+78 83
+12 90
+19 103
+91 134
+78 121
+31 75
+57 139
+2 15
+84 129
+73 139
+24 71
+56 135
+17 117
+26 66
+46 110
+21 97
+24 111
+100 177
+59 132
+13 14
+12 73
+4 51
+49 89
+27 82
+23 107
+84 112
+8 52
+96 172
+97 133
+40 80
+21 32
+65 149
+61 125
+92 133
+89 119
+28 37
+46 106
+95 190
+78 91
diff --git a/bottleneck/tests/data/test_599_B b/bottleneck/tests/data/test_599_B
new file mode 100644
index 0000000..aaea2a7
--- /dev/null
+++ b/bottleneck/tests/data/test_599_B
@@ -0,0 +1,50 @@
+83 144
+54 114
+6 83
+53 109
+60 159
+33 90
+72 83
+3 5
+72 170
+60 116
+75 172
+19 107
+11 36
+36 109
+25 59
+22 100
+30 127
+57 119
+28 87
+81 144
+10 53
+2 27
+71 117
+60 84
+95 99
+77 81
+56 67
+67 85
+32 42
+28 45
+81 148
+6 33
+60 146
+83 86
+30 48
+89 105
+26 53
+65 89
+41 94
+47 84
+88 130
+51 95
+65 74
+98 107
+99 180
+80 107
+89 94
+25 36
+83 106
+24 112
diff --git a/bottleneck/tests/data/test_600_A b/bottleneck/tests/data/test_600_A
new file mode 100644
index 0000000..13c5659
--- /dev/null
+++ b/bottleneck/tests/data/test_600_A
@@ -0,0 +1,100 @@
+77 125
+40 107
+52 73
+65 77
+96 158
+26 106
+61 138
+1 10
+56 151
+91 161
+1 20
+100 172
+69 152
+26 57
+33 96
+21 98
+2 24
+54 115
+35 116
+17 31
+21 50
+36 93
+61 74
+98 122
+96 151
+90 168
+49 69
+23 24
+2 67
+28 123
+95 181
+60 81
+33 96
+25 103
+44 114
+84 128
+1 45
+90 154
+34 83
+57 149
+49 109
+57 121
+47 74
+57 77
+37 132
+44 48
+61 98
+37 60
+66 84
+71 73
+30 121
+50 150
+44 99
+86 179
+99 137
+53 125
+85 136
+56 126
+99 163
+43 132
+1 66
+90 132
+27 40
+2 10
+65 115
+39 68
+17 89
+90 153
+22 102
+28 78
+56 101
+89 184
+88 125
+83 85
+75 144
+26 89
+56 108
+83 173
+90 106
+7 72
+97 173
+94 131
+31 104
+95 148
+100 102
+37 82
+86 128
+29 56
+54 109
+81 157
+82 126
+62 71
+33 116
+86 126
+20 103
+34 131
+93 107
+26 104
+31 91
+23 115
diff --git a/bottleneck/tests/data/test_600_B b/bottleneck/tests/data/test_600_B
new file mode 100644
index 0000000..5de1dfa
--- /dev/null
+++ b/bottleneck/tests/data/test_600_B
@@ -0,0 +1,100 @@
+99 168
+39 113
+73 109
+91 101
+67 144
+17 57
+3 59
+81 155
+100 159
+48 110
+98 128
+73 167
+55 135
+42 140
+84 129
+18 97
+92 103
+33 86
+68 84
+83 111
+72 111
+97 179
+8 58
+6 80
+21 99
+81 124
+37 85
+19 48
+11 14
+53 122
+16 74
+75 113
+47 74
+87 166
+45 69
+51 68
+74 122
+10 47
+50 90
+66 114
+24 115
+40 65
+74 136
+72 146
+24 114
+48 91
+56 68
+78 102
+30 64
+75 159
+16 101
+58 150
+69 126
+80 136
+6 96
+53 121
+15 115
+76 81
+36 59
+63 68
+85 142
+7 50
+20 83
+9 40
+98 163
+70 165
+88 177
+85 149
+0 17
+30 124
+40 113
+35 91
+66 117
+94 108
+11 106
+78 88
+42 107
+60 121
+55 119
+78 110
+0 76
+63 130
+10 105
+23 68
+13 81
+60 142
+3 81
+53 90
+26 99
+95 165
+52 126
+41 70
+6 29
+14 103
+88 170
+79 102
+9 98
+27 124
+12 60
+59 145
diff --git a/bottleneck/tests/data/test_601_A b/bottleneck/tests/data/test_601_A
new file mode 100644
index 0000000..9f57dd0
--- /dev/null
+++ b/bottleneck/tests/data/test_601_A
@@ -0,0 +1,100 @@
+49 135
+27 47
+45 83
+13 49
+15 80
+78 84
+54 128
+20 24
+75 121
+52 90
+15 64
+19 101
+35 80
+35 69
+49 122
+21 49
+51 75
+41 95
+91 162
+26 101
+54 104
+65 164
+74 100
+6 51
+58 68
+99 148
+55 87
+35 51
+51 77
+22 117
+78 141
+80 135
+66 145
+80 145
+68 112
+35 97
+63 91
+10 62
+1 73
+40 106
+76 77
+8 93
+94 136
+57 157
+16 43
+46 92
+49 77
+44 49
+51 120
+68 133
+41 73
+72 109
+42 59
+11 13
+19 86
+24 49
+11 105
+93 113
+81 160
+5 99
+78 159
+37 97
+68 120
+54 111
+41 49
+33 123
+27 35
+71 101
+55 70
+99 183
+68 121
+62 92
+47 53
+4 6
+56 110
+96 113
+85 122
+85 92
+31 97
+1 62
+25 67
+30 39
+16 23
+97 148
+21 22
+21 46
+85 134
+19 23
+12 56
+16 40
+59 138
+9 63
+31 46
+88 161
+72 74
+28 45
+57 95
+90 164
+89 106
+49 134
diff --git a/bottleneck/tests/data/test_601_B b/bottleneck/tests/data/test_601_B
new file mode 100644
index 0000000..64d7ef8
--- /dev/null
+++ b/bottleneck/tests/data/test_601_B
@@ -0,0 +1,100 @@
+45 101
+84 90
+70 98
+64 109
+100 111
+82 87
+26 54
+18 90
+84 133
+92 145
+68 139
+90 154
+85 104
+34 76
+30 79
+21 99
+2 85
+20 75
+12 57
+62 102
+69 148
+18 116
+28 97
+52 88
+40 68
+21 26
+66 73
+8 68
+31 130
+83 174
+89 156
+38 43
+62 153
+4 34
+85 123
+51 99
+39 119
+99 149
+19 81
+51 79
+51 136
+25 52
+63 80
+91 166
+62 126
+86 102
+16 39
+0 66
+26 107
+55 89
+72 100
+73 106
+82 129
+77 112
+44 81
+94 118
+57 136
+1 13
+43 52
+24 112
+39 129
+28 97
+41 105
+59 150
+21 84
+38 92
+39 91
+25 36
+52 125
+56 119
+99 171
+51 142
+6 34
+44 77
+100 170
+23 43
+76 138
+67 77
+26 116
+18 49
+25 92
+42 138
+22 41
+48 112
+81 89
+51 67
+64 90
+51 94
+75 147
+49 96
+47 102
+31 114
+7 92
+48 81
+40 41
+84 117
+34 118
+9 27
+86 145
+56 69
diff --git a/bottleneck/tests/data/test_602_A b/bottleneck/tests/data/test_602_A
new file mode 100644
index 0000000..df83de7
--- /dev/null
+++ b/bottleneck/tests/data/test_602_A
@@ -0,0 +1,100 @@
+8 77
+68 127
+23 104
+15 96
+58 68
+5 77
+70 105
+13 49
+60 133
+31 122
+74 75
+80 132
+72 107
+44 52
+31 124
+32 36
+62 146
+51 98
+31 118
+45 107
+53 85
+76 152
+67 161
+51 92
+10 23
+89 183
+73 117
+47 112
+42 97
+68 101
+82 86
+32 61
+39 134
+9 109
+31 83
+95 137
+82 155
+34 39
+5 6
+24 108
+94 150
+22 68
+95 172
+12 92
+59 107
+31 59
+0 40
+53 64
+32 73
+69 134
+21 63
+13 107
+10 82
+3 94
+85 147
+51 127
+91 169
+17 87
+80 137
+90 178
+89 185
+56 103
+13 18
+83 84
+34 77
+50 148
+1 10
+80 141
+92 191
+9 21
+85 172
+11 50
+98 134
+12 99
+81 137
+66 90
+32 109
+22 73
+39 130
+38 52
+24 68
+71 113
+84 90
+79 102
+92 192
+47 105
+70 132
+4 45
+57 123
+60 125
+48 56
+19 110
+40 130
+36 114
+55 92
+1 66
+77 131
+96 172
+34 85
+79 102
diff --git a/bottleneck/tests/data/test_602_B b/bottleneck/tests/data/test_602_B
new file mode 100644
index 0000000..fb19e1c
--- /dev/null
+++ b/bottleneck/tests/data/test_602_B
@@ -0,0 +1,100 @@
+4 97
+46 76
+86 104
+38 75
+73 124
+7 52
+42 105
+72 132
+14 114
+38 136
+77 91
+72 92
+36 64
+53 121
+57 62
+20 49
+55 78
+82 151
+9 95
+6 20
+10 51
+50 110
+38 100
+69 150
+80 102
+78 93
+94 157
+7 55
+39 121
+80 136
+24 49
+33 95
+99 150
+55 119
+97 188
+73 82
+26 42
+84 92
+5 103
+88 167
+7 54
+35 74
+68 141
+31 56
+98 182
+38 116
+0 63
+29 39
+19 62
+41 91
+50 81
+37 106
+22 65
+19 113
+55 125
+59 79
+29 75
+6 48
+12 101
+37 102
+48 126
+34 71
+63 90
+87 139
+97 147
+86 143
+22 69
+7 17
+9 93
+82 109
+12 55
+88 126
+97 102
+6 70
+6 21
+39 105
+4 103
+46 139
+38 111
+44 45
+17 31
+79 150
+83 96
+97 101
+66 152
+15 84
+82 99
+2 102
+62 123
+8 101
+32 92
+76 158
+20 26
+20 106
+17 75
+70 89
+13 22
+57 87
+6 27
+16 25
diff --git a/bottleneck/tests/data/test_603_A b/bottleneck/tests/data/test_603_A
new file mode 100644
index 0000000..a81f6cb
--- /dev/null
+++ b/bottleneck/tests/data/test_603_A
@@ -0,0 +1,100 @@
+59 86
+86 166
+73 114
+3 10
+36 59
+0 33
+24 25
+51 70
+83 129
+7 60
+47 58
+20 97
+30 96
+61 161
+83 143
+83 127
+100 188
+6 28
+18 44
+53 54
+58 94
+53 97
+36 86
+83 133
+37 83
+79 125
+19 104
+67 156
+6 99
+44 128
+37 64
+35 92
+36 126
+55 155
+16 48
+37 108
+72 119
+96 111
+10 83
+96 143
+31 65
+41 138
+94 148
+41 74
+6 92
+53 133
+98 113
+2 71
+15 52
+28 54
+46 58
+81 109
+24 85
+60 159
+61 68
+46 96
+45 138
+99 117
+82 145
+69 121
+15 53
+74 174
+51 114
+100 145
+26 82
+32 115
+72 169
+48 144
+75 172
+65 114
+49 74
+45 119
+31 122
+59 146
+62 67
+43 46
+6 69
+23 25
+76 176
+68 164
+36 113
+26 106
+46 134
+71 151
+59 121
+10 99
+71 167
+82 162
+62 79
+97 127
+68 115
+46 90
+83 156
+12 39
+61 87
+90 187
+0 84
+44 85
+41 93
+98 187
diff --git a/bottleneck/tests/data/test_603_B b/bottleneck/tests/data/test_603_B
new file mode 100644
index 0000000..0ea6eda
--- /dev/null
+++ b/bottleneck/tests/data/test_603_B
@@ -0,0 +1,100 @@
+67 101
+34 55
+8 100
+52 112
+78 120
+15 71
+17 58
+83 109
+41 137
+41 107
+26 125
+87 111
+82 141
+77 78
+24 50
+49 78
+79 88
+91 110
+75 78
+84 91
+100 199
+34 70
+66 154
+23 34
+46 73
+43 94
+23 65
+89 175
+44 46
+13 24
+8 95
+94 162
+13 27
+74 102
+80 156
+77 124
+44 100
+13 52
+32 43
+23 38
+87 162
+24 52
+67 103
+97 146
+79 94
+21 100
+97 186
+38 39
+67 123
+99 197
+29 46
+52 139
+1 80
+5 34
+67 86
+49 122
+45 50
+64 80
+73 154
+85 164
+23 42
+93 123
+54 123
+63 64
+84 162
+86 103
+47 117
+32 112
+60 152
+96 111
+79 97
+86 130
+0 98
+65 161
+55 83
+73 139
+82 133
+9 108
+24 123
+92 132
+87 91
+23 40
+55 116
+91 176
+49 100
+25 58
+4 65
+28 39
+3 74
+22 37
+34 128
+98 154
+32 122
+9 84
+53 79
+47 61
+76 82
+11 34
+65 128
+28 82
diff --git a/bottleneck/tests/data/test_604_A b/bottleneck/tests/data/test_604_A
new file mode 100644
index 0000000..11a7c84
--- /dev/null
+++ b/bottleneck/tests/data/test_604_A
@@ -0,0 +1,100 @@
+90 168
+97 169
+3 20
+65 71
+61 105
+6 56
+50 122
+9 12
+15 51
+73 121
+54 118
+27 121
+97 135
+38 100
+35 69
+40 57
+64 159
+37 125
+79 116
+11 54
+66 72
+76 162
+69 154
+35 77
+91 177
+77 111
+67 145
+59 100
+94 130
+75 135
+53 106
+43 106
+100 130
+81 159
+14 107
+52 91
+47 136
+83 133
+16 63
+11 98
+4 6
+98 120
+98 117
+69 90
+24 108
+74 138
+100 105
+9 16
+55 81
+86 154
+6 99
+82 85
+86 176
+57 79
+83 136
+70 135
+30 85
+73 126
+73 164
+20 89
+42 93
+97 150
+6 69
+26 66
+43 129
+84 117
+75 132
+68 98
+29 111
+57 140
+15 107
+75 141
+97 180
+47 130
+31 72
+56 150
+30 75
+86 106
+49 50
+16 38
+40 68
+99 176
+10 56
+89 128
+97 124
+35 134
+82 137
+34 97
+34 40
+34 43
+71 149
+33 113
+6 80
+69 160
+54 148
+88 131
+98 141
+91 112
+25 106
+68 149
diff --git a/bottleneck/tests/data/test_604_B b/bottleneck/tests/data/test_604_B
new file mode 100644
index 0000000..6e14339
--- /dev/null
+++ b/bottleneck/tests/data/test_604_B
@@ -0,0 +1,100 @@
+4 69
+24 43
+68 72
+33 77
+96 106
+48 134
+18 38
+1 28
+12 112
+70 76
+6 16
+19 65
+35 49
+91 95
+50 147
+94 174
+87 124
+27 29
+17 116
+50 120
+83 183
+60 129
+92 120
+67 125
+60 73
+17 60
+10 12
+65 158
+19 100
+44 92
+86 139
+98 184
+67 100
+28 115
+16 94
+36 94
+40 99
+20 115
+94 149
+80 135
+47 109
+39 53
+62 159
+25 78
+30 118
+71 89
+86 166
+85 159
+58 120
+45 64
+73 156
+66 107
+31 88
+53 88
+67 167
+49 144
+60 71
+69 151
+44 111
+43 93
+95 102
+78 150
+98 120
+22 92
+70 76
+1 98
+25 44
+93 166
+16 100
+94 134
+37 99
+4 70
+32 47
+61 136
+30 95
+99 133
+91 163
+32 112
+78 91
+55 62
+16 33
+13 48
+45 75
+96 155
+20 82
+39 57
+22 51
+7 31
+73 90
+49 55
+32 65
+16 22
+33 71
+80 97
+85 154
+100 172
+86 114
+98 191
+2 7
+35 113
diff --git a/bottleneck/tests/data/test_605_A b/bottleneck/tests/data/test_605_A
new file mode 100644
index 0000000..522dbf9
--- /dev/null
+++ b/bottleneck/tests/data/test_605_A
@@ -0,0 +1,100 @@
+59 77
+22 53
+70 99
+32 126
+63 100
+72 89
+93 150
+70 83
+35 53
+96 128
+55 151
+30 96
+6 85
+80 131
+76 80
+36 79
+50 72
+70 134
+20 77
+27 33
+35 37
+44 55
+91 165
+68 132
+52 141
+81 142
+43 106
+46 55
+55 100
+21 86
+100 130
+97 173
+56 142
+26 36
+54 68
+17 23
+57 124
+65 122
+11 30
+70 96
+46 47
+52 114
+65 104
+24 39
+2 102
+91 181
+66 107
+27 120
+24 38
+33 94
+87 166
+35 78
+38 92
+56 125
+15 50
+95 129
+85 174
+53 126
+76 171
+71 154
+67 86
+61 133
+99 183
+92 102
+83 103
+80 174
+63 109
+37 60
+12 78
+30 56
+19 117
+33 99
+3 94
+18 52
+44 133
+53 55
+37 95
+43 92
+64 127
+12 79
+65 129
+48 92
+92 136
+25 64
+83 91
+22 91
+66 96
+33 37
+8 45
+4 5
+21 107
+72 171
+6 14
+75 124
+79 140
+52 114
+61 62
+89 151
+98 102
+4 46
diff --git a/bottleneck/tests/data/test_605_B b/bottleneck/tests/data/test_605_B
new file mode 100644
index 0000000..34f19db
--- /dev/null
+++ b/bottleneck/tests/data/test_605_B
@@ -0,0 +1,100 @@
+17 96
+1 57
+57 149
+10 24
+76 155
+3 81
+66 101
+79 85
+17 91
+78 105
+78 155
+91 167
+63 84
+41 45
+12 50
+49 107
+13 31
+93 175
+93 105
+33 46
+70 121
+36 57
+43 103
+44 99
+54 91
+25 65
+26 27
+64 119
+94 161
+29 115
+0 14
+81 152
+15 83
+4 50
+56 132
+27 50
+42 61
+28 39
+2 38
+55 87
+52 91
+70 160
+57 94
+32 41
+52 142
+28 37
+81 92
+89 91
+79 127
+94 179
+45 128
+92 120
+61 124
+61 143
+12 31
+2 36
+42 48
+25 55
+89 184
+56 57
+90 154
+55 94
+70 104
+35 135
+10 39
+45 63
+72 102
+0 12
+45 71
+84 126
+89 146
+52 100
+14 93
+16 42
+89 186
+50 77
+64 75
+29 52
+14 81
+55 73
+69 105
+47 144
+70 102
+59 76
+81 94
+63 163
+19 55
+70 146
+58 118
+56 96
+74 93
+24 30
+100 190
+80 115
+88 172
+0 31
+83 124
+53 153
+68 70
+73 108
diff --git a/bottleneck/tests/data/test_606_A b/bottleneck/tests/data/test_606_A
new file mode 100644
index 0000000..2f4dec4
--- /dev/null
+++ b/bottleneck/tests/data/test_606_A
@@ -0,0 +1,100 @@
+49 104
+89 185
+56 72
+44 117
+27 73
+64 87
+30 44
+89 150
+73 105
+80 156
+48 145
+36 87
+62 122
+85 97
+51 144
+48 137
+61 132
+47 66
+78 134
+17 101
+66 119
+74 82
+96 99
+56 57
+66 109
+13 103
+6 40
+55 78
+77 130
+92 133
+65 74
+8 9
+29 123
+6 61
+41 138
+21 98
+85 107
+99 108
+79 95
+93 161
+9 20
+58 150
+33 93
+2 48
+38 40
+83 153
+33 92
+94 155
+44 96
+17 102
+68 99
+32 69
+73 126
+5 43
+86 181
+2 38
+65 163
+86 164
+49 132
+41 86
+96 186
+87 145
+12 81
+11 73
+77 87
+22 116
+14 21
+56 82
+61 120
+2 24
+67 71
+33 93
+89 132
+14 102
+12 29
+7 38
+12 88
+76 123
+46 75
+79 99
+49 74
+27 35
+8 47
+33 84
+79 171
+72 83
+79 106
+96 152
+86 164
+100 128
+7 97
+70 128
+89 156
+15 17
+86 126
+65 110
+53 80
+51 81
+36 85
+50 82
diff --git a/bottleneck/tests/data/test_606_B b/bottleneck/tests/data/test_606_B
new file mode 100644
index 0000000..62417b1
--- /dev/null
+++ b/bottleneck/tests/data/test_606_B
@@ -0,0 +1,100 @@
+35 135
+1 41
+63 72
+43 98
+37 71
+24 87
+14 105
+66 67
+12 79
+60 145
+20 72
+0 70
+67 149
+22 30
+86 151
+20 106
+38 74
+58 133
+40 103
+34 111
+81 126
+55 74
+49 133
+44 128
+54 86
+15 82
+84 89
+87 121
+95 135
+53 104
+91 157
+7 101
+45 124
+87 162
+73 164
+60 123
+77 81
+69 78
+44 118
+0 79
+66 106
+67 85
+85 168
+93 122
+0 42
+10 66
+9 23
+29 80
+46 76
+75 126
+2 32
+99 143
+24 90
+31 120
+73 98
+42 57
+67 86
+44 99
+65 135
+100 167
+33 43
+10 29
+36 63
+79 178
+82 85
+35 49
+24 57
+66 142
+2 29
+73 149
+16 76
+27 53
+86 88
+36 75
+54 56
+11 82
+87 183
+33 72
+84 94
+96 108
+13 63
+34 98
+76 173
+57 114
+63 149
+74 131
+20 21
+48 100
+92 98
+3 41
+66 138
+90 130
+62 152
+26 101
+28 102
+41 139
+85 167
+68 84
+64 74
+64 136
diff --git a/bottleneck/tests/data/test_607_A b/bottleneck/tests/data/test_607_A
new file mode 100644
index 0000000..abc3b6b
--- /dev/null
+++ b/bottleneck/tests/data/test_607_A
@@ -0,0 +1,100 @@
+82 154
+80 107
+94 156
+55 58
+84 183
+82 128
+35 97
+32 105
+12 104
+17 57
+54 67
+59 103
+22 106
+50 122
+31 93
+33 123
+9 105
+78 140
+15 101
+67 117
+34 119
+96 123
+71 169
+91 93
+99 119
+85 169
+59 69
+85 169
+32 76
+62 134
+21 77
+79 141
+5 63
+9 72
+21 41
+2 95
+16 92
+22 54
+44 58
+1 24
+26 54
+33 93
+85 135
+74 110
+63 81
+64 113
+3 21
+24 92
+78 82
+54 63
+66 83
+22 38
+41 59
+99 156
+26 34
+67 78
+9 22
+15 62
+25 43
+0 93
+43 44
+54 63
+16 40
+62 136
+35 85
+80 179
+4 103
+21 73
+91 119
+99 188
+16 42
+63 64
+76 137
+58 61
+20 39
+61 72
+0 9
+7 41
+11 61
+39 124
+70 153
+97 121
+66 166
+7 72
+65 140
+96 140
+60 87
+34 35
+14 15
+17 41
+33 69
+5 101
+49 109
+79 102
+22 57
+50 126
+24 119
+76 166
+84 93
+34 70
diff --git a/bottleneck/tests/data/test_607_B b/bottleneck/tests/data/test_607_B
new file mode 100644
index 0000000..0f79931
--- /dev/null
+++ b/bottleneck/tests/data/test_607_B
@@ -0,0 +1,100 @@
+23 33
+0 85
+33 82
+21 38
+41 75
+94 128
+35 107
+9 76
+65 74
+71 133
+83 173
+94 109
+58 83
+61 68
+44 111
+67 107
+97 152
+100 167
+94 105
+94 95
+9 37
+18 47
+87 141
+81 153
+57 90
+10 19
+67 137
+11 75
+86 139
+39 72
+13 51
+65 155
+56 98
+91 149
+58 68
+6 89
+39 95
+82 150
+97 129
+26 73
+87 112
+37 117
+73 137
+68 73
+4 88
+2 70
+79 112
+59 123
+31 93
+36 77
+95 158
+25 52
+33 47
+69 112
+73 160
+95 138
+15 56
+31 96
+1 2
+9 41
+59 129
+48 55
+52 111
+51 139
+38 115
+100 198
+30 46
+77 105
+43 115
+66 151
+69 70
+93 98
+19 59
+10 59
+10 59
+51 89
+21 58
+48 75
+57 58
+0 34
+48 110
+87 152
+9 44
+19 73
+8 76
+82 165
+4 51
+9 24
+62 105
+97 147
+28 102
+37 77
+25 55
+77 86
+80 87
+81 172
+99 152
+57 107
+61 154
+45 93
diff --git a/bottleneck/tests/data/test_608_A b/bottleneck/tests/data/test_608_A
new file mode 100644
index 0000000..a4beccc
--- /dev/null
+++ b/bottleneck/tests/data/test_608_A
@@ -0,0 +1,100 @@
+91 111
+71 96
+84 176
+57 123
+7 22
+4 76
+83 171
+79 172
+96 173
+75 76
+19 98
+91 135
+13 54
+10 13
+2 53
+65 128
+96 133
+54 64
+43 112
+72 139
+32 33
+45 89
+82 174
+36 79
+5 89
+90 114
+41 90
+16 30
+78 177
+64 77
+40 67
+57 129
+29 51
+53 54
+86 90
+64 116
+87 92
+73 76
+35 108
+25 81
+57 155
+55 123
+56 99
+96 103
+88 93
+28 101
+74 106
+76 166
+28 126
+34 41
+75 91
+19 119
+59 108
+29 121
+0 66
+9 25
+68 150
+26 51
+19 47
+34 55
+37 127
+66 80
+23 52
+8 19
+65 128
+44 109
+16 70
+17 114
+29 31
+40 100
+20 42
+61 121
+89 153
+35 104
+5 81
+33 95
+17 29
+93 132
+72 133
+100 102
+54 109
+23 53
+85 87
+64 69
+20 67
+30 34
+96 143
+40 134
+60 86
+40 91
+92 133
+73 141
+70 117
+43 78
+52 83
+27 114
+2 88
+48 121
+40 66
+96 159
diff --git a/bottleneck/tests/data/test_608_B b/bottleneck/tests/data/test_608_B
new file mode 100644
index 0000000..94f4c9a
--- /dev/null
+++ b/bottleneck/tests/data/test_608_B
@@ -0,0 +1,100 @@
+69 152
+69 122
+74 138
+60 95
+88 127
+98 124
+99 193
+82 85
+17 78
+57 130
+50 71
+62 94
+7 39
+89 137
+26 69
+71 146
+9 73
+37 55
+25 111
+65 145
+94 157
+92 99
+31 51
+50 112
+87 99
+64 76
+55 126
+6 56
+48 124
+89 147
+16 18
+93 172
+53 152
+90 102
+25 123
+81 110
+1 93
+74 150
+61 73
+39 100
+74 148
+58 152
+21 94
+39 112
+96 161
+4 85
+61 79
+90 150
+2 42
+100 110
+81 161
+56 71
+90 162
+2 30
+69 80
+33 99
+27 43
+56 74
+57 138
+63 162
+51 121
+80 153
+75 174
+4 29
+91 122
+45 145
+72 74
+66 130
+13 79
+9 91
+59 100
+35 114
+100 124
+40 80
+40 134
+72 123
+43 63
+43 81
+37 83
+74 128
+5 86
+54 66
+88 133
+6 93
+98 166
+8 104
+100 199
+56 130
+88 128
+41 97
+8 17
+44 123
+7 51
+33 59
+0 80
+16 69
+16 55
+77 141
+75 108
+84 117
diff --git a/bottleneck/tests/data/test_609_A b/bottleneck/tests/data/test_609_A
new file mode 100644
index 0000000..a8e841e
--- /dev/null
+++ b/bottleneck/tests/data/test_609_A
@@ -0,0 +1,100 @@
+52 69
+8 75
+78 173
+64 147
+34 126
+24 107
+83 158
+79 135
+39 119
+72 163
+12 78
+45 107
+7 27
+8 48
+65 133
+43 99
+92 116
+46 61
+78 94
+73 122
+30 89
+27 50
+46 142
+58 92
+7 73
+52 123
+53 77
+28 115
+28 111
+65 159
+95 131
+58 82
+47 103
+31 110
+15 37
+90 139
+76 128
+88 131
+76 145
+96 165
+77 154
+11 36
+36 63
+25 122
+100 144
+13 15
+7 65
+50 128
+97 104
+98 183
+39 81
+55 89
+76 78
+46 87
+2 43
+86 151
+61 130
+40 122
+72 111
+14 113
+26 89
+43 61
+80 176
+83 170
+78 153
+93 171
+87 142
+98 101
+60 71
+24 93
+18 94
+86 103
+22 42
+14 104
+2 85
+26 78
+98 190
+91 191
+9 68
+46 124
+50 105
+0 38
+62 138
+26 27
+78 168
+80 87
+64 68
+64 129
+10 48
+77 171
+79 129
+53 89
+30 92
+71 125
+26 125
+12 112
+96 134
+27 114
+62 91
+10 11
diff --git a/bottleneck/tests/data/test_609_B b/bottleneck/tests/data/test_609_B
new file mode 100644
index 0000000..574351a
--- /dev/null
+++ b/bottleneck/tests/data/test_609_B
@@ -0,0 +1,100 @@
+64 90
+2 6
+69 77
+35 119
+59 88
+27 127
+39 134
+68 155
+92 151
+5 84
+79 125
+37 66
+31 116
+48 97
+63 88
+92 176
+36 98
+97 135
+67 130
+21 44
+42 114
+42 114
+56 93
+4 78
+91 128
+87 94
+35 69
+5 25
+46 72
+91 151
+96 180
+87 165
+24 32
+72 134
+78 150
+0 3
+100 197
+84 95
+6 31
+61 97
+25 26
+46 114
+91 152
+64 82
+75 78
+73 134
+43 58
+66 157
+82 130
+66 96
+49 61
+55 82
+25 39
+58 153
+93 184
+17 113
+51 123
+51 77
+61 106
+26 111
+94 187
+28 77
+5 95
+100 123
+0 74
+55 91
+60 76
+2 43
+58 110
+82 153
+22 100
+13 92
+7 22
+82 153
+71 84
+16 26
+3 45
+80 97
+51 143
+99 191
+38 67
+14 112
+4 11
+72 141
+4 34
+86 115
+74 134
+53 102
+87 116
+51 119
+5 105
+62 103
+32 116
+64 152
+41 52
+1 38
+3 57
+50 133
+57 132
+57 93
diff --git a/bottleneck/tests/data/test_610_A b/bottleneck/tests/data/test_610_A
new file mode 100644
index 0000000..c37fa9c
--- /dev/null
+++ b/bottleneck/tests/data/test_610_A
@@ -0,0 +1,100 @@
+4 71
+61 90
+58 59
+14 102
+53 142
+94 103
+47 71
+72 115
+33 113
+64 142
+82 115
+65 85
+34 101
+78 93
+68 109
+84 112
+45 80
+30 83
+100 164
+88 158
+2 10
+56 135
+22 41
+11 21
+77 128
+34 110
+8 54
+91 184
+57 120
+100 187
+76 115
+52 83
+48 54
+78 173
+10 84
+85 185
+44 129
+100 132
+52 58
+23 84
+65 70
+54 73
+92 167
+91 103
+73 112
+11 85
+38 78
+78 105
+7 22
+3 85
+57 125
+45 77
+15 99
+87 104
+2 70
+11 111
+40 75
+33 47
+99 186
+24 87
+20 78
+14 92
+71 135
+23 30
+58 95
+51 112
+8 21
+75 138
+78 102
+0 48
+86 106
+18 28
+4 103
+75 81
+96 126
+16 88
+83 120
+87 182
+35 48
+31 58
+46 71
+52 73
+71 89
+20 92
+33 107
+10 62
+29 37
+6 22
+0 81
+33 35
+0 81
+20 82
+18 39
+19 84
+88 166
+49 95
+64 74
+58 139
+20 21
+49 105
diff --git a/bottleneck/tests/data/test_610_B b/bottleneck/tests/data/test_610_B
new file mode 100644
index 0000000..0745255
--- /dev/null
+++ b/bottleneck/tests/data/test_610_B
@@ -0,0 +1,100 @@
+44 136
+49 63
+56 122
+67 109
+38 136
+87 96
+23 34
+53 130
+94 108
+67 81
+58 88
+74 158
+20 86
+34 42
+76 128
+33 61
+92 156
+97 107
+39 111
+93 165
+56 144
+36 121
+2 34
+90 136
+91 185
+76 125
+13 26
+59 108
+39 131
+65 138
+49 145
+86 179
+56 138
+62 128
+37 106
+11 22
+27 39
+39 116
+83 127
+20 51
+10 20
+14 79
+96 107
+44 122
+85 122
+85 112
+75 95
+55 100
+56 111
+46 127
+72 157
+49 71
+32 126
+90 144
+94 95
+34 81
+21 64
+37 84
+40 103
+53 76
+88 102
+63 73
+28 31
+42 43
+29 50
+17 61
+59 156
+97 164
+22 50
+45 128
+65 159
+56 123
+10 82
+76 132
+9 86
+97 180
+34 62
+63 70
+68 127
+52 104
+75 168
+54 66
+67 154
+94 113
+34 76
+12 106
+34 69
+31 130
+70 105
+27 52
+47 71
+36 128
+68 156
+47 134
+12 79
+42 139
+85 138
+37 91
+43 68
+23 81
diff --git a/bottleneck/tests/data/test_611_A b/bottleneck/tests/data/test_611_A
new file mode 100644
index 0000000..f7cfbbe
--- /dev/null
+++ b/bottleneck/tests/data/test_611_A
@@ -0,0 +1,100 @@
+79 154
+81 116
+71 125
+5 48
+85 176
+76 115
+3 87
+85 102
+17 116
+49 80
+95 183
+82 92
+23 60
+66 97
+4 37
+81 90
+24 50
+64 136
+54 86
+87 160
+33 102
+40 80
+82 127
+97 118
+68 76
+99 160
+92 107
+14 80
+5 45
+42 83
+40 108
+77 163
+39 105
+91 176
+45 73
+96 169
+78 176
+12 90
+53 135
+87 124
+79 172
+52 65
+26 86
+65 112
+1 60
+57 131
+65 135
+45 57
+28 71
+40 50
+17 110
+95 112
+59 156
+38 86
+63 78
+60 112
+28 108
+18 72
+18 91
+33 94
+41 105
+2 37
+36 93
+49 103
+57 131
+10 108
+29 64
+73 83
+79 85
+30 115
+93 111
+47 90
+41 47
+90 158
+72 137
+55 65
+55 136
+40 52
+38 49
+33 57
+82 125
+53 139
+42 87
+43 55
+16 54
+45 61
+6 92
+21 37
+33 84
+37 137
+39 87
+19 70
+62 79
+9 15
+16 48
+39 131
+59 130
+80 94
+56 126
+76 95
diff --git a/bottleneck/tests/data/test_611_B b/bottleneck/tests/data/test_611_B
new file mode 100644
index 0000000..ffc3bf6
--- /dev/null
+++ b/bottleneck/tests/data/test_611_B
@@ -0,0 +1,100 @@
+15 50
+61 137
+52 63
+72 148
+89 101
+93 143
+56 127
+30 99
+72 120
+92 114
+53 106
+43 72
+80 116
+67 136
+33 98
+63 111
+39 55
+84 170
+55 106
+1 8
+96 157
+85 143
+30 95
+66 132
+45 51
+36 128
+69 141
+1 31
+20 97
+14 47
+66 163
+44 125
+45 75
+86 185
+13 78
+28 31
+6 14
+96 108
+62 99
+29 120
+11 20
+55 107
+9 19
+32 105
+4 60
+92 160
+29 80
+68 113
+63 161
+78 95
+24 96
+98 128
+28 81
+87 175
+81 165
+70 137
+55 83
+38 43
+96 158
+40 100
+15 21
+66 70
+22 103
+37 106
+61 126
+52 151
+92 113
+36 61
+11 106
+81 141
+38 135
+48 142
+8 16
+88 89
+80 178
+100 160
+43 91
+71 122
+2 79
+21 27
+74 82
+3 6
+56 109
+94 175
+78 153
+32 117
+78 135
+14 53
+68 70
+53 115
+59 143
+41 63
+18 111
+28 109
+30 65
+42 132
+91 135
+5 43
+47 144
+53 103
diff --git a/bottleneck/tests/data/test_612_A b/bottleneck/tests/data/test_612_A
new file mode 100644
index 0000000..1d08d30
--- /dev/null
+++ b/bottleneck/tests/data/test_612_A
@@ -0,0 +1,100 @@
+29 103
+5 54
+70 158
+33 82
+96 190
+84 184
+49 139
+37 47
+96 159
+75 126
+37 67
+5 28
+41 44
+64 107
+0 88
+32 35
+41 42
+11 14
+82 107
+36 111
+35 80
+69 142
+22 85
+95 191
+48 102
+78 135
+74 151
+71 73
+92 114
+95 152
+52 85
+52 95
+72 147
+33 133
+57 148
+90 155
+94 192
+97 108
+84 172
+3 46
+36 112
+72 129
+80 132
+17 41
+67 113
+27 77
+45 86
+56 135
+41 65
+13 53
+52 84
+54 101
+34 74
+25 99
+86 87
+36 136
+82 124
+5 95
+86 150
+76 90
+66 127
+54 110
+76 82
+82 101
+75 139
+2 28
+68 156
+38 60
+51 75
+96 161
+98 143
+38 66
+43 67
+72 112
+25 27
+96 195
+24 26
+46 85
+71 157
+12 47
+46 92
+72 109
+14 65
+68 144
+53 56
+61 105
+18 111
+51 95
+18 28
+39 121
+67 71
+42 58
+25 106
+88 169
+66 150
+47 114
+36 61
+12 101
+64 137
+8 31
diff --git a/bottleneck/tests/data/test_612_B b/bottleneck/tests/data/test_612_B
new file mode 100644
index 0000000..712c645
--- /dev/null
+++ b/bottleneck/tests/data/test_612_B
@@ -0,0 +1,100 @@
+51 131
+46 143
+100 147
+25 81
+73 151
+74 80
+50 143
+91 157
+46 56
+67 152
+67 75
+78 137
+33 90
+17 45
+82 165
+64 97
+85 168
+44 130
+93 140
+80 137
+68 76
+82 177
+21 60
+73 82
+28 41
+45 121
+6 100
+72 83
+27 74
+53 69
+7 8
+7 93
+30 57
+38 98
+38 44
+58 81
+70 168
+15 112
+25 66
+80 122
+24 38
+60 149
+29 116
+54 75
+53 142
+48 111
+0 21
+82 151
+74 118
+93 155
+14 69
+7 70
+30 125
+9 73
+21 54
+97 144
+14 26
+27 95
+25 74
+60 75
+44 95
+94 168
+82 108
+97 129
+7 49
+86 95
+92 97
+98 166
+31 82
+33 90
+24 47
+48 147
+66 117
+26 66
+29 114
+84 166
+62 127
+72 132
+20 37
+77 170
+21 89
+1 9
+74 83
+96 192
+40 117
+3 8
+38 72
+88 156
+66 109
+22 52
+14 39
+51 92
+65 123
+81 119
+28 43
+75 170
+94 159
+20 96
+63 109
+17 106
diff --git a/bottleneck/tests/data/test_613_A b/bottleneck/tests/data/test_613_A
new file mode 100644
index 0000000..909c462
--- /dev/null
+++ b/bottleneck/tests/data/test_613_A
@@ -0,0 +1,100 @@
+43 47
+47 132
+11 66
+37 81
+99 108
+46 54
+47 80
+96 121
+12 18
+56 128
+7 75
+27 104
+43 110
+100 127
+28 29
+75 174
+62 105
+0 13
+43 62
+5 43
+8 27
+54 56
+43 103
+41 105
+96 156
+42 48
+97 134
+25 67
+79 144
+25 29
+99 140
+98 128
+45 144
+37 46
+4 98
+92 121
+12 77
+14 97
+92 119
+72 167
+14 36
+92 101
+30 38
+94 100
+42 55
+8 97
+8 78
+78 135
+46 83
+78 126
+30 58
+80 175
+49 130
+67 85
+4 24
+100 188
+36 49
+88 179
+45 69
+80 89
+1 73
+30 88
+44 124
+29 81
+15 100
+35 70
+29 87
+73 152
+64 102
+47 136
+50 68
+75 127
+80 152
+34 44
+78 167
+98 162
+18 45
+19 60
+90 120
+68 106
+98 198
+61 130
+3 41
+90 100
+22 68
+19 57
+59 88
+19 77
+60 92
+38 61
+7 45
+23 87
+71 155
+23 57
+97 177
+58 128
+77 109
+13 112
+37 129
+54 61
diff --git a/bottleneck/tests/data/test_613_B b/bottleneck/tests/data/test_613_B
new file mode 100644
index 0000000..9569b49
--- /dev/null
+++ b/bottleneck/tests/data/test_613_B
@@ -0,0 +1,100 @@
+22 108
+62 83
+61 105
+95 188
+77 78
+7 45
+83 149
+1 65
+14 16
+30 89
+84 112
+29 123
+73 173
+5 35
+37 58
+11 56
+83 125
+71 165
+53 103
+88 176
+28 88
+71 141
+93 170
+95 187
+15 84
+57 70
+19 118
+14 51
+37 117
+69 131
+97 143
+20 117
+54 99
+54 146
+62 104
+76 155
+23 75
+77 155
+23 117
+30 42
+97 137
+44 107
+24 33
+99 188
+30 38
+60 129
+83 102
+95 120
+37 71
+72 106
+90 149
+16 73
+97 127
+81 98
+39 101
+64 149
+43 112
+90 182
+8 93
+36 50
+33 45
+63 78
+25 103
+78 125
+47 143
+83 141
+66 153
+51 125
+53 83
+94 125
+99 199
+67 109
+67 99
+29 55
+68 148
+91 159
+65 96
+25 84
+63 134
+40 136
+94 173
+67 154
+14 107
+73 153
+24 79
+85 116
+66 104
+98 166
+0 42
+100 148
+74 168
+31 86
+42 62
+83 182
+48 131
+18 94
+90 134
+84 150
+78 175
+27 121
diff --git a/bottleneck/tests/data/test_614_A b/bottleneck/tests/data/test_614_A
new file mode 100644
index 0000000..29c02c8
--- /dev/null
+++ b/bottleneck/tests/data/test_614_A
@@ -0,0 +1,100 @@
+24 124
+56 99
+57 147
+95 161
+39 104
+63 154
+82 105
+65 89
+82 122
+62 129
+88 181
+75 121
+32 33
+44 68
+12 28
+36 131
+63 64
+23 72
+92 159
+80 112
+2 92
+48 110
+50 98
+23 50
+20 72
+32 39
+32 86
+51 63
+47 114
+61 71
+32 78
+43 110
+69 157
+79 122
+35 48
+74 85
+15 62
+14 72
+29 62
+37 61
+56 75
+35 88
+70 84
+37 91
+45 139
+16 33
+76 145
+8 70
+87 128
+91 183
+29 47
+37 48
+13 102
+88 142
+10 75
+35 109
+84 178
+88 118
+85 93
+17 113
+30 49
+13 47
+83 129
+60 106
+92 154
+29 90
+93 135
+33 66
+60 117
+36 92
+1 22
+13 76
+5 102
+7 102
+76 154
+78 133
+72 135
+93 146
+37 47
+44 103
+68 102
+81 136
+51 58
+92 172
+43 119
+92 140
+62 116
+15 84
+58 82
+94 119
+74 131
+5 42
+37 56
+28 127
+82 85
+60 107
+18 98
+1 80
+95 129
+96 101
diff --git a/bottleneck/tests/data/test_614_B b/bottleneck/tests/data/test_614_B
new file mode 100644
index 0000000..f34b836
--- /dev/null
+++ b/bottleneck/tests/data/test_614_B
@@ -0,0 +1,100 @@
+28 55
+77 152
+40 97
+23 116
+61 120
+59 143
+27 48
+32 88
+92 117
+66 145
+83 132
+2 51
+57 82
+47 122
+7 40
+68 150
+86 156
+68 122
+74 94
+92 113
+14 46
+61 116
+42 133
+15 55
+9 24
+49 70
+41 108
+20 45
+93 177
+87 144
+81 161
+11 60
+64 92
+24 69
+50 79
+39 82
+28 116
+62 122
+38 48
+64 75
+51 62
+22 34
+10 96
+61 73
+72 146
+10 62
+61 86
+5 41
+43 106
+25 66
+30 55
+91 112
+30 76
+96 176
+84 148
+17 81
+51 127
+90 106
+100 177
+67 129
+23 84
+49 99
+100 124
+11 59
+54 106
+19 113
+76 96
+10 96
+15 114
+83 143
+29 57
+82 143
+32 64
+6 73
+94 142
+22 52
+93 100
+57 154
+100 110
+90 165
+69 110
+54 118
+38 47
+92 142
+45 65
+0 19
+100 196
+71 136
+16 78
+53 148
+76 83
+49 81
+86 148
+59 152
+13 69
+25 101
+57 102
+89 113
+15 17
+1 2
diff --git a/bottleneck/tests/data/test_615_A b/bottleneck/tests/data/test_615_A
new file mode 100644
index 0000000..d1b55eb
--- /dev/null
+++ b/bottleneck/tests/data/test_615_A
@@ -0,0 +1,100 @@
+98 121
+87 153
+92 109
+60 122
+16 78
+1 43
+29 68
+93 186
+35 121
+95 183
+47 59
+98 129
+57 129
+82 134
+10 104
+20 60
+74 125
+97 158
+96 142
+71 88
+94 192
+37 132
+50 114
+65 96
+43 128
+27 48
+96 180
+10 22
+39 129
+28 29
+36 136
+1 65
+0 80
+3 99
+31 44
+35 94
+73 82
+91 155
+67 166
+36 78
+92 183
+74 157
+46 123
+31 68
+62 72
+21 83
+7 70
+49 137
+23 79
+48 132
+78 171
+51 80
+41 54
+59 108
+82 156
+42 136
+92 163
+27 90
+82 128
+95 96
+20 74
+26 40
+36 86
+29 35
+84 168
+82 151
+80 123
+58 109
+37 74
+53 86
+55 124
+24 91
+52 113
+79 126
+3 82
+68 124
+91 142
+48 85
+36 131
+7 61
+69 150
+66 77
+64 142
+91 95
+11 25
+71 162
+51 58
+20 104
+61 152
+2 19
+26 27
+41 58
+46 102
+29 41
+13 36
+93 145
+7 35
+54 102
+98 158
+85 93
diff --git a/bottleneck/tests/data/test_615_B b/bottleneck/tests/data/test_615_B
new file mode 100644
index 0000000..ab204be
--- /dev/null
+++ b/bottleneck/tests/data/test_615_B
@@ -0,0 +1,100 @@
+11 38
+73 143
+46 112
+28 29
+68 96
+49 111
+90 154
+98 189
+25 45
+40 129
+76 104
+72 79
+100 121
+3 73
+73 83
+51 84
+81 102
+55 91
+60 96
+54 139
+80 131
+4 84
+97 125
+75 132
+39 84
+90 153
+29 61
+27 31
+14 71
+86 112
+52 87
+1 100
+66 69
+16 51
+70 93
+91 139
+80 140
+92 144
+20 42
+45 122
+27 115
+51 112
+61 94
+54 140
+85 159
+0 99
+31 59
+9 24
+31 122
+5 13
+51 85
+22 65
+14 42
+79 120
+40 43
+13 85
+78 147
+47 48
+87 109
+94 187
+2 74
+36 95
+41 72
+85 105
+36 103
+41 94
+27 90
+66 72
+42 89
+93 170
+84 151
+66 96
+65 162
+2 3
+25 45
+50 77
+20 78
+21 50
+93 119
+76 150
+65 93
+11 68
+42 61
+28 92
+39 129
+92 112
+91 187
+48 97
+59 62
+0 31
+57 107
+83 140
+80 82
+87 135
+35 48
+23 57
+79 166
+7 81
+97 121
+97 98
diff --git a/bottleneck/tests/data/test_616_A b/bottleneck/tests/data/test_616_A
new file mode 100644
index 0000000..2b99b87
--- /dev/null
+++ b/bottleneck/tests/data/test_616_A
@@ -0,0 +1,100 @@
+74 170
+100 122
+43 126
+66 162
+54 71
+31 122
+49 55
+100 194
+68 142
+83 94
+4 55
+20 79
+90 117
+67 143
+50 51
+40 123
+21 64
+41 114
+35 44
+75 169
+82 162
+52 138
+69 99
+53 107
+36 95
+99 118
+55 69
+86 102
+70 75
+5 94
+55 133
+79 141
+100 171
+6 73
+22 99
+92 185
+5 94
+34 131
+50 143
+97 184
+51 106
+82 158
+85 173
+81 163
+59 85
+50 93
+49 60
+94 128
+83 167
+29 44
+85 164
+62 138
+33 92
+32 114
+74 80
+64 124
+30 117
+22 116
+37 80
+87 142
+65 143
+0 95
+93 131
+70 168
+35 90
+74 169
+79 173
+49 99
+33 120
+30 63
+57 113
+72 97
+71 127
+53 61
+77 139
+85 159
+0 80
+51 120
+3 76
+65 88
+63 121
+55 73
+23 92
+29 98
+2 31
+65 112
+15 86
+47 86
+100 146
+21 49
+76 158
+75 130
+65 141
+73 112
+6 90
+29 110
+89 93
+99 106
+95 135
+39 101
diff --git a/bottleneck/tests/data/test_616_B b/bottleneck/tests/data/test_616_B
new file mode 100644
index 0000000..55a8c9f
--- /dev/null
+++ b/bottleneck/tests/data/test_616_B
@@ -0,0 +1,100 @@
+22 54
+34 134
+72 81
+63 68
+99 119
+35 79
+86 177
+39 120
+68 128
+50 115
+59 119
+60 125
+19 91
+82 118
+81 100
+46 144
+99 152
+7 81
+81 113
+29 93
+68 86
+15 54
+52 67
+85 182
+44 76
+2 55
+51 146
+19 32
+39 111
+41 116
+83 112
+97 190
+83 94
+85 133
+31 103
+55 92
+99 150
+49 136
+72 138
+1 53
+25 89
+37 106
+49 149
+2 10
+39 90
+85 143
+4 17
+8 69
+59 120
+70 80
+73 96
+80 119
+57 86
+30 59
+52 60
+13 93
+16 92
+45 103
+14 27
+4 30
+81 117
+22 39
+14 78
+42 120
+19 118
+97 115
+74 164
+70 158
+12 63
+38 79
+80 150
+37 111
+71 97
+7 13
+73 162
+31 75
+61 98
+54 89
+73 110
+87 137
+61 126
+23 71
+97 146
+20 47
+98 181
+63 69
+4 102
+11 50
+17 46
+19 22
+70 167
+98 147
+99 153
+93 144
+44 72
+67 117
+46 133
+15 48
+64 135
+55 122
diff --git a/bottleneck/tests/data/test_617_A b/bottleneck/tests/data/test_617_A
new file mode 100644
index 0000000..9eb04ba
--- /dev/null
+++ b/bottleneck/tests/data/test_617_A
@@ -0,0 +1,100 @@
+91 153
+68 149
+3 63
+83 160
+15 40
+13 60
+92 126
+96 190
+2 94
+75 89
+100 141
+12 107
+66 104
+57 120
+65 91
+91 191
+12 93
+50 66
+30 85
+4 5
+63 124
+69 145
+50 131
+61 94
+23 33
+27 91
+43 46
+67 131
+90 106
+47 128
+99 109
+76 133
+62 89
+68 95
+72 125
+37 55
+10 14
+6 55
+9 13
+99 168
+14 47
+24 62
+27 112
+92 133
+95 166
+36 76
+67 152
+72 94
+72 158
+77 175
+93 143
+38 78
+20 71
+68 122
+39 111
+49 120
+0 62
+52 127
+51 142
+81 168
+63 117
+33 52
+47 48
+4 66
+92 166
+51 120
+77 80
+54 89
+83 124
+90 126
+93 122
+6 83
+63 111
+95 146
+3 57
+39 117
+76 105
+71 76
+13 88
+94 185
+77 147
+47 147
+60 123
+64 134
+97 110
+99 111
+75 119
+15 35
+82 130
+92 129
+27 108
+93 94
+91 138
+43 101
+90 160
+90 155
+27 88
+2 17
+20 43
+9 94
diff --git a/bottleneck/tests/data/test_617_B b/bottleneck/tests/data/test_617_B
new file mode 100644
index 0000000..eb300a8
--- /dev/null
+++ b/bottleneck/tests/data/test_617_B
@@ -0,0 +1,100 @@
+100 145
+51 93
+52 55
+73 86
+99 166
+80 151
+75 83
+81 105
+10 11
+52 110
+32 102
+38 124
+83 168
+55 116
+47 101
+71 90
+78 163
+19 98
+58 135
+54 137
+79 114
+91 102
+96 119
+9 10
+30 82
+15 60
+69 106
+56 125
+0 7
+71 74
+37 79
+80 102
+89 177
+43 92
+80 94
+9 92
+37 69
+6 95
+85 111
+27 38
+95 138
+92 157
+51 57
+79 96
+67 123
+56 70
+69 153
+82 151
+96 192
+12 34
+66 78
+75 154
+91 135
+79 179
+67 153
+45 86
+88 144
+91 109
+60 115
+92 176
+45 110
+35 117
+58 61
+91 147
+80 86
+9 80
+65 125
+75 78
+29 105
+69 148
+55 138
+54 60
+89 139
+98 131
+73 104
+29 127
+63 123
+7 69
+82 152
+6 92
+20 37
+41 112
+82 182
+73 128
+48 106
+60 98
+35 65
+13 42
+49 52
+8 36
+6 18
+42 70
+16 60
+30 56
+78 120
+80 94
+38 92
+19 52
+78 89
+49 131
diff --git a/bottleneck/tests/data/test_618_A b/bottleneck/tests/data/test_618_A
new file mode 100644
index 0000000..a53c5f8
--- /dev/null
+++ b/bottleneck/tests/data/test_618_A
@@ -0,0 +1,100 @@
+28 78
+66 159
+45 123
+56 140
+67 109
+32 81
+23 101
+44 121
+82 99
+20 28
+59 137
+93 185
+51 103
+75 89
+47 69
+48 94
+23 52
+35 74
+67 161
+67 138
+12 25
+50 73
+90 158
+55 124
+95 120
+36 96
+91 126
+100 114
+15 66
+89 180
+19 54
+81 137
+65 114
+46 51
+42 141
+74 88
+46 76
+38 69
+21 92
+92 97
+16 29
+97 177
+22 75
+94 155
+10 47
+96 174
+98 155
+16 104
+49 88
+36 44
+1 9
+66 83
+71 117
+45 56
+49 146
+29 66
+31 35
+49 133
+43 123
+6 20
+24 103
+14 103
+13 30
+100 101
+8 68
+71 101
+18 52
+33 94
+82 113
+0 36
+1 79
+63 141
+29 113
+41 105
+5 105
+47 142
+98 159
+48 96
+31 43
+29 76
+63 159
+9 72
+39 62
+75 111
+27 37
+72 81
+39 112
+70 88
+78 149
+69 101
+68 136
+72 77
+18 40
+48 72
+53 115
+12 78
+40 63
+75 163
+57 141
+47 140
diff --git a/bottleneck/tests/data/test_618_B b/bottleneck/tests/data/test_618_B
new file mode 100644
index 0000000..611fb6a
--- /dev/null
+++ b/bottleneck/tests/data/test_618_B
@@ -0,0 +1,100 @@
+35 126
+40 82
+62 85
+64 72
+55 138
+43 97
+12 41
+75 142
+12 68
+26 114
+69 169
+65 101
+76 161
+20 63
+25 113
+70 153
+54 70
+41 79
+29 91
+85 100
+53 134
+12 13
+38 56
+28 112
+34 118
+56 111
+17 104
+66 108
+23 26
+47 96
+18 100
+18 100
+51 127
+40 87
+63 75
+40 101
+14 48
+72 90
+80 121
+28 56
+91 147
+25 92
+31 55
+25 106
+41 57
+42 52
+65 98
+14 110
+98 188
+39 75
+68 147
+62 148
+16 96
+91 103
+83 109
+55 91
+85 184
+62 73
+9 105
+70 74
+33 132
+6 82
+97 169
+11 90
+98 194
+91 160
+74 133
+25 69
+73 114
+1 27
+100 120
+77 159
+88 187
+31 42
+24 25
+93 140
+44 96
+0 86
+39 55
+52 96
+2 54
+33 97
+63 151
+7 95
+40 54
+89 127
+71 112
+74 162
+55 113
+20 60
+81 106
+36 111
+17 75
+48 69
+6 33
+11 94
+73 150
+5 28
+62 118
+38 78
diff --git a/bottleneck/tests/data/test_619_A b/bottleneck/tests/data/test_619_A
new file mode 100644
index 0000000..4dd6557
--- /dev/null
+++ b/bottleneck/tests/data/test_619_A
@@ -0,0 +1,100 @@
+31 76
+34 130
+70 80
+52 82
+40 116
+77 109
+84 130
+53 111
+63 79
+7 12
+28 70
+35 78
+95 115
+78 123
+23 44
+96 162
+50 139
+58 155
+31 91
+91 129
+82 139
+21 111
+98 117
+75 137
+27 68
+51 125
+93 104
+71 161
+66 147
+97 132
+98 169
+93 186
+22 83
+73 136
+27 70
+100 194
+74 87
+21 31
+11 107
+59 70
+0 77
+99 126
+50 86
+31 123
+62 91
+25 119
+44 104
+68 156
+79 165
+58 89
+66 122
+20 42
+71 77
+97 177
+40 66
+78 122
+73 169
+84 89
+28 107
+58 94
+76 89
+68 103
+50 89
+90 97
+32 94
+30 96
+78 100
+97 186
+99 141
+61 116
+19 32
+19 101
+32 65
+15 67
+69 150
+55 64
+37 53
+76 130
+4 53
+27 79
+90 121
+8 53
+39 75
+90 102
+41 65
+34 124
+16 110
+52 61
+55 58
+23 62
+14 92
+39 88
+5 71
+59 110
+12 100
+14 90
+35 101
+23 105
+50 124
+58 148
diff --git a/bottleneck/tests/data/test_619_B b/bottleneck/tests/data/test_619_B
new file mode 100644
index 0000000..711d7cb
--- /dev/null
+++ b/bottleneck/tests/data/test_619_B
@@ -0,0 +1,100 @@
+75 136
+69 74
+21 44
+4 30
+6 70
+27 50
+57 72
+62 67
+50 127
+33 84
+10 71
+87 167
+12 58
+1 41
+86 164
+74 133
+64 132
+80 178
+72 124
+91 165
+4 96
+6 90
+49 97
+87 123
+34 101
+34 66
+94 108
+78 109
+34 87
+23 107
+7 70
+88 108
+100 157
+18 29
+15 38
+81 136
+39 103
+12 96
+56 136
+71 104
+90 137
+100 167
+39 125
+10 102
+8 49
+86 89
+76 153
+21 48
+52 129
+58 61
+41 136
+43 110
+37 39
+20 65
+99 161
+54 82
+17 64
+66 137
+32 44
+13 40
+43 127
+1 21
+41 63
+57 127
+29 126
+64 134
+24 122
+62 73
+20 120
+72 109
+100 156
+35 43
+4 19
+84 174
+64 101
+32 122
+14 43
+68 111
+84 132
+55 92
+21 84
+90 183
+62 63
+10 107
+40 46
+81 124
+62 120
+50 125
+38 112
+72 137
+93 190
+38 57
+27 42
+7 76
+84 169
+45 102
+51 78
+96 111
+84 153
+53 60
diff --git a/bottleneck/tests/data/test_620_A b/bottleneck/tests/data/test_620_A
new file mode 100644
index 0000000..74e7856
--- /dev/null
+++ b/bottleneck/tests/data/test_620_A
@@ -0,0 +1,2 @@
+977 1670
+257 583
diff --git a/bottleneck/tests/data/test_620_B b/bottleneck/tests/data/test_620_B
new file mode 100644
index 0000000..e7efa97
--- /dev/null
+++ b/bottleneck/tests/data/test_620_B
@@ -0,0 +1,2 @@
+519 914
+659 781
diff --git a/bottleneck/tests/data/test_621_A b/bottleneck/tests/data/test_621_A
new file mode 100644
index 0000000..6a24523
--- /dev/null
+++ b/bottleneck/tests/data/test_621_A
@@ -0,0 +1,2 @@
+928 1424
+468 1402
diff --git a/bottleneck/tests/data/test_621_B b/bottleneck/tests/data/test_621_B
new file mode 100644
index 0000000..7b49acb
--- /dev/null
+++ b/bottleneck/tests/data/test_621_B
@@ -0,0 +1,2 @@
+946 1838
+602 1466
diff --git a/bottleneck/tests/data/test_622_A b/bottleneck/tests/data/test_622_A
new file mode 100644
index 0000000..58d67ac
--- /dev/null
+++ b/bottleneck/tests/data/test_622_A
@@ -0,0 +1,2 @@
+199 1177
+163 743
diff --git a/bottleneck/tests/data/test_622_B b/bottleneck/tests/data/test_622_B
new file mode 100644
index 0000000..f9a4fdd
--- /dev/null
+++ b/bottleneck/tests/data/test_622_B
@@ -0,0 +1,2 @@
+502 1478
+838 1480
diff --git a/bottleneck/tests/data/test_623_A b/bottleneck/tests/data/test_623_A
new file mode 100644
index 0000000..8d99200
--- /dev/null
+++ b/bottleneck/tests/data/test_623_A
@@ -0,0 +1,2 @@
+156 443
+264 982
diff --git a/bottleneck/tests/data/test_623_B b/bottleneck/tests/data/test_623_B
new file mode 100644
index 0000000..22ab9fd
--- /dev/null
+++ b/bottleneck/tests/data/test_623_B
@@ -0,0 +1,2 @@
+995 1285
+571 1427
diff --git a/bottleneck/tests/data/test_624_A b/bottleneck/tests/data/test_624_A
new file mode 100644
index 0000000..49891f6
--- /dev/null
+++ b/bottleneck/tests/data/test_624_A
@@ -0,0 +1,2 @@
+884 1159
+315 1125
diff --git a/bottleneck/tests/data/test_624_B b/bottleneck/tests/data/test_624_B
new file mode 100644
index 0000000..fa3e1ea
--- /dev/null
+++ b/bottleneck/tests/data/test_624_B
@@ -0,0 +1,2 @@
+236 1034
+474 567
diff --git a/bottleneck/tests/data/test_625_A b/bottleneck/tests/data/test_625_A
new file mode 100644
index 0000000..4da6ce4
--- /dev/null
+++ b/bottleneck/tests/data/test_625_A
@@ -0,0 +1,2 @@
+8 375
+509 926
diff --git a/bottleneck/tests/data/test_625_B b/bottleneck/tests/data/test_625_B
new file mode 100644
index 0000000..bf587fc
--- /dev/null
+++ b/bottleneck/tests/data/test_625_B
@@ -0,0 +1,2 @@
+805 895
+735 1279
diff --git a/bottleneck/tests/data/test_626_A b/bottleneck/tests/data/test_626_A
new file mode 100644
index 0000000..92036c8
--- /dev/null
+++ b/bottleneck/tests/data/test_626_A
@@ -0,0 +1,2 @@
+821 1025
+74 936
diff --git a/bottleneck/tests/data/test_626_B b/bottleneck/tests/data/test_626_B
new file mode 100644
index 0000000..3052b59
--- /dev/null
+++ b/bottleneck/tests/data/test_626_B
@@ -0,0 +1,2 @@
+155 737
+564 1257
diff --git a/bottleneck/tests/data/test_627_A b/bottleneck/tests/data/test_627_A
new file mode 100644
index 0000000..f682247
--- /dev/null
+++ b/bottleneck/tests/data/test_627_A
@@ -0,0 +1,2 @@
+680 1473
+354 876
diff --git a/bottleneck/tests/data/test_627_B b/bottleneck/tests/data/test_627_B
new file mode 100644
index 0000000..7c61fad
--- /dev/null
+++ b/bottleneck/tests/data/test_627_B
@@ -0,0 +1,2 @@
+767 1509
+998 1182
diff --git a/bottleneck/tests/data/test_628_A b/bottleneck/tests/data/test_628_A
new file mode 100644
index 0000000..f499ec3
--- /dev/null
+++ b/bottleneck/tests/data/test_628_A
@@ -0,0 +1,2 @@
+481 1127
+66 1027
diff --git a/bottleneck/tests/data/test_628_B b/bottleneck/tests/data/test_628_B
new file mode 100644
index 0000000..5eb5994
--- /dev/null
+++ b/bottleneck/tests/data/test_628_B
@@ -0,0 +1,2 @@
+961 1197
+123 388
diff --git a/bottleneck/tests/data/test_629_A b/bottleneck/tests/data/test_629_A
new file mode 100644
index 0000000..ff42c12
--- /dev/null
+++ b/bottleneck/tests/data/test_629_A
@@ -0,0 +1,2 @@
+457 1026
+405 1343
diff --git a/bottleneck/tests/data/test_629_B b/bottleneck/tests/data/test_629_B
new file mode 100644
index 0000000..b0b983a
--- /dev/null
+++ b/bottleneck/tests/data/test_629_B
@@ -0,0 +1,2 @@
+575 706
+472 965
diff --git a/bottleneck/tests/data/test_630_A b/bottleneck/tests/data/test_630_A
new file mode 100644
index 0000000..6ed10cf
--- /dev/null
+++ b/bottleneck/tests/data/test_630_A
@@ -0,0 +1,2 @@
+480 650
+0 307
diff --git a/bottleneck/tests/data/test_630_B b/bottleneck/tests/data/test_630_B
new file mode 100644
index 0000000..0583a0c
--- /dev/null
+++ b/bottleneck/tests/data/test_630_B
@@ -0,0 +1,2 @@
+836 1099
+771 1050
diff --git a/bottleneck/tests/data/test_631_A b/bottleneck/tests/data/test_631_A
new file mode 100644
index 0000000..d49637c
--- /dev/null
+++ b/bottleneck/tests/data/test_631_A
@@ -0,0 +1,2 @@
+551 1534
+392 820
diff --git a/bottleneck/tests/data/test_631_B b/bottleneck/tests/data/test_631_B
new file mode 100644
index 0000000..f522f48
--- /dev/null
+++ b/bottleneck/tests/data/test_631_B
@@ -0,0 +1,2 @@
+721 1465
+591 781
diff --git a/bottleneck/tests/data/test_632_A b/bottleneck/tests/data/test_632_A
new file mode 100644
index 0000000..32c4757
--- /dev/null
+++ b/bottleneck/tests/data/test_632_A
@@ -0,0 +1,2 @@
+352 417
+814 986
diff --git a/bottleneck/tests/data/test_632_B b/bottleneck/tests/data/test_632_B
new file mode 100644
index 0000000..f50a6bb
--- /dev/null
+++ b/bottleneck/tests/data/test_632_B
@@ -0,0 +1,2 @@
+211 264
+517 1443
diff --git a/bottleneck/tests/data/test_633_A b/bottleneck/tests/data/test_633_A
new file mode 100644
index 0000000..0199c88
--- /dev/null
+++ b/bottleneck/tests/data/test_633_A
@@ -0,0 +1,2 @@
+487 1216
+842 1559
diff --git a/bottleneck/tests/data/test_633_B b/bottleneck/tests/data/test_633_B
new file mode 100644
index 0000000..d516834
--- /dev/null
+++ b/bottleneck/tests/data/test_633_B
@@ -0,0 +1,2 @@
+353 982
+437 1421
diff --git a/bottleneck/tests/data/test_634_A b/bottleneck/tests/data/test_634_A
new file mode 100644
index 0000000..45493ad
--- /dev/null
+++ b/bottleneck/tests/data/test_634_A
@@ -0,0 +1,2 @@
+367 742
+382 796
diff --git a/bottleneck/tests/data/test_634_B b/bottleneck/tests/data/test_634_B
new file mode 100644
index 0000000..8840b3a
--- /dev/null
+++ b/bottleneck/tests/data/test_634_B
@@ -0,0 +1,2 @@
+9 723
+351 901
diff --git a/bottleneck/tests/data/test_635_A b/bottleneck/tests/data/test_635_A
new file mode 100644
index 0000000..d65240b
--- /dev/null
+++ b/bottleneck/tests/data/test_635_A
@@ -0,0 +1,2 @@
+984 1272
+952 1384
diff --git a/bottleneck/tests/data/test_635_B b/bottleneck/tests/data/test_635_B
new file mode 100644
index 0000000..8cc813d
--- /dev/null
+++ b/bottleneck/tests/data/test_635_B
@@ -0,0 +1,2 @@
+528 622
+88 466
diff --git a/bottleneck/tests/data/test_636_A b/bottleneck/tests/data/test_636_A
new file mode 100644
index 0000000..eee9635
--- /dev/null
+++ b/bottleneck/tests/data/test_636_A
@@ -0,0 +1,2 @@
+285 617
+809 1379
diff --git a/bottleneck/tests/data/test_636_B b/bottleneck/tests/data/test_636_B
new file mode 100644
index 0000000..e565845
--- /dev/null
+++ b/bottleneck/tests/data/test_636_B
@@ -0,0 +1,2 @@
+162 1083
+842 1760
diff --git a/bottleneck/tests/data/test_637_A b/bottleneck/tests/data/test_637_A
new file mode 100644
index 0000000..4ba4314
--- /dev/null
+++ b/bottleneck/tests/data/test_637_A
@@ -0,0 +1,2 @@
+624 1031
+118 423
diff --git a/bottleneck/tests/data/test_637_B b/bottleneck/tests/data/test_637_B
new file mode 100644
index 0000000..58aba0f
--- /dev/null
+++ b/bottleneck/tests/data/test_637_B
@@ -0,0 +1,2 @@
+453 958
+310 1149
diff --git a/bottleneck/tests/data/test_638_A b/bottleneck/tests/data/test_638_A
new file mode 100644
index 0000000..4d993df
--- /dev/null
+++ b/bottleneck/tests/data/test_638_A
@@ -0,0 +1,2 @@
+683 1251
+811 1566
diff --git a/bottleneck/tests/data/test_638_B b/bottleneck/tests/data/test_638_B
new file mode 100644
index 0000000..5750b40
--- /dev/null
+++ b/bottleneck/tests/data/test_638_B
@@ -0,0 +1,2 @@
+489 1389
+408 858
diff --git a/bottleneck/tests/data/test_639_A b/bottleneck/tests/data/test_639_A
new file mode 100644
index 0000000..1e86c9b
--- /dev/null
+++ b/bottleneck/tests/data/test_639_A
@@ -0,0 +1,2 @@
+907 1067
+329 547
diff --git a/bottleneck/tests/data/test_639_B b/bottleneck/tests/data/test_639_B
new file mode 100644
index 0000000..758fe2d
--- /dev/null
+++ b/bottleneck/tests/data/test_639_B
@@ -0,0 +1,2 @@
+896 1777
+769 1237
diff --git a/bottleneck/tests/data/test_640_A b/bottleneck/tests/data/test_640_A
new file mode 100644
index 0000000..981248a
--- /dev/null
+++ b/bottleneck/tests/data/test_640_A
@@ -0,0 +1,3 @@
+609 1601
+450 549
+123 590
diff --git a/bottleneck/tests/data/test_640_B b/bottleneck/tests/data/test_640_B
new file mode 100644
index 0000000..d4f75ec
--- /dev/null
+++ b/bottleneck/tests/data/test_640_B
@@ -0,0 +1,3 @@
+392 752
+844 1720
+51 914
diff --git a/bottleneck/tests/data/test_641_A b/bottleneck/tests/data/test_641_A
new file mode 100644
index 0000000..04100b0
--- /dev/null
+++ b/bottleneck/tests/data/test_641_A
@@ -0,0 +1,3 @@
+344 679
+413 673
+647 1475
diff --git a/bottleneck/tests/data/test_641_B b/bottleneck/tests/data/test_641_B
new file mode 100644
index 0000000..840a640
--- /dev/null
+++ b/bottleneck/tests/data/test_641_B
@@ -0,0 +1,3 @@
+688 1185
+529 598
+382 1269
diff --git a/bottleneck/tests/data/test_642_A b/bottleneck/tests/data/test_642_A
new file mode 100644
index 0000000..a7da9ec
--- /dev/null
+++ b/bottleneck/tests/data/test_642_A
@@ -0,0 +1,3 @@
+886 1249
+24 684
+651 895
diff --git a/bottleneck/tests/data/test_642_B b/bottleneck/tests/data/test_642_B
new file mode 100644
index 0000000..e25e427
--- /dev/null
+++ b/bottleneck/tests/data/test_642_B
@@ -0,0 +1,3 @@
+779 977
+2 736
+978 1769
diff --git a/bottleneck/tests/data/test_643_A b/bottleneck/tests/data/test_643_A
new file mode 100644
index 0000000..e818bdc
--- /dev/null
+++ b/bottleneck/tests/data/test_643_A
@@ -0,0 +1,3 @@
+891 1186
+391 1185
+921 1300
diff --git a/bottleneck/tests/data/test_643_B b/bottleneck/tests/data/test_643_B
new file mode 100644
index 0000000..7a5f620
--- /dev/null
+++ b/bottleneck/tests/data/test_643_B
@@ -0,0 +1,3 @@
+21 783
+84 583
+133 483
diff --git a/bottleneck/tests/data/test_644_A b/bottleneck/tests/data/test_644_A
new file mode 100644
index 0000000..f6bc335
--- /dev/null
+++ b/bottleneck/tests/data/test_644_A
@@ -0,0 +1,3 @@
+608 1036
+485 1247
+532 1302
diff --git a/bottleneck/tests/data/test_644_B b/bottleneck/tests/data/test_644_B
new file mode 100644
index 0000000..109024d
--- /dev/null
+++ b/bottleneck/tests/data/test_644_B
@@ -0,0 +1,3 @@
+639 1059
+177 1044
+680 901
diff --git a/bottleneck/tests/data/test_645_A b/bottleneck/tests/data/test_645_A
new file mode 100644
index 0000000..3f62c52
--- /dev/null
+++ b/bottleneck/tests/data/test_645_A
@@ -0,0 +1,3 @@
+353 877
+730 1291
+610 992
diff --git a/bottleneck/tests/data/test_645_B b/bottleneck/tests/data/test_645_B
new file mode 100644
index 0000000..f818161
--- /dev/null
+++ b/bottleneck/tests/data/test_645_B
@@ -0,0 +1,3 @@
+854 1092
+395 737
+966 1230
diff --git a/bottleneck/tests/data/test_646_A b/bottleneck/tests/data/test_646_A
new file mode 100644
index 0000000..7582a95
--- /dev/null
+++ b/bottleneck/tests/data/test_646_A
@@ -0,0 +1,3 @@
+908 946
+490 875
+115 272
diff --git a/bottleneck/tests/data/test_646_B b/bottleneck/tests/data/test_646_B
new file mode 100644
index 0000000..af402f8
--- /dev/null
+++ b/bottleneck/tests/data/test_646_B
@@ -0,0 +1,3 @@
+787 1300
+123 569
+222 235
diff --git a/bottleneck/tests/data/test_647_A b/bottleneck/tests/data/test_647_A
new file mode 100644
index 0000000..caa678f
--- /dev/null
+++ b/bottleneck/tests/data/test_647_A
@@ -0,0 +1,3 @@
+165 217
+390 1141
+18 238
diff --git a/bottleneck/tests/data/test_647_B b/bottleneck/tests/data/test_647_B
new file mode 100644
index 0000000..a135f9e
--- /dev/null
+++ b/bottleneck/tests/data/test_647_B
@@ -0,0 +1,3 @@
+244 641
+97 859
+575 1088
diff --git a/bottleneck/tests/data/test_648_A b/bottleneck/tests/data/test_648_A
new file mode 100644
index 0000000..35e36b8
--- /dev/null
+++ b/bottleneck/tests/data/test_648_A
@@ -0,0 +1,3 @@
+461 1111
+285 713
+349 943
diff --git a/bottleneck/tests/data/test_648_B b/bottleneck/tests/data/test_648_B
new file mode 100644
index 0000000..8a28c4a
--- /dev/null
+++ b/bottleneck/tests/data/test_648_B
@@ -0,0 +1,3 @@
+808 938
+293 374
+580 976
diff --git a/bottleneck/tests/data/test_649_A b/bottleneck/tests/data/test_649_A
new file mode 100644
index 0000000..065cc77
--- /dev/null
+++ b/bottleneck/tests/data/test_649_A
@@ -0,0 +1,3 @@
+57 802
+286 543
+403 1224
diff --git a/bottleneck/tests/data/test_649_B b/bottleneck/tests/data/test_649_B
new file mode 100644
index 0000000..b23411e
--- /dev/null
+++ b/bottleneck/tests/data/test_649_B
@@ -0,0 +1,3 @@
+548 551
+21 683
+6 490
diff --git a/bottleneck/tests/data/test_650_A b/bottleneck/tests/data/test_650_A
new file mode 100644
index 0000000..d87b7b4
--- /dev/null
+++ b/bottleneck/tests/data/test_650_A
@@ -0,0 +1,3 @@
+36 367
+273 389
+981 1711
diff --git a/bottleneck/tests/data/test_650_B b/bottleneck/tests/data/test_650_B
new file mode 100644
index 0000000..f379676
--- /dev/null
+++ b/bottleneck/tests/data/test_650_B
@@ -0,0 +1,3 @@
+659 1452
+551 1121
+551 949
diff --git a/bottleneck/tests/data/test_651_A b/bottleneck/tests/data/test_651_A
new file mode 100644
index 0000000..ecf506a
--- /dev/null
+++ b/bottleneck/tests/data/test_651_A
@@ -0,0 +1,3 @@
+929 1425
+793 1446
+949 1437
diff --git a/bottleneck/tests/data/test_651_B b/bottleneck/tests/data/test_651_B
new file mode 100644
index 0000000..f05128d
--- /dev/null
+++ b/bottleneck/tests/data/test_651_B
@@ -0,0 +1,3 @@
+860 1575
+476 1240
+126 1042
diff --git a/bottleneck/tests/data/test_652_A b/bottleneck/tests/data/test_652_A
new file mode 100644
index 0000000..52d5bdf
--- /dev/null
+++ b/bottleneck/tests/data/test_652_A
@@ -0,0 +1,3 @@
+842 1066
+564 764
+68 267
diff --git a/bottleneck/tests/data/test_652_B b/bottleneck/tests/data/test_652_B
new file mode 100644
index 0000000..2b12de5
--- /dev/null
+++ b/bottleneck/tests/data/test_652_B
@@ -0,0 +1,3 @@
+427 528
+404 1245
+800 994
diff --git a/bottleneck/tests/data/test_653_A b/bottleneck/tests/data/test_653_A
new file mode 100644
index 0000000..b4bbdd3
--- /dev/null
+++ b/bottleneck/tests/data/test_653_A
@@ -0,0 +1,3 @@
+792 967
+574 1406
+175 533
diff --git a/bottleneck/tests/data/test_653_B b/bottleneck/tests/data/test_653_B
new file mode 100644
index 0000000..f349693
--- /dev/null
+++ b/bottleneck/tests/data/test_653_B
@@ -0,0 +1,3 @@
+421 822
+339 1231
+723 1052
diff --git a/bottleneck/tests/data/test_654_A b/bottleneck/tests/data/test_654_A
new file mode 100644
index 0000000..d090ad8
--- /dev/null
+++ b/bottleneck/tests/data/test_654_A
@@ -0,0 +1,3 @@
+175 462
+829 1810
+494 1040
diff --git a/bottleneck/tests/data/test_654_B b/bottleneck/tests/data/test_654_B
new file mode 100644
index 0000000..f9944d7
--- /dev/null
+++ b/bottleneck/tests/data/test_654_B
@@ -0,0 +1,3 @@
+656 658
+403 1260
+887 1883
diff --git a/bottleneck/tests/data/test_655_A b/bottleneck/tests/data/test_655_A
new file mode 100644
index 0000000..9105397
--- /dev/null
+++ b/bottleneck/tests/data/test_655_A
@@ -0,0 +1,3 @@
+1 419
+674 970
+633 664
diff --git a/bottleneck/tests/data/test_655_B b/bottleneck/tests/data/test_655_B
new file mode 100644
index 0000000..9aa2ab6
--- /dev/null
+++ b/bottleneck/tests/data/test_655_B
@@ -0,0 +1,3 @@
+194 461
+376 901
+417 723
diff --git a/bottleneck/tests/data/test_656_A b/bottleneck/tests/data/test_656_A
new file mode 100644
index 0000000..bcdfd3c
--- /dev/null
+++ b/bottleneck/tests/data/test_656_A
@@ -0,0 +1,3 @@
+707 825
+811 1475
+344 915
diff --git a/bottleneck/tests/data/test_656_B b/bottleneck/tests/data/test_656_B
new file mode 100644
index 0000000..5ee0ab0
--- /dev/null
+++ b/bottleneck/tests/data/test_656_B
@@ -0,0 +1,3 @@
+928 1504
+366 991
+506 1194
diff --git a/bottleneck/tests/data/test_657_A b/bottleneck/tests/data/test_657_A
new file mode 100644
index 0000000..7d39a99
--- /dev/null
+++ b/bottleneck/tests/data/test_657_A
@@ -0,0 +1,3 @@
+101 439
+539 1442
+955 1560
diff --git a/bottleneck/tests/data/test_657_B b/bottleneck/tests/data/test_657_B
new file mode 100644
index 0000000..3b9d726
--- /dev/null
+++ b/bottleneck/tests/data/test_657_B
@@ -0,0 +1,3 @@
+505 966
+757 1602
+615 1309
diff --git a/bottleneck/tests/data/test_658_A b/bottleneck/tests/data/test_658_A
new file mode 100644
index 0000000..33f8b08
--- /dev/null
+++ b/bottleneck/tests/data/test_658_A
@@ -0,0 +1,3 @@
+829 1642
+95 139
+435 558
diff --git a/bottleneck/tests/data/test_658_B b/bottleneck/tests/data/test_658_B
new file mode 100644
index 0000000..b131e5d
--- /dev/null
+++ b/bottleneck/tests/data/test_658_B
@@ -0,0 +1,3 @@
+171 1171
+240 780
+363 720
diff --git a/bottleneck/tests/data/test_659_A b/bottleneck/tests/data/test_659_A
new file mode 100644
index 0000000..974d216
--- /dev/null
+++ b/bottleneck/tests/data/test_659_A
@@ -0,0 +1,3 @@
+409 1266
+680 909
+942 1270
diff --git a/bottleneck/tests/data/test_659_B b/bottleneck/tests/data/test_659_B
new file mode 100644
index 0000000..c3cfbeb
--- /dev/null
+++ b/bottleneck/tests/data/test_659_B
@@ -0,0 +1,3 @@
+318 1245
+561 1013
+787 1275
diff --git a/bottleneck/tests/data/test_660_A b/bottleneck/tests/data/test_660_A
new file mode 100644
index 0000000..1c408f3
--- /dev/null
+++ b/bottleneck/tests/data/test_660_A
@@ -0,0 +1,4 @@
+526 757
+355 743
+250 1221
+35 439
diff --git a/bottleneck/tests/data/test_660_B b/bottleneck/tests/data/test_660_B
new file mode 100644
index 0000000..5fffa69
--- /dev/null
+++ b/bottleneck/tests/data/test_660_B
@@ -0,0 +1,4 @@
+348 611
+127 398
+839 1650
+136 803
diff --git a/bottleneck/tests/data/test_661_A b/bottleneck/tests/data/test_661_A
new file mode 100644
index 0000000..df0d8ad
--- /dev/null
+++ b/bottleneck/tests/data/test_661_A
@@ -0,0 +1,4 @@
+769 905
+534 1227
+410 422
+937 1744
diff --git a/bottleneck/tests/data/test_661_B b/bottleneck/tests/data/test_661_B
new file mode 100644
index 0000000..56cfa0c
--- /dev/null
+++ b/bottleneck/tests/data/test_661_B
@@ -0,0 +1,4 @@
+19 350
+255 390
+910 1001
+853 1070
diff --git a/bottleneck/tests/data/test_662_A b/bottleneck/tests/data/test_662_A
new file mode 100644
index 0000000..cb65a38
--- /dev/null
+++ b/bottleneck/tests/data/test_662_A
@@ -0,0 +1,4 @@
+394 674
+364 1209
+763 1333
+344 1294
diff --git a/bottleneck/tests/data/test_662_B b/bottleneck/tests/data/test_662_B
new file mode 100644
index 0000000..92f0ee6
--- /dev/null
+++ b/bottleneck/tests/data/test_662_B
@@ -0,0 +1,4 @@
+324 939
+829 987
+210 998
+519 756
diff --git a/bottleneck/tests/data/test_663_A b/bottleneck/tests/data/test_663_A
new file mode 100644
index 0000000..ed35031
--- /dev/null
+++ b/bottleneck/tests/data/test_663_A
@@ -0,0 +1,4 @@
+659 1254
+201 1188
+660 811
+630 1044
diff --git a/bottleneck/tests/data/test_663_B b/bottleneck/tests/data/test_663_B
new file mode 100644
index 0000000..6a6126c
--- /dev/null
+++ b/bottleneck/tests/data/test_663_B
@@ -0,0 +1,4 @@
+873 914
+441 1063
+135 468
+584 620
diff --git a/bottleneck/tests/data/test_664_A b/bottleneck/tests/data/test_664_A
new file mode 100644
index 0000000..59f6bfa
--- /dev/null
+++ b/bottleneck/tests/data/test_664_A
@@ -0,0 +1,4 @@
+753 1625
+353 1109
+565 650
+321 708
diff --git a/bottleneck/tests/data/test_664_B b/bottleneck/tests/data/test_664_B
new file mode 100644
index 0000000..6b34a5f
--- /dev/null
+++ b/bottleneck/tests/data/test_664_B
@@ -0,0 +1,4 @@
+664 794
+572 1058
+754 1119
+899 1445
diff --git a/bottleneck/tests/data/test_665_A b/bottleneck/tests/data/test_665_A
new file mode 100644
index 0000000..ff6ce72
--- /dev/null
+++ b/bottleneck/tests/data/test_665_A
@@ -0,0 +1,4 @@
+661 1260
+232 833
+820 826
+32 139
diff --git a/bottleneck/tests/data/test_665_B b/bottleneck/tests/data/test_665_B
new file mode 100644
index 0000000..9a5d4a9
--- /dev/null
+++ b/bottleneck/tests/data/test_665_B
@@ -0,0 +1,4 @@
+466 1319
+809 1762
+165 235
+636 1460
diff --git a/bottleneck/tests/data/test_666_A b/bottleneck/tests/data/test_666_A
new file mode 100644
index 0000000..455e262
--- /dev/null
+++ b/bottleneck/tests/data/test_666_A
@@ -0,0 +1,4 @@
+496 1447
+606 1017
+578 767
+971 1768
diff --git a/bottleneck/tests/data/test_666_B b/bottleneck/tests/data/test_666_B
new file mode 100644
index 0000000..0c9069e
--- /dev/null
+++ b/bottleneck/tests/data/test_666_B
@@ -0,0 +1,4 @@
+578 896
+731 1115
+455 1129
+649 1421
diff --git a/bottleneck/tests/data/test_667_A b/bottleneck/tests/data/test_667_A
new file mode 100644
index 0000000..054d14e
--- /dev/null
+++ b/bottleneck/tests/data/test_667_A
@@ -0,0 +1,4 @@
+537 1030
+887 1179
+644 905
+403 1382
diff --git a/bottleneck/tests/data/test_667_B b/bottleneck/tests/data/test_667_B
new file mode 100644
index 0000000..a4a432a
--- /dev/null
+++ b/bottleneck/tests/data/test_667_B
@@ -0,0 +1,4 @@
+981 1100
+582 1487
+603 1448
+526 1059
diff --git a/bottleneck/tests/data/test_668_A b/bottleneck/tests/data/test_668_A
new file mode 100644
index 0000000..00c5554
--- /dev/null
+++ b/bottleneck/tests/data/test_668_A
@@ -0,0 +1,4 @@
+376 564
+803 1414
+324 973
+901 1266
diff --git a/bottleneck/tests/data/test_668_B b/bottleneck/tests/data/test_668_B
new file mode 100644
index 0000000..5b7e07c
--- /dev/null
+++ b/bottleneck/tests/data/test_668_B
@@ -0,0 +1,4 @@
+901 1627
+805 1168
+867 1069
+156 291
diff --git a/bottleneck/tests/data/test_669_A b/bottleneck/tests/data/test_669_A
new file mode 100644
index 0000000..2abb014
--- /dev/null
+++ b/bottleneck/tests/data/test_669_A
@@ -0,0 +1,4 @@
+282 848
+560 1190
+152 342
+998 1524
diff --git a/bottleneck/tests/data/test_669_B b/bottleneck/tests/data/test_669_B
new file mode 100644
index 0000000..5694ce9
--- /dev/null
+++ b/bottleneck/tests/data/test_669_B
@@ -0,0 +1,4 @@
+398 731
+835 1681
+791 1026
+939 1024
diff --git a/bottleneck/tests/data/test_670_A b/bottleneck/tests/data/test_670_A
new file mode 100644
index 0000000..e7ae4f1
--- /dev/null
+++ b/bottleneck/tests/data/test_670_A
@@ -0,0 +1,4 @@
+665 1146
+512 1332
+375 595
+566 1211
diff --git a/bottleneck/tests/data/test_670_B b/bottleneck/tests/data/test_670_B
new file mode 100644
index 0000000..8f6b057
--- /dev/null
+++ b/bottleneck/tests/data/test_670_B
@@ -0,0 +1,4 @@
+203 469
+966 1146
+342 638
+290 498
diff --git a/bottleneck/tests/data/test_671_A b/bottleneck/tests/data/test_671_A
new file mode 100644
index 0000000..8ac70f3
--- /dev/null
+++ b/bottleneck/tests/data/test_671_A
@@ -0,0 +1,4 @@
+533 1333
+682 1127
+928 1703
+487 781
diff --git a/bottleneck/tests/data/test_671_B b/bottleneck/tests/data/test_671_B
new file mode 100644
index 0000000..bcb5f1b
--- /dev/null
+++ b/bottleneck/tests/data/test_671_B
@@ -0,0 +1,4 @@
+336 1128
+992 1292
+931 1497
+622 1165
diff --git a/bottleneck/tests/data/test_672_A b/bottleneck/tests/data/test_672_A
new file mode 100644
index 0000000..4ca2b19
--- /dev/null
+++ b/bottleneck/tests/data/test_672_A
@@ -0,0 +1,4 @@
+30 600
+893 1394
+112 776
+434 905
diff --git a/bottleneck/tests/data/test_672_B b/bottleneck/tests/data/test_672_B
new file mode 100644
index 0000000..29b8d76
--- /dev/null
+++ b/bottleneck/tests/data/test_672_B
@@ -0,0 +1,4 @@
+684 1559
+372 1171
+113 700
+180 865
diff --git a/bottleneck/tests/data/test_673_A b/bottleneck/tests/data/test_673_A
new file mode 100644
index 0000000..f6e6e4a
--- /dev/null
+++ b/bottleneck/tests/data/test_673_A
@@ -0,0 +1,4 @@
+894 1455
+676 1502
+402 976
+863 1258
diff --git a/bottleneck/tests/data/test_673_B b/bottleneck/tests/data/test_673_B
new file mode 100644
index 0000000..01ac9c7
--- /dev/null
+++ b/bottleneck/tests/data/test_673_B
@@ -0,0 +1,4 @@
+190 473
+420 1059
+187 827
+482 1365
diff --git a/bottleneck/tests/data/test_674_A b/bottleneck/tests/data/test_674_A
new file mode 100644
index 0000000..8bbf6ad
--- /dev/null
+++ b/bottleneck/tests/data/test_674_A
@@ -0,0 +1,4 @@
+89 681
+460 781
+500 679
+786 827
diff --git a/bottleneck/tests/data/test_674_B b/bottleneck/tests/data/test_674_B
new file mode 100644
index 0000000..ddebd4c
--- /dev/null
+++ b/bottleneck/tests/data/test_674_B
@@ -0,0 +1,4 @@
+445 1261
+769 1735
+5 81
+964 1477
diff --git a/bottleneck/tests/data/test_675_A b/bottleneck/tests/data/test_675_A
new file mode 100644
index 0000000..30b36bb
--- /dev/null
+++ b/bottleneck/tests/data/test_675_A
@@ -0,0 +1,4 @@
+507 965
+1000 1816
+946 1201
+926 1637
diff --git a/bottleneck/tests/data/test_675_B b/bottleneck/tests/data/test_675_B
new file mode 100644
index 0000000..c0722ef
--- /dev/null
+++ b/bottleneck/tests/data/test_675_B
@@ -0,0 +1,4 @@
+302 1162
+795 1527
+602 747
+646 683
diff --git a/bottleneck/tests/data/test_676_A b/bottleneck/tests/data/test_676_A
new file mode 100644
index 0000000..b43ef5e
--- /dev/null
+++ b/bottleneck/tests/data/test_676_A
@@ -0,0 +1,4 @@
+343 1040
+556 758
+286 983
+467 700
diff --git a/bottleneck/tests/data/test_676_B b/bottleneck/tests/data/test_676_B
new file mode 100644
index 0000000..59b2fb6
--- /dev/null
+++ b/bottleneck/tests/data/test_676_B
@@ -0,0 +1,4 @@
+446 1062
+65 988
+159 1102
+920 1553
diff --git a/bottleneck/tests/data/test_677_A b/bottleneck/tests/data/test_677_A
new file mode 100644
index 0000000..4d9d36e
--- /dev/null
+++ b/bottleneck/tests/data/test_677_A
@@ -0,0 +1,4 @@
+355 949
+561 704
+153 945
+407 1134
diff --git a/bottleneck/tests/data/test_677_B b/bottleneck/tests/data/test_677_B
new file mode 100644
index 0000000..4edf573
--- /dev/null
+++ b/bottleneck/tests/data/test_677_B
@@ -0,0 +1,4 @@
+758 962
+354 535
+115 782
+309 1207
diff --git a/bottleneck/tests/data/test_678_A b/bottleneck/tests/data/test_678_A
new file mode 100644
index 0000000..54ab668
--- /dev/null
+++ b/bottleneck/tests/data/test_678_A
@@ -0,0 +1,4 @@
+946 1489
+594 1446
+686 986
+200 493
diff --git a/bottleneck/tests/data/test_678_B b/bottleneck/tests/data/test_678_B
new file mode 100644
index 0000000..f695f5f
--- /dev/null
+++ b/bottleneck/tests/data/test_678_B
@@ -0,0 +1,4 @@
+708 725
+761 1309
+47 963
+61 320
diff --git a/bottleneck/tests/data/test_679_A b/bottleneck/tests/data/test_679_A
new file mode 100644
index 0000000..33e4ce8
--- /dev/null
+++ b/bottleneck/tests/data/test_679_A
@@ -0,0 +1,4 @@
+153 950
+179 1047
+736 845
+943 1760
diff --git a/bottleneck/tests/data/test_679_B b/bottleneck/tests/data/test_679_B
new file mode 100644
index 0000000..a99ec77
--- /dev/null
+++ b/bottleneck/tests/data/test_679_B
@@ -0,0 +1,4 @@
+744 1423
+669 1350
+989 1062
+57 823
diff --git a/bottleneck/tests/data/test_680_A b/bottleneck/tests/data/test_680_A
new file mode 100644
index 0000000..4bb43a8
--- /dev/null
+++ b/bottleneck/tests/data/test_680_A
@@ -0,0 +1,5 @@
+102 183
+847 1835
+300 1098
+953 1849
+327 1070
diff --git a/bottleneck/tests/data/test_680_B b/bottleneck/tests/data/test_680_B
new file mode 100644
index 0000000..efb704f
--- /dev/null
+++ b/bottleneck/tests/data/test_680_B
@@ -0,0 +1,5 @@
+917 1904
+340 1190
+128 516
+695 1474
+450 628
diff --git a/bottleneck/tests/data/test_681_A b/bottleneck/tests/data/test_681_A
new file mode 100644
index 0000000..5eb7d6a
--- /dev/null
+++ b/bottleneck/tests/data/test_681_A
@@ -0,0 +1,5 @@
+882 1558
+108 921
+479 653
+329 533
+643 952
diff --git a/bottleneck/tests/data/test_681_B b/bottleneck/tests/data/test_681_B
new file mode 100644
index 0000000..092ddc5
--- /dev/null
+++ b/bottleneck/tests/data/test_681_B
@@ -0,0 +1,5 @@
+155 350
+686 1081
+791 900
+402 653
+364 610
diff --git a/bottleneck/tests/data/test_682_A b/bottleneck/tests/data/test_682_A
new file mode 100644
index 0000000..7898cba
--- /dev/null
+++ b/bottleneck/tests/data/test_682_A
@@ -0,0 +1,5 @@
+548 632
+839 990
+856 1008
+719 1091
+532 1445
diff --git a/bottleneck/tests/data/test_682_B b/bottleneck/tests/data/test_682_B
new file mode 100644
index 0000000..f5b1d81
--- /dev/null
+++ b/bottleneck/tests/data/test_682_B
@@ -0,0 +1,5 @@
+341 429
+146 682
+40 962
+543 1339
+277 944
diff --git a/bottleneck/tests/data/test_683_A b/bottleneck/tests/data/test_683_A
new file mode 100644
index 0000000..3661bfc
--- /dev/null
+++ b/bottleneck/tests/data/test_683_A
@@ -0,0 +1,5 @@
+227 587
+365 708
+565 1465
+240 248
+610 1328
diff --git a/bottleneck/tests/data/test_683_B b/bottleneck/tests/data/test_683_B
new file mode 100644
index 0000000..62c998b
--- /dev/null
+++ b/bottleneck/tests/data/test_683_B
@@ -0,0 +1,5 @@
+741 1553
+314 914
+980 1322
+398 1163
+304 901
diff --git a/bottleneck/tests/data/test_684_A b/bottleneck/tests/data/test_684_A
new file mode 100644
index 0000000..b22afe3
--- /dev/null
+++ b/bottleneck/tests/data/test_684_A
@@ -0,0 +1,5 @@
+196 1047
+489 739
+11 758
+204 1069
+959 976
diff --git a/bottleneck/tests/data/test_684_B b/bottleneck/tests/data/test_684_B
new file mode 100644
index 0000000..cbede63
--- /dev/null
+++ b/bottleneck/tests/data/test_684_B
@@ -0,0 +1,5 @@
+391 1180
+229 906
+246 1219
+564 1171
+797 1273
diff --git a/bottleneck/tests/data/test_685_A b/bottleneck/tests/data/test_685_A
new file mode 100644
index 0000000..c4bd0e9
--- /dev/null
+++ b/bottleneck/tests/data/test_685_A
@@ -0,0 +1,5 @@
+628 762
+148 921
+694 1155
+865 1298
+365 1337
diff --git a/bottleneck/tests/data/test_685_B b/bottleneck/tests/data/test_685_B
new file mode 100644
index 0000000..984dd98
--- /dev/null
+++ b/bottleneck/tests/data/test_685_B
@@ -0,0 +1,5 @@
+504 1226
+608 1576
+256 475
+479 884
+384 656
diff --git a/bottleneck/tests/data/test_686_A b/bottleneck/tests/data/test_686_A
new file mode 100644
index 0000000..e498d5c
--- /dev/null
+++ b/bottleneck/tests/data/test_686_A
@@ -0,0 +1,5 @@
+839 1291
+140 808
+539 720
+928 1729
+881 1126
diff --git a/bottleneck/tests/data/test_686_B b/bottleneck/tests/data/test_686_B
new file mode 100644
index 0000000..56ada59
--- /dev/null
+++ b/bottleneck/tests/data/test_686_B
@@ -0,0 +1,5 @@
+280 962
+935 1205
+328 1022
+27 247
+554 732
diff --git a/bottleneck/tests/data/test_687_A b/bottleneck/tests/data/test_687_A
new file mode 100644
index 0000000..c31c2d2
--- /dev/null
+++ b/bottleneck/tests/data/test_687_A
@@ -0,0 +1,5 @@
+323 954
+507 885
+533 1044
+679 1402
+43 918
diff --git a/bottleneck/tests/data/test_687_B b/bottleneck/tests/data/test_687_B
new file mode 100644
index 0000000..471eeed
--- /dev/null
+++ b/bottleneck/tests/data/test_687_B
@@ -0,0 +1,5 @@
+243 823
+269 1215
+449 1214
+24 777
+705 1558
diff --git a/bottleneck/tests/data/test_688_A b/bottleneck/tests/data/test_688_A
new file mode 100644
index 0000000..7396099
--- /dev/null
+++ b/bottleneck/tests/data/test_688_A
@@ -0,0 +1,5 @@
+471 989
+319 432
+130 900
+856 1389
+422 635
diff --git a/bottleneck/tests/data/test_688_B b/bottleneck/tests/data/test_688_B
new file mode 100644
index 0000000..e133e74
--- /dev/null
+++ b/bottleneck/tests/data/test_688_B
@@ -0,0 +1,5 @@
+13 373
+575 1199
+553 1347
+158 1148
+111 393
diff --git a/bottleneck/tests/data/test_689_A b/bottleneck/tests/data/test_689_A
new file mode 100644
index 0000000..72febe7
--- /dev/null
+++ b/bottleneck/tests/data/test_689_A
@@ -0,0 +1,5 @@
+451 1035
+293 380
+400 648
+9 681
+85 96
diff --git a/bottleneck/tests/data/test_689_B b/bottleneck/tests/data/test_689_B
new file mode 100644
index 0000000..f684387
--- /dev/null
+++ b/bottleneck/tests/data/test_689_B
@@ -0,0 +1,5 @@
+431 1117
+40 969
+54 1026
+297 710
+722 1143
diff --git a/bottleneck/tests/data/test_690_A b/bottleneck/tests/data/test_690_A
new file mode 100644
index 0000000..4106f49
--- /dev/null
+++ b/bottleneck/tests/data/test_690_A
@@ -0,0 +1,5 @@
+624 1464
+228 1205
+638 876
+896 1632
+564 1378
diff --git a/bottleneck/tests/data/test_690_B b/bottleneck/tests/data/test_690_B
new file mode 100644
index 0000000..d452cff
--- /dev/null
+++ b/bottleneck/tests/data/test_690_B
@@ -0,0 +1,5 @@
+745 1386
+574 898
+472 1427
+922 1325
+592 1053
diff --git a/bottleneck/tests/data/test_691_A b/bottleneck/tests/data/test_691_A
new file mode 100644
index 0000000..b6c906e
--- /dev/null
+++ b/bottleneck/tests/data/test_691_A
@@ -0,0 +1,5 @@
+291 1111
+75 251
+47 913
+753 1632
+582 739
diff --git a/bottleneck/tests/data/test_691_B b/bottleneck/tests/data/test_691_B
new file mode 100644
index 0000000..57e58ff
--- /dev/null
+++ b/bottleneck/tests/data/test_691_B
@@ -0,0 +1,5 @@
+264 911
+478 839
+182 258
+336 1121
+915 1764
diff --git a/bottleneck/tests/data/test_692_A b/bottleneck/tests/data/test_692_A
new file mode 100644
index 0000000..1686c25
--- /dev/null
+++ b/bottleneck/tests/data/test_692_A
@@ -0,0 +1,5 @@
+856 1460
+852 1085
+246 328
+508 1202
+900 1487
diff --git a/bottleneck/tests/data/test_692_B b/bottleneck/tests/data/test_692_B
new file mode 100644
index 0000000..bf6174a
--- /dev/null
+++ b/bottleneck/tests/data/test_692_B
@@ -0,0 +1,5 @@
+624 1180
+247 889
+218 373
+823 1637
+439 597
diff --git a/bottleneck/tests/data/test_693_A b/bottleneck/tests/data/test_693_A
new file mode 100644
index 0000000..ea16ba6
--- /dev/null
+++ b/bottleneck/tests/data/test_693_A
@@ -0,0 +1,5 @@
+37 175
+952 1934
+808 843
+742 822
+75 863
diff --git a/bottleneck/tests/data/test_693_B b/bottleneck/tests/data/test_693_B
new file mode 100644
index 0000000..52c8f97
--- /dev/null
+++ b/bottleneck/tests/data/test_693_B
@@ -0,0 +1,5 @@
+431 1287
+490 765
+552 843
+179 1131
+334 732
diff --git a/bottleneck/tests/data/test_694_A b/bottleneck/tests/data/test_694_A
new file mode 100644
index 0000000..e577a0f
--- /dev/null
+++ b/bottleneck/tests/data/test_694_A
@@ -0,0 +1,5 @@
+917 1066
+928 1036
+611 1593
+682 1661
+561 810
diff --git a/bottleneck/tests/data/test_694_B b/bottleneck/tests/data/test_694_B
new file mode 100644
index 0000000..e406840
--- /dev/null
+++ b/bottleneck/tests/data/test_694_B
@@ -0,0 +1,5 @@
+754 918
+735 1730
+430 1284
+588 986
+56 791
diff --git a/bottleneck/tests/data/test_695_A b/bottleneck/tests/data/test_695_A
new file mode 100644
index 0000000..ef9cacb
--- /dev/null
+++ b/bottleneck/tests/data/test_695_A
@@ -0,0 +1,5 @@
+219 629
+438 1008
+695 1385
+137 844
+394 1126
diff --git a/bottleneck/tests/data/test_695_B b/bottleneck/tests/data/test_695_B
new file mode 100644
index 0000000..f2bb91b
--- /dev/null
+++ b/bottleneck/tests/data/test_695_B
@@ -0,0 +1,5 @@
+556 1218
+942 975
+730 1199
+110 947
+867 1613
diff --git a/bottleneck/tests/data/test_696_A b/bottleneck/tests/data/test_696_A
new file mode 100644
index 0000000..71fa19f
--- /dev/null
+++ b/bottleneck/tests/data/test_696_A
@@ -0,0 +1,5 @@
+929 1104
+287 561
+801 1419
+549 1265
+758 795
diff --git a/bottleneck/tests/data/test_696_B b/bottleneck/tests/data/test_696_B
new file mode 100644
index 0000000..a964c63
--- /dev/null
+++ b/bottleneck/tests/data/test_696_B
@@ -0,0 +1,5 @@
+446 641
+863 1426
+0 382
+659 945
+707 715
diff --git a/bottleneck/tests/data/test_697_A b/bottleneck/tests/data/test_697_A
new file mode 100644
index 0000000..848e417
--- /dev/null
+++ b/bottleneck/tests/data/test_697_A
@@ -0,0 +1,5 @@
+876 1854
+147 864
+249 1095
+965 1723
+548 865
diff --git a/bottleneck/tests/data/test_697_B b/bottleneck/tests/data/test_697_B
new file mode 100644
index 0000000..98a8d15
--- /dev/null
+++ b/bottleneck/tests/data/test_697_B
@@ -0,0 +1,5 @@
+478 1175
+40 533
+212 388
+865 1736
+697 1335
diff --git a/bottleneck/tests/data/test_698_A b/bottleneck/tests/data/test_698_A
new file mode 100644
index 0000000..a90620d
--- /dev/null
+++ b/bottleneck/tests/data/test_698_A
@@ -0,0 +1,5 @@
+714 1561
+967 1649
+57 65
+560 807
+451 1000
diff --git a/bottleneck/tests/data/test_698_B b/bottleneck/tests/data/test_698_B
new file mode 100644
index 0000000..ef52ae0
--- /dev/null
+++ b/bottleneck/tests/data/test_698_B
@@ -0,0 +1,5 @@
+909 1809
+266 758
+894 1395
+495 1481
+91 646
diff --git a/bottleneck/tests/data/test_699_A b/bottleneck/tests/data/test_699_A
new file mode 100644
index 0000000..e00215d
--- /dev/null
+++ b/bottleneck/tests/data/test_699_A
@@ -0,0 +1,5 @@
+749 799
+150 307
+463 1009
+503 1047
+613 1549
diff --git a/bottleneck/tests/data/test_699_B b/bottleneck/tests/data/test_699_B
new file mode 100644
index 0000000..0fff210
--- /dev/null
+++ b/bottleneck/tests/data/test_699_B
@@ -0,0 +1,5 @@
+915 1430
+582 685
+994 1491
+227 869
+251 1173
diff --git a/bottleneck/tests/data/test_700_A b/bottleneck/tests/data/test_700_A
new file mode 100644
index 0000000..9425b73
--- /dev/null
+++ b/bottleneck/tests/data/test_700_A
@@ -0,0 +1,6 @@
+313 977
+396 888
+244 339
+474 1072
+191 1069
+519 940
diff --git a/bottleneck/tests/data/test_700_B b/bottleneck/tests/data/test_700_B
new file mode 100644
index 0000000..19944b2
--- /dev/null
+++ b/bottleneck/tests/data/test_700_B
@@ -0,0 +1,6 @@
+547 588
+852 1072
+34 817
+54 441
+222 413
+184 888
diff --git a/bottleneck/tests/data/test_701_A b/bottleneck/tests/data/test_701_A
new file mode 100644
index 0000000..062d6fb
--- /dev/null
+++ b/bottleneck/tests/data/test_701_A
@@ -0,0 +1,6 @@
+582 910
+701 1226
+195 619
+541 668
+275 1161
+322 1041
diff --git a/bottleneck/tests/data/test_701_B b/bottleneck/tests/data/test_701_B
new file mode 100644
index 0000000..3149c7c
--- /dev/null
+++ b/bottleneck/tests/data/test_701_B
@@ -0,0 +1,6 @@
+868 1747
+559 1027
+635 1354
+337 541
+630 1220
+860 1681
diff --git a/bottleneck/tests/data/test_702_A b/bottleneck/tests/data/test_702_A
new file mode 100644
index 0000000..2a82935
--- /dev/null
+++ b/bottleneck/tests/data/test_702_A
@@ -0,0 +1,6 @@
+378 869
+890 1016
+13 941
+706 1365
+879 1261
+334 864
diff --git a/bottleneck/tests/data/test_702_B b/bottleneck/tests/data/test_702_B
new file mode 100644
index 0000000..c3854d5
--- /dev/null
+++ b/bottleneck/tests/data/test_702_B
@@ -0,0 +1,6 @@
+381 525
+852 1350
+825 884
+984 1542
+614 942
+74 652
diff --git a/bottleneck/tests/data/test_703_A b/bottleneck/tests/data/test_703_A
new file mode 100644
index 0000000..fb434c0
--- /dev/null
+++ b/bottleneck/tests/data/test_703_A
@@ -0,0 +1,6 @@
+551 801
+116 205
+364 382
+883 1597
+834 1212
+737 988
diff --git a/bottleneck/tests/data/test_703_B b/bottleneck/tests/data/test_703_B
new file mode 100644
index 0000000..f8af9dd
--- /dev/null
+++ b/bottleneck/tests/data/test_703_B
@@ -0,0 +1,6 @@
+661 695
+904 1528
+65 986
+691 785
+98 1000
+102 592
diff --git a/bottleneck/tests/data/test_704_A b/bottleneck/tests/data/test_704_A
new file mode 100644
index 0000000..a89a1aa
--- /dev/null
+++ b/bottleneck/tests/data/test_704_A
@@ -0,0 +1,6 @@
+679 1424
+746 1074
+761 1546
+360 934
+139 855
+942 1002
diff --git a/bottleneck/tests/data/test_704_B b/bottleneck/tests/data/test_704_B
new file mode 100644
index 0000000..5abc5fa
--- /dev/null
+++ b/bottleneck/tests/data/test_704_B
@@ -0,0 +1,6 @@
+781 1388
+48 645
+242 294
+979 1071
+348 1065
+701 1351
diff --git a/bottleneck/tests/data/test_705_A b/bottleneck/tests/data/test_705_A
new file mode 100644
index 0000000..924a661
--- /dev/null
+++ b/bottleneck/tests/data/test_705_A
@@ -0,0 +1,6 @@
+123 751
+405 935
+708 1217
+540 708
+810 1047
+346 1088
diff --git a/bottleneck/tests/data/test_705_B b/bottleneck/tests/data/test_705_B
new file mode 100644
index 0000000..0681a80
--- /dev/null
+++ b/bottleneck/tests/data/test_705_B
@@ -0,0 +1,6 @@
+175 1150
+840 1056
+180 658
+805 1787
+123 467
+947 1539
diff --git a/bottleneck/tests/data/test_706_A b/bottleneck/tests/data/test_706_A
new file mode 100644
index 0000000..0a249be
--- /dev/null
+++ b/bottleneck/tests/data/test_706_A
@@ -0,0 +1,6 @@
+900 1181
+555 663
+1 750
+883 1197
+33 518
+450 808
diff --git a/bottleneck/tests/data/test_706_B b/bottleneck/tests/data/test_706_B
new file mode 100644
index 0000000..624923c
--- /dev/null
+++ b/bottleneck/tests/data/test_706_B
@@ -0,0 +1,6 @@
+682 818
+814 1240
+900 1777
+399 967
+420 921
+723 1022
diff --git a/bottleneck/tests/data/test_707_A b/bottleneck/tests/data/test_707_A
new file mode 100644
index 0000000..a251b74
--- /dev/null
+++ b/bottleneck/tests/data/test_707_A
@@ -0,0 +1,6 @@
+991 1398
+632 1322
+635 1448
+97 955
+793 1016
+995 1832
diff --git a/bottleneck/tests/data/test_707_B b/bottleneck/tests/data/test_707_B
new file mode 100644
index 0000000..2647b31
--- /dev/null
+++ b/bottleneck/tests/data/test_707_B
@@ -0,0 +1,6 @@
+320 551
+552 1125
+383 551
+891 1032
+272 1038
+925 1695
diff --git a/bottleneck/tests/data/test_708_A b/bottleneck/tests/data/test_708_A
new file mode 100644
index 0000000..ddc601a
--- /dev/null
+++ b/bottleneck/tests/data/test_708_A
@@ -0,0 +1,6 @@
+681 786
+125 980
+146 721
+769 1207
+504 1208
+724 985
diff --git a/bottleneck/tests/data/test_708_B b/bottleneck/tests/data/test_708_B
new file mode 100644
index 0000000..0a64a4f
--- /dev/null
+++ b/bottleneck/tests/data/test_708_B
@@ -0,0 +1,6 @@
+571 697
+763 1635
+573 623
+683 1438
+783 1580
+541 1374
diff --git a/bottleneck/tests/data/test_709_A b/bottleneck/tests/data/test_709_A
new file mode 100644
index 0000000..2d3aa30
--- /dev/null
+++ b/bottleneck/tests/data/test_709_A
@@ -0,0 +1,6 @@
+704 1089
+764 1349
+322 1100
+731 1284
+42 525
+49 602
diff --git a/bottleneck/tests/data/test_709_B b/bottleneck/tests/data/test_709_B
new file mode 100644
index 0000000..c5f7233
--- /dev/null
+++ b/bottleneck/tests/data/test_709_B
@@ -0,0 +1,6 @@
+435 502
+150 1140
+356 1273
+592 1292
+552 1331
+905 1713
diff --git a/bottleneck/tests/data/test_710_A b/bottleneck/tests/data/test_710_A
new file mode 100644
index 0000000..e611f5a
--- /dev/null
+++ b/bottleneck/tests/data/test_710_A
@@ -0,0 +1,6 @@
+257 589
+18 966
+482 1110
+588 763
+989 1857
+479 494
diff --git a/bottleneck/tests/data/test_710_B b/bottleneck/tests/data/test_710_B
new file mode 100644
index 0000000..cd9cedb
--- /dev/null
+++ b/bottleneck/tests/data/test_710_B
@@ -0,0 +1,6 @@
+2 263
+642 884
+72 321
+632 1186
+633 1310
+263 1219
diff --git a/bottleneck/tests/data/test_711_A b/bottleneck/tests/data/test_711_A
new file mode 100644
index 0000000..900b87a
--- /dev/null
+++ b/bottleneck/tests/data/test_711_A
@@ -0,0 +1,6 @@
+954 1912
+243 556
+758 967
+836 1102
+184 1134
+401 434
diff --git a/bottleneck/tests/data/test_711_B b/bottleneck/tests/data/test_711_B
new file mode 100644
index 0000000..31dd505
--- /dev/null
+++ b/bottleneck/tests/data/test_711_B
@@ -0,0 +1,6 @@
+454 1045
+606 646
+999 1478
+398 845
+743 1192
+926 1080
diff --git a/bottleneck/tests/data/test_712_A b/bottleneck/tests/data/test_712_A
new file mode 100644
index 0000000..15bc0a2
--- /dev/null
+++ b/bottleneck/tests/data/test_712_A
@@ -0,0 +1,6 @@
+395 1052
+984 1461
+792 801
+652 1183
+411 744
+830 876
diff --git a/bottleneck/tests/data/test_712_B b/bottleneck/tests/data/test_712_B
new file mode 100644
index 0000000..3071ea5
--- /dev/null
+++ b/bottleneck/tests/data/test_712_B
@@ -0,0 +1,6 @@
+16 294
+910 1274
+495 1113
+4 944
+244 512
+164 1074
diff --git a/bottleneck/tests/data/test_713_A b/bottleneck/tests/data/test_713_A
new file mode 100644
index 0000000..89ee240
--- /dev/null
+++ b/bottleneck/tests/data/test_713_A
@@ -0,0 +1,6 @@
+588 1259
+827 1531
+94 877
+171 1137
+482 729
+879 1065
diff --git a/bottleneck/tests/data/test_713_B b/bottleneck/tests/data/test_713_B
new file mode 100644
index 0000000..f2b501c
--- /dev/null
+++ b/bottleneck/tests/data/test_713_B
@@ -0,0 +1,6 @@
+222 623
+527 1158
+784 1040
+597 1063
+456 525
+713 1476
diff --git a/bottleneck/tests/data/test_714_A b/bottleneck/tests/data/test_714_A
new file mode 100644
index 0000000..73ba892
--- /dev/null
+++ b/bottleneck/tests/data/test_714_A
@@ -0,0 +1,6 @@
+81 1045
+398 727
+668 1311
+788 1623
+363 1222
+630 757
diff --git a/bottleneck/tests/data/test_714_B b/bottleneck/tests/data/test_714_B
new file mode 100644
index 0000000..c495e7a
--- /dev/null
+++ b/bottleneck/tests/data/test_714_B
@@ -0,0 +1,6 @@
+840 1651
+664 995
+984 1812
+501 1183
+859 1373
+224 321
diff --git a/bottleneck/tests/data/test_715_A b/bottleneck/tests/data/test_715_A
new file mode 100644
index 0000000..70b698d
--- /dev/null
+++ b/bottleneck/tests/data/test_715_A
@@ -0,0 +1,6 @@
+390 400
+914 963
+118 182
+848 1799
+24 207
+310 917
diff --git a/bottleneck/tests/data/test_715_B b/bottleneck/tests/data/test_715_B
new file mode 100644
index 0000000..3cdf2b3
--- /dev/null
+++ b/bottleneck/tests/data/test_715_B
@@ -0,0 +1,6 @@
+999 1621
+121 432
+878 1064
+454 925
+642 1350
+976 1667
diff --git a/bottleneck/tests/data/test_716_A b/bottleneck/tests/data/test_716_A
new file mode 100644
index 0000000..ada9ac0
--- /dev/null
+++ b/bottleneck/tests/data/test_716_A
@@ -0,0 +1,6 @@
+838 1400
+274 999
+806 1428
+957 1203
+48 503
+600 754
diff --git a/bottleneck/tests/data/test_716_B b/bottleneck/tests/data/test_716_B
new file mode 100644
index 0000000..b13c8a1
--- /dev/null
+++ b/bottleneck/tests/data/test_716_B
@@ -0,0 +1,6 @@
+64 560
+385 907
+324 1041
+611 868
+685 1605
+320 733
diff --git a/bottleneck/tests/data/test_717_A b/bottleneck/tests/data/test_717_A
new file mode 100644
index 0000000..f23e351
--- /dev/null
+++ b/bottleneck/tests/data/test_717_A
@@ -0,0 +1,6 @@
+435 538
+281 369
+230 609
+932 1150
+629 1558
+397 511
diff --git a/bottleneck/tests/data/test_717_B b/bottleneck/tests/data/test_717_B
new file mode 100644
index 0000000..150f7ff
--- /dev/null
+++ b/bottleneck/tests/data/test_717_B
@@ -0,0 +1,6 @@
+293 1253
+356 1075
+559 754
+309 911
+726 1445
+539 1249
diff --git a/bottleneck/tests/data/test_718_A b/bottleneck/tests/data/test_718_A
new file mode 100644
index 0000000..6efc756
--- /dev/null
+++ b/bottleneck/tests/data/test_718_A
@@ -0,0 +1,6 @@
+289 455
+404 1182
+924 1629
+961 1779
+392 1078
+881 1571
diff --git a/bottleneck/tests/data/test_718_B b/bottleneck/tests/data/test_718_B
new file mode 100644
index 0000000..4e45db1
--- /dev/null
+++ b/bottleneck/tests/data/test_718_B
@@ -0,0 +1,6 @@
+666 983
+482 1016
+609 1498
+352 882
+92 384
+911 1898
diff --git a/bottleneck/tests/data/test_719_A b/bottleneck/tests/data/test_719_A
new file mode 100644
index 0000000..3512e1f
--- /dev/null
+++ b/bottleneck/tests/data/test_719_A
@@ -0,0 +1,6 @@
+589 1272
+999 1340
+628 1428
+112 311
+854 1288
+579 1034
diff --git a/bottleneck/tests/data/test_719_B b/bottleneck/tests/data/test_719_B
new file mode 100644
index 0000000..028f44a
--- /dev/null
+++ b/bottleneck/tests/data/test_719_B
@@ -0,0 +1,6 @@
+223 460
+798 1620
+582 901
+542 835
+309 851
+28 133
diff --git a/bottleneck/tests/data/test_720_A b/bottleneck/tests/data/test_720_A
new file mode 100644
index 0000000..57e2829
--- /dev/null
+++ b/bottleneck/tests/data/test_720_A
@@ -0,0 +1,7 @@
+842 955
+876 1162
+447 481
+217 1212
+392 731
+112 940
+462 796
diff --git a/bottleneck/tests/data/test_720_B b/bottleneck/tests/data/test_720_B
new file mode 100644
index 0000000..f3f2675
--- /dev/null
+++ b/bottleneck/tests/data/test_720_B
@@ -0,0 +1,7 @@
+768 1167
+970 1497
+720 809
+848 1278
+264 387
+443 673
+481 643
diff --git a/bottleneck/tests/data/test_721_A b/bottleneck/tests/data/test_721_A
new file mode 100644
index 0000000..f8a7f29
--- /dev/null
+++ b/bottleneck/tests/data/test_721_A
@@ -0,0 +1,7 @@
+712 1082
+573 1189
+468 579
+431 1140
+543 758
+852 1545
+707 1585
diff --git a/bottleneck/tests/data/test_721_B b/bottleneck/tests/data/test_721_B
new file mode 100644
index 0000000..35b828c
--- /dev/null
+++ b/bottleneck/tests/data/test_721_B
@@ -0,0 +1,7 @@
+274 999
+671 1640
+687 969
+641 796
+566 1384
+558 1386
+611 1189
diff --git a/bottleneck/tests/data/test_722_A b/bottleneck/tests/data/test_722_A
new file mode 100644
index 0000000..6e0719f
--- /dev/null
+++ b/bottleneck/tests/data/test_722_A
@@ -0,0 +1,7 @@
+292 783
+995 1371
+60 662
+506 531
+294 1245
+966 1027
+750 1180
diff --git a/bottleneck/tests/data/test_722_B b/bottleneck/tests/data/test_722_B
new file mode 100644
index 0000000..0fd37cc
--- /dev/null
+++ b/bottleneck/tests/data/test_722_B
@@ -0,0 +1,7 @@
+194 750
+520 773
+206 498
+746 1278
+354 643
+812 1219
+547 707
diff --git a/bottleneck/tests/data/test_723_A b/bottleneck/tests/data/test_723_A
new file mode 100644
index 0000000..ad94fdd
--- /dev/null
+++ b/bottleneck/tests/data/test_723_A
@@ -0,0 +1,7 @@
+44 715
+470 1287
+692 1635
+849 1409
+636 724
+108 255
+377 1253
diff --git a/bottleneck/tests/data/test_723_B b/bottleneck/tests/data/test_723_B
new file mode 100644
index 0000000..247a17e
--- /dev/null
+++ b/bottleneck/tests/data/test_723_B
@@ -0,0 +1,7 @@
+565 1129
+574 725
+387 1204
+990 1093
+548 1447
+547 1294
+394 421
diff --git a/bottleneck/tests/data/test_724_A b/bottleneck/tests/data/test_724_A
new file mode 100644
index 0000000..f9a6bcf
--- /dev/null
+++ b/bottleneck/tests/data/test_724_A
@@ -0,0 +1,7 @@
+121 963
+4 934
+471 1403
+78 700
+500 749
+577 1241
+961 1123
diff --git a/bottleneck/tests/data/test_724_B b/bottleneck/tests/data/test_724_B
new file mode 100644
index 0000000..71d03b3
--- /dev/null
+++ b/bottleneck/tests/data/test_724_B
@@ -0,0 +1,7 @@
+597 1424
+232 317
+618 1105
+593 1007
+410 1158
+534 965
+306 782
diff --git a/bottleneck/tests/data/test_725_A b/bottleneck/tests/data/test_725_A
new file mode 100644
index 0000000..1e20d9e
--- /dev/null
+++ b/bottleneck/tests/data/test_725_A
@@ -0,0 +1,7 @@
+365 431
+764 1023
+503 1251
+50 557
+899 930
+906 1266
+698 1582
diff --git a/bottleneck/tests/data/test_725_B b/bottleneck/tests/data/test_725_B
new file mode 100644
index 0000000..a215c1e
--- /dev/null
+++ b/bottleneck/tests/data/test_725_B
@@ -0,0 +1,7 @@
+591 1250
+643 1388
+429 1007
+953 1625
+604 1075
+486 1455
+999 1790
diff --git a/bottleneck/tests/data/test_726_A b/bottleneck/tests/data/test_726_A
new file mode 100644
index 0000000..dd9500a
--- /dev/null
+++ b/bottleneck/tests/data/test_726_A
@@ -0,0 +1,7 @@
+193 1032
+813 1060
+401 672
+819 1490
+913 993
+294 753
+107 807
diff --git a/bottleneck/tests/data/test_726_B b/bottleneck/tests/data/test_726_B
new file mode 100644
index 0000000..b3d3e50
--- /dev/null
+++ b/bottleneck/tests/data/test_726_B
@@ -0,0 +1,7 @@
+57 1011
+861 1503
+669 1185
+630 1360
+636 952
+524 526
+264 1129
diff --git a/bottleneck/tests/data/test_727_A b/bottleneck/tests/data/test_727_A
new file mode 100644
index 0000000..dae9ff3
--- /dev/null
+++ b/bottleneck/tests/data/test_727_A
@@ -0,0 +1,7 @@
+268 505
+525 1512
+131 265
+534 1402
+810 1044
+474 933
+752 1495
diff --git a/bottleneck/tests/data/test_727_B b/bottleneck/tests/data/test_727_B
new file mode 100644
index 0000000..551d523
--- /dev/null
+++ b/bottleneck/tests/data/test_727_B
@@ -0,0 +1,7 @@
+366 1348
+38 470
+594 1547
+97 353
+417 626
+791 1472
+493 1262
diff --git a/bottleneck/tests/data/test_728_A b/bottleneck/tests/data/test_728_A
new file mode 100644
index 0000000..8074ce8
--- /dev/null
+++ b/bottleneck/tests/data/test_728_A
@@ -0,0 +1,7 @@
+798 958
+59 406
+670 868
+533 789
+192 727
+52 109
+997 1981
diff --git a/bottleneck/tests/data/test_728_B b/bottleneck/tests/data/test_728_B
new file mode 100644
index 0000000..6d1448a
--- /dev/null
+++ b/bottleneck/tests/data/test_728_B
@@ -0,0 +1,7 @@
+211 624
+198 1095
+150 530
+757 1274
+672 1255
+847 1476
+879 1407
diff --git a/bottleneck/tests/data/test_729_A b/bottleneck/tests/data/test_729_A
new file mode 100644
index 0000000..f9de136
--- /dev/null
+++ b/bottleneck/tests/data/test_729_A
@@ -0,0 +1,7 @@
+574 1387
+241 543
+338 345
+888 1183
+942 1193
+5 802
+357 510
diff --git a/bottleneck/tests/data/test_729_B b/bottleneck/tests/data/test_729_B
new file mode 100644
index 0000000..d34621f
--- /dev/null
+++ b/bottleneck/tests/data/test_729_B
@@ -0,0 +1,7 @@
+878 1129
+669 805
+56 973
+201 756
+911 1352
+494 887
+161 541
diff --git a/bottleneck/tests/data/test_730_A b/bottleneck/tests/data/test_730_A
new file mode 100644
index 0000000..433cbd8
--- /dev/null
+++ b/bottleneck/tests/data/test_730_A
@@ -0,0 +1,7 @@
+135 1110
+126 417
+647 964
+895 1124
+213 1115
+340 755
+154 605
diff --git a/bottleneck/tests/data/test_730_B b/bottleneck/tests/data/test_730_B
new file mode 100644
index 0000000..1b46964
--- /dev/null
+++ b/bottleneck/tests/data/test_730_B
@@ -0,0 +1,7 @@
+854 866
+212 1211
+180 272
+386 1292
+47 565
+916 1350
+906 912
diff --git a/bottleneck/tests/data/test_731_A b/bottleneck/tests/data/test_731_A
new file mode 100644
index 0000000..38d42cd
--- /dev/null
+++ b/bottleneck/tests/data/test_731_A
@@ -0,0 +1,7 @@
+1000 1606
+332 982
+581 1398
+403 1237
+954 1071
+560 890
+980 1624
diff --git a/bottleneck/tests/data/test_731_B b/bottleneck/tests/data/test_731_B
new file mode 100644
index 0000000..3017d7a
--- /dev/null
+++ b/bottleneck/tests/data/test_731_B
@@ -0,0 +1,7 @@
+171 558
+391 1367
+177 1159
+130 343
+914 1175
+774 835
+672 1301
diff --git a/bottleneck/tests/data/test_732_A b/bottleneck/tests/data/test_732_A
new file mode 100644
index 0000000..75a48cf
--- /dev/null
+++ b/bottleneck/tests/data/test_732_A
@@ -0,0 +1,7 @@
+330 1018
+692 1639
+213 1060
+138 458
+356 1233
+976 1361
+117 365
diff --git a/bottleneck/tests/data/test_732_B b/bottleneck/tests/data/test_732_B
new file mode 100644
index 0000000..fada3b9
--- /dev/null
+++ b/bottleneck/tests/data/test_732_B
@@ -0,0 +1,7 @@
+530 729
+842 926
+375 633
+364 987
+507 1398
+303 1096
+137 344
diff --git a/bottleneck/tests/data/test_733_A b/bottleneck/tests/data/test_733_A
new file mode 100644
index 0000000..d97ae0b
--- /dev/null
+++ b/bottleneck/tests/data/test_733_A
@@ -0,0 +1,7 @@
+155 290
+712 904
+154 668
+518 1267
+224 1022
+997 1304
+551 1015
diff --git a/bottleneck/tests/data/test_733_B b/bottleneck/tests/data/test_733_B
new file mode 100644
index 0000000..529c7de
--- /dev/null
+++ b/bottleneck/tests/data/test_733_B
@@ -0,0 +1,7 @@
+930 1406
+626 980
+541 1340
+129 1023
+407 615
+105 850
+688 756
diff --git a/bottleneck/tests/data/test_734_A b/bottleneck/tests/data/test_734_A
new file mode 100644
index 0000000..9aec4b4
--- /dev/null
+++ b/bottleneck/tests/data/test_734_A
@@ -0,0 +1,7 @@
+296 1160
+3 574
+642 808
+844 1148
+982 1081
+236 634
+151 904
diff --git a/bottleneck/tests/data/test_734_B b/bottleneck/tests/data/test_734_B
new file mode 100644
index 0000000..4cb7206
--- /dev/null
+++ b/bottleneck/tests/data/test_734_B
@@ -0,0 +1,7 @@
+30 884
+13 769
+406 954
+794 1615
+976 1177
+631 816
+400 1099
diff --git a/bottleneck/tests/data/test_735_A b/bottleneck/tests/data/test_735_A
new file mode 100644
index 0000000..f364a21
--- /dev/null
+++ b/bottleneck/tests/data/test_735_A
@@ -0,0 +1,7 @@
+259 941
+218 975
+286 718
+70 401
+496 830
+220 362
+511 1270
diff --git a/bottleneck/tests/data/test_735_B b/bottleneck/tests/data/test_735_B
new file mode 100644
index 0000000..0f93850
--- /dev/null
+++ b/bottleneck/tests/data/test_735_B
@@ -0,0 +1,7 @@
+489 705
+467 962
+110 116
+817 1521
+571 1059
+426 584
+933 1307
diff --git a/bottleneck/tests/data/test_736_A b/bottleneck/tests/data/test_736_A
new file mode 100644
index 0000000..d89c563
--- /dev/null
+++ b/bottleneck/tests/data/test_736_A
@@ -0,0 +1,7 @@
+624 1466
+288 1004
+552 978
+710 1190
+796 1634
+322 800
+171 197
diff --git a/bottleneck/tests/data/test_736_B b/bottleneck/tests/data/test_736_B
new file mode 100644
index 0000000..25427f3
--- /dev/null
+++ b/bottleneck/tests/data/test_736_B
@@ -0,0 +1,7 @@
+385 852
+110 431
+284 646
+803 1541
+436 821
+262 951
+470 1172
diff --git a/bottleneck/tests/data/test_737_A b/bottleneck/tests/data/test_737_A
new file mode 100644
index 0000000..2fbdf41
--- /dev/null
+++ b/bottleneck/tests/data/test_737_A
@@ -0,0 +1,7 @@
+340 942
+812 1103
+129 553
+729 781
+779 1100
+99 1059
+720 1532
diff --git a/bottleneck/tests/data/test_737_B b/bottleneck/tests/data/test_737_B
new file mode 100644
index 0000000..42348d5
--- /dev/null
+++ b/bottleneck/tests/data/test_737_B
@@ -0,0 +1,7 @@
+677 1323
+268 916
+165 674
+594 689
+975 1246
+717 734
+877 1479
diff --git a/bottleneck/tests/data/test_738_A b/bottleneck/tests/data/test_738_A
new file mode 100644
index 0000000..d56b09b
--- /dev/null
+++ b/bottleneck/tests/data/test_738_A
@@ -0,0 +1,7 @@
+367 725
+277 1154
+267 994
+780 1005
+293 530
+964 1682
+421 734
diff --git a/bottleneck/tests/data/test_738_B b/bottleneck/tests/data/test_738_B
new file mode 100644
index 0000000..834b2cf
--- /dev/null
+++ b/bottleneck/tests/data/test_738_B
@@ -0,0 +1,7 @@
+661 1499
+920 1597
+528 958
+482 957
+143 757
+547 1079
+774 937
diff --git a/bottleneck/tests/data/test_739_A b/bottleneck/tests/data/test_739_A
new file mode 100644
index 0000000..84cbd7c
--- /dev/null
+++ b/bottleneck/tests/data/test_739_A
@@ -0,0 +1,7 @@
+414 1244
+395 937
+504 1155
+711 1389
+302 859
+220 731
+725 962
diff --git a/bottleneck/tests/data/test_739_B b/bottleneck/tests/data/test_739_B
new file mode 100644
index 0000000..85afe3e
--- /dev/null
+++ b/bottleneck/tests/data/test_739_B
@@ -0,0 +1,7 @@
+598 980
+50 441
+473 1160
+524 1273
+523 1060
+936 1295
+73 910
diff --git a/bottleneck/tests/data/test_740_A b/bottleneck/tests/data/test_740_A
new file mode 100644
index 0000000..a99113a
--- /dev/null
+++ b/bottleneck/tests/data/test_740_A
@@ -0,0 +1,8 @@
+569 1119
+905 1475
+608 1595
+469 1334
+501 1299
+306 797
+802 1036
+155 379
diff --git a/bottleneck/tests/data/test_740_B b/bottleneck/tests/data/test_740_B
new file mode 100644
index 0000000..5aac504
--- /dev/null
+++ b/bottleneck/tests/data/test_740_B
@@ -0,0 +1,8 @@
+729 946
+190 1105
+541 1315
+719 1537
+319 1219
+269 468
+638 838
+51 440
diff --git a/bottleneck/tests/data/test_741_A b/bottleneck/tests/data/test_741_A
new file mode 100644
index 0000000..7c3f3fc
--- /dev/null
+++ b/bottleneck/tests/data/test_741_A
@@ -0,0 +1,8 @@
+897 1868
+872 1752
+739 1445
+156 178
+256 714
+198 528
+595 1485
+873 1452
diff --git a/bottleneck/tests/data/test_741_B b/bottleneck/tests/data/test_741_B
new file mode 100644
index 0000000..9f8d386
--- /dev/null
+++ b/bottleneck/tests/data/test_741_B
@@ -0,0 +1,8 @@
+193 277
+309 1030
+263 1230
+824 1414
+191 1103
+42 165
+665 690
+414 742
diff --git a/bottleneck/tests/data/test_742_A b/bottleneck/tests/data/test_742_A
new file mode 100644
index 0000000..9effd4c
--- /dev/null
+++ b/bottleneck/tests/data/test_742_A
@@ -0,0 +1,8 @@
+268 974
+345 812
+75 359
+178 827
+647 1213
+667 677
+400 521
+703 1302
diff --git a/bottleneck/tests/data/test_742_B b/bottleneck/tests/data/test_742_B
new file mode 100644
index 0000000..f17965b
--- /dev/null
+++ b/bottleneck/tests/data/test_742_B
@@ -0,0 +1,8 @@
+577 1161
+635 1057
+395 684
+225 312
+194 475
+550 732
+892 1097
+494 987
diff --git a/bottleneck/tests/data/test_743_A b/bottleneck/tests/data/test_743_A
new file mode 100644
index 0000000..3a40cfb
--- /dev/null
+++ b/bottleneck/tests/data/test_743_A
@@ -0,0 +1,8 @@
+593 1306
+117 664
+701 1073
+918 1452
+125 1012
+80 106
+26 904
+525 1251
diff --git a/bottleneck/tests/data/test_743_B b/bottleneck/tests/data/test_743_B
new file mode 100644
index 0000000..482d6dd
--- /dev/null
+++ b/bottleneck/tests/data/test_743_B
@@ -0,0 +1,8 @@
+913 1090
+957 1355
+465 559
+490 1102
+957 1559
+535 805
+569 1211
+8 570
diff --git a/bottleneck/tests/data/test_744_A b/bottleneck/tests/data/test_744_A
new file mode 100644
index 0000000..25c3e55
--- /dev/null
+++ b/bottleneck/tests/data/test_744_A
@@ -0,0 +1,8 @@
+648 773
+599 1278
+940 1503
+127 461
+923 1912
+724 939
+609 633
+720 936
diff --git a/bottleneck/tests/data/test_744_B b/bottleneck/tests/data/test_744_B
new file mode 100644
index 0000000..da30f30
--- /dev/null
+++ b/bottleneck/tests/data/test_744_B
@@ -0,0 +1,8 @@
+102 119
+262 460
+568 825
+855 1517
+622 1062
+441 607
+183 1095
+446 1422
diff --git a/bottleneck/tests/data/test_745_A b/bottleneck/tests/data/test_745_A
new file mode 100644
index 0000000..f8ef7e6
--- /dev/null
+++ b/bottleneck/tests/data/test_745_A
@@ -0,0 +1,8 @@
+34 614
+939 1749
+639 698
+16 851
+847 1299
+760 1345
+477 682
+931 1291
diff --git a/bottleneck/tests/data/test_745_B b/bottleneck/tests/data/test_745_B
new file mode 100644
index 0000000..f6d32b5
--- /dev/null
+++ b/bottleneck/tests/data/test_745_B
@@ -0,0 +1,8 @@
+972 1016
+16 293
+116 641
+230 1015
+164 468
+557 700
+1 477
+437 739
diff --git a/bottleneck/tests/data/test_746_A b/bottleneck/tests/data/test_746_A
new file mode 100644
index 0000000..dbd677e
--- /dev/null
+++ b/bottleneck/tests/data/test_746_A
@@ -0,0 +1,8 @@
+651 1348
+225 349
+382 755
+986 1090
+601 856
+349 1261
+667 1644
+637 1197
diff --git a/bottleneck/tests/data/test_746_B b/bottleneck/tests/data/test_746_B
new file mode 100644
index 0000000..9d02f4b
--- /dev/null
+++ b/bottleneck/tests/data/test_746_B
@@ -0,0 +1,8 @@
+804 1762
+13 403
+615 1487
+810 899
+939 1026
+59 539
+258 803
+199 488
diff --git a/bottleneck/tests/data/test_747_A b/bottleneck/tests/data/test_747_A
new file mode 100644
index 0000000..c7886f8
--- /dev/null
+++ b/bottleneck/tests/data/test_747_A
@@ -0,0 +1,8 @@
+810 1169
+599 1295
+34 243
+41 247
+828 1689
+884 1265
+57 122
+340 1041
diff --git a/bottleneck/tests/data/test_747_B b/bottleneck/tests/data/test_747_B
new file mode 100644
index 0000000..1ca1b5e
--- /dev/null
+++ b/bottleneck/tests/data/test_747_B
@@ -0,0 +1,8 @@
+282 836
+663 822
+874 1239
+911 1439
+704 1085
+593 787
+125 683
+790 1041
diff --git a/bottleneck/tests/data/test_748_A b/bottleneck/tests/data/test_748_A
new file mode 100644
index 0000000..5fe22c2
--- /dev/null
+++ b/bottleneck/tests/data/test_748_A
@@ -0,0 +1,8 @@
+713 1382
+941 1859
+531 1460
+239 703
+4 712
+381 1018
+492 1298
+142 765
diff --git a/bottleneck/tests/data/test_748_B b/bottleneck/tests/data/test_748_B
new file mode 100644
index 0000000..2e69002
--- /dev/null
+++ b/bottleneck/tests/data/test_748_B
@@ -0,0 +1,8 @@
+993 1036
+886 1574
+892 1880
+649 1474
+228 1041
+124 730
+197 360
+490 1447
diff --git a/bottleneck/tests/data/test_749_A b/bottleneck/tests/data/test_749_A
new file mode 100644
index 0000000..b3bf068
--- /dev/null
+++ b/bottleneck/tests/data/test_749_A
@@ -0,0 +1,8 @@
+233 929
+150 391
+761 1353
+402 872
+890 1624
+103 482
+855 1150
+173 190
diff --git a/bottleneck/tests/data/test_749_B b/bottleneck/tests/data/test_749_B
new file mode 100644
index 0000000..b181d57
--- /dev/null
+++ b/bottleneck/tests/data/test_749_B
@@ -0,0 +1,8 @@
+304 960
+633 956
+62 250
+678 1085
+582 1509
+267 1159
+555 872
+828 935
diff --git a/bottleneck/tests/data/test_750_A b/bottleneck/tests/data/test_750_A
new file mode 100644
index 0000000..3bd3e77
--- /dev/null
+++ b/bottleneck/tests/data/test_750_A
@@ -0,0 +1,8 @@
+46 814
+299 740
+422 505
+597 674
+626 882
+550 1384
+257 522
+191 537
diff --git a/bottleneck/tests/data/test_750_B b/bottleneck/tests/data/test_750_B
new file mode 100644
index 0000000..837ed3d
--- /dev/null
+++ b/bottleneck/tests/data/test_750_B
@@ -0,0 +1,8 @@
+119 1069
+304 1151
+984 1304
+938 1017
+915 1414
+603 1419
+806 1391
+247 563
diff --git a/bottleneck/tests/data/test_751_A b/bottleneck/tests/data/test_751_A
new file mode 100644
index 0000000..adb0fe7
--- /dev/null
+++ b/bottleneck/tests/data/test_751_A
@@ -0,0 +1,8 @@
+161 749
+884 1266
+52 256
+626 1062
+244 1161
+52 651
+429 513
+123 381
diff --git a/bottleneck/tests/data/test_751_B b/bottleneck/tests/data/test_751_B
new file mode 100644
index 0000000..1ed1651
--- /dev/null
+++ b/bottleneck/tests/data/test_751_B
@@ -0,0 +1,8 @@
+646 1122
+980 1686
+3 270
+410 1255
+5 817
+9 390
+601 1013
+786 1675
diff --git a/bottleneck/tests/data/test_752_A b/bottleneck/tests/data/test_752_A
new file mode 100644
index 0000000..4b54da2
--- /dev/null
+++ b/bottleneck/tests/data/test_752_A
@@ -0,0 +1,8 @@
+941 1425
+272 829
+904 1623
+562 1306
+223 245
+534 1385
+903 1274
+531 629
diff --git a/bottleneck/tests/data/test_752_B b/bottleneck/tests/data/test_752_B
new file mode 100644
index 0000000..9c05ec9
--- /dev/null
+++ b/bottleneck/tests/data/test_752_B
@@ -0,0 +1,8 @@
+514 1333
+981 1676
+949 1493
+952 1015
+572 1224
+131 835
+93 335
+306 906
diff --git a/bottleneck/tests/data/test_753_A b/bottleneck/tests/data/test_753_A
new file mode 100644
index 0000000..5704668
--- /dev/null
+++ b/bottleneck/tests/data/test_753_A
@@ -0,0 +1,8 @@
+405 996
+473 1330
+168 804
+516 578
+712 1449
+425 1336
+237 816
+625 1304
diff --git a/bottleneck/tests/data/test_753_B b/bottleneck/tests/data/test_753_B
new file mode 100644
index 0000000..1e845f7
--- /dev/null
+++ b/bottleneck/tests/data/test_753_B
@@ -0,0 +1,8 @@
+291 1031
+70 332
+847 973
+311 398
+815 1512
+996 1375
+720 1388
+518 611
diff --git a/bottleneck/tests/data/test_754_A b/bottleneck/tests/data/test_754_A
new file mode 100644
index 0000000..1957784
--- /dev/null
+++ b/bottleneck/tests/data/test_754_A
@@ -0,0 +1,8 @@
+138 781
+992 1803
+189 1157
+546 1145
+461 1153
+634 1004
+152 947
+706 713
diff --git a/bottleneck/tests/data/test_754_B b/bottleneck/tests/data/test_754_B
new file mode 100644
index 0000000..4463862
--- /dev/null
+++ b/bottleneck/tests/data/test_754_B
@@ -0,0 +1,8 @@
+742 1152
+909 947
+350 1168
+240 769
+415 479
+752 1507
+356 902
+856 1356
diff --git a/bottleneck/tests/data/test_755_A b/bottleneck/tests/data/test_755_A
new file mode 100644
index 0000000..d05546d
--- /dev/null
+++ b/bottleneck/tests/data/test_755_A
@@ -0,0 +1,8 @@
+163 1000
+403 624
+628 829
+458 854
+319 778
+180 856
+822 1028
+806 923
diff --git a/bottleneck/tests/data/test_755_B b/bottleneck/tests/data/test_755_B
new file mode 100644
index 0000000..47b372a
--- /dev/null
+++ b/bottleneck/tests/data/test_755_B
@@ -0,0 +1,8 @@
+922 1134
+900 1378
+200 780
+184 815
+631 1014
+837 1762
+676 789
+298 486
diff --git a/bottleneck/tests/data/test_756_A b/bottleneck/tests/data/test_756_A
new file mode 100644
index 0000000..bac3296
--- /dev/null
+++ b/bottleneck/tests/data/test_756_A
@@ -0,0 +1,8 @@
+467 1356
+84 188
+215 968
+702 1035
+305 745
+171 880
+724 1223
+916 1487
diff --git a/bottleneck/tests/data/test_756_B b/bottleneck/tests/data/test_756_B
new file mode 100644
index 0000000..0579dd8
--- /dev/null
+++ b/bottleneck/tests/data/test_756_B
@@ -0,0 +1,8 @@
+62 816
+781 1333
+496 1018
+211 657
+968 1779
+684 828
+707 816
+133 710
diff --git a/bottleneck/tests/data/test_757_A b/bottleneck/tests/data/test_757_A
new file mode 100644
index 0000000..3d0e16e
--- /dev/null
+++ b/bottleneck/tests/data/test_757_A
@@ -0,0 +1,8 @@
+850 1310
+104 459
+439 1185
+320 454
+423 1247
+85 891
+899 1560
+114 246
diff --git a/bottleneck/tests/data/test_757_B b/bottleneck/tests/data/test_757_B
new file mode 100644
index 0000000..7ccedc5
--- /dev/null
+++ b/bottleneck/tests/data/test_757_B
@@ -0,0 +1,8 @@
+797 1761
+642 812
+919 1333
+446 703
+330 1069
+575 668
+735 1258
+723 1330
diff --git a/bottleneck/tests/data/test_758_A b/bottleneck/tests/data/test_758_A
new file mode 100644
index 0000000..fdabcdd
--- /dev/null
+++ b/bottleneck/tests/data/test_758_A
@@ -0,0 +1,8 @@
+310 820
+65 766
+892 1802
+459 1216
+237 358
+371 419
+218 375
+27 127
diff --git a/bottleneck/tests/data/test_758_B b/bottleneck/tests/data/test_758_B
new file mode 100644
index 0000000..4fb7f60
--- /dev/null
+++ b/bottleneck/tests/data/test_758_B
@@ -0,0 +1,8 @@
+261 318
+423 669
+485 1330
+814 942
+276 1013
+914 1010
+893 1161
+559 1118
diff --git a/bottleneck/tests/data/test_759_A b/bottleneck/tests/data/test_759_A
new file mode 100644
index 0000000..dcf3a28
--- /dev/null
+++ b/bottleneck/tests/data/test_759_A
@@ -0,0 +1,8 @@
+235 1080
+801 1281
+406 1012
+157 1091
+394 1385
+217 791
+971 1930
+529 1401
diff --git a/bottleneck/tests/data/test_759_B b/bottleneck/tests/data/test_759_B
new file mode 100644
index 0000000..e094e35
--- /dev/null
+++ b/bottleneck/tests/data/test_759_B
@@ -0,0 +1,8 @@
+957 1887
+857 1225
+366 386
+678 1429
+828 876
+250 466
+506 1127
+791 946
diff --git a/bottleneck/tests/data/test_760_A b/bottleneck/tests/data/test_760_A
new file mode 100644
index 0000000..38e77f3
--- /dev/null
+++ b/bottleneck/tests/data/test_760_A
@@ -0,0 +1,9 @@
+754 1750
+559 782
+889 1821
+897 1093
+380 764
+367 932
+854 1721
+815 1633
+803 939
diff --git a/bottleneck/tests/data/test_760_B b/bottleneck/tests/data/test_760_B
new file mode 100644
index 0000000..1bb3547
--- /dev/null
+++ b/bottleneck/tests/data/test_760_B
@@ -0,0 +1,9 @@
+895 1474
+904 1893
+474 832
+238 631
+82 583
+470 797
+461 903
+856 1006
+151 669
diff --git a/bottleneck/tests/data/test_761_A b/bottleneck/tests/data/test_761_A
new file mode 100644
index 0000000..4690752
--- /dev/null
+++ b/bottleneck/tests/data/test_761_A
@@ -0,0 +1,9 @@
+377 1284
+139 699
+50 438
+687 919
+35 957
+652 713
+272 1264
+788 1721
+656 1330
diff --git a/bottleneck/tests/data/test_761_B b/bottleneck/tests/data/test_761_B
new file mode 100644
index 0000000..9978d2c
--- /dev/null
+++ b/bottleneck/tests/data/test_761_B
@@ -0,0 +1,9 @@
+670 860
+401 500
+127 995
+594 1023
+638 1052
+727 802
+766 1624
+261 880
+172 663
diff --git a/bottleneck/tests/data/test_762_A b/bottleneck/tests/data/test_762_A
new file mode 100644
index 0000000..7918ab6
--- /dev/null
+++ b/bottleneck/tests/data/test_762_A
@@ -0,0 +1,9 @@
+457 1270
+23 803
+189 293
+113 500
+911 1041
+504 728
+105 492
+514 1222
+753 923
diff --git a/bottleneck/tests/data/test_762_B b/bottleneck/tests/data/test_762_B
new file mode 100644
index 0000000..d36f033
--- /dev/null
+++ b/bottleneck/tests/data/test_762_B
@@ -0,0 +1,9 @@
+393 565
+182 184
+852 1821
+702 1558
+157 245
+456 924
+640 1103
+934 1125
+979 1099
diff --git a/bottleneck/tests/data/test_763_A b/bottleneck/tests/data/test_763_A
new file mode 100644
index 0000000..73d90de
--- /dev/null
+++ b/bottleneck/tests/data/test_763_A
@@ -0,0 +1,9 @@
+89 776
+785 1157
+846 1324
+854 1048
+968 1721
+653 1216
+707 718
+958 1397
+247 1245
diff --git a/bottleneck/tests/data/test_763_B b/bottleneck/tests/data/test_763_B
new file mode 100644
index 0000000..09d159c
--- /dev/null
+++ b/bottleneck/tests/data/test_763_B
@@ -0,0 +1,9 @@
+730 1315
+831 1373
+669 1287
+125 500
+676 1262
+272 524
+173 651
+38 624
+514 1175
diff --git a/bottleneck/tests/data/test_764_A b/bottleneck/tests/data/test_764_A
new file mode 100644
index 0000000..8dead93
--- /dev/null
+++ b/bottleneck/tests/data/test_764_A
@@ -0,0 +1,9 @@
+104 150
+837 890
+975 1135
+650 697
+202 393
+972 1174
+619 969
+274 891
+16 366
diff --git a/bottleneck/tests/data/test_764_B b/bottleneck/tests/data/test_764_B
new file mode 100644
index 0000000..014198d
--- /dev/null
+++ b/bottleneck/tests/data/test_764_B
@@ -0,0 +1,9 @@
+150 432
+45 234
+8 95
+31 712
+331 1329
+184 531
+44 922
+764 1746
+838 919
diff --git a/bottleneck/tests/data/test_765_A b/bottleneck/tests/data/test_765_A
new file mode 100644
index 0000000..666d2fe
--- /dev/null
+++ b/bottleneck/tests/data/test_765_A
@@ -0,0 +1,9 @@
+105 587
+505 1209
+617 651
+120 670
+322 1268
+410 1307
+822 1420
+351 1226
+150 633
diff --git a/bottleneck/tests/data/test_765_B b/bottleneck/tests/data/test_765_B
new file mode 100644
index 0000000..c0be6d4
--- /dev/null
+++ b/bottleneck/tests/data/test_765_B
@@ -0,0 +1,9 @@
+274 1006
+627 1237
+21 246
+785 1167
+929 1234
+462 904
+539 997
+453 592
+251 513
diff --git a/bottleneck/tests/data/test_766_A b/bottleneck/tests/data/test_766_A
new file mode 100644
index 0000000..48d55d9
--- /dev/null
+++ b/bottleneck/tests/data/test_766_A
@@ -0,0 +1,9 @@
+49 532
+799 1331
+372 667
+852 1746
+400 834
+182 499
+889 1775
+831 867
+139 227
diff --git a/bottleneck/tests/data/test_766_B b/bottleneck/tests/data/test_766_B
new file mode 100644
index 0000000..9943c61
--- /dev/null
+++ b/bottleneck/tests/data/test_766_B
@@ -0,0 +1,9 @@
+976 1516
+153 908
+103 143
+105 439
+469 744
+981 1387
+267 319
+960 1495
+734 1370
diff --git a/bottleneck/tests/data/test_767_A b/bottleneck/tests/data/test_767_A
new file mode 100644
index 0000000..badb767
--- /dev/null
+++ b/bottleneck/tests/data/test_767_A
@@ -0,0 +1,9 @@
+244 622
+925 1530
+263 455
+189 991
+342 1273
+266 321
+544 962
+613 1019
+592 791
diff --git a/bottleneck/tests/data/test_767_B b/bottleneck/tests/data/test_767_B
new file mode 100644
index 0000000..3eb4c39
--- /dev/null
+++ b/bottleneck/tests/data/test_767_B
@@ -0,0 +1,9 @@
+928 1479
+80 1065
+382 1056
+679 880
+307 891
+685 1466
+278 806
+501 1479
+126 271
diff --git a/bottleneck/tests/data/test_768_A b/bottleneck/tests/data/test_768_A
new file mode 100644
index 0000000..69b6425
--- /dev/null
+++ b/bottleneck/tests/data/test_768_A
@@ -0,0 +1,9 @@
+674 1590
+745 1289
+854 1215
+412 627
+538 992
+135 1053
+385 594
+354 569
+702 1010
diff --git a/bottleneck/tests/data/test_768_B b/bottleneck/tests/data/test_768_B
new file mode 100644
index 0000000..a0e8eb0
--- /dev/null
+++ b/bottleneck/tests/data/test_768_B
@@ -0,0 +1,9 @@
+735 1627
+423 514
+524 1236
+377 412
+372 415
+873 1835
+719 1488
+828 1361
+160 705
diff --git a/bottleneck/tests/data/test_769_A b/bottleneck/tests/data/test_769_A
new file mode 100644
index 0000000..08a46bd
--- /dev/null
+++ b/bottleneck/tests/data/test_769_A
@@ -0,0 +1,9 @@
+930 1077
+466 1159
+305 866
+672 1003
+970 1824
+774 1212
+454 611
+702 944
+979 1136
diff --git a/bottleneck/tests/data/test_769_B b/bottleneck/tests/data/test_769_B
new file mode 100644
index 0000000..ce18190
--- /dev/null
+++ b/bottleneck/tests/data/test_769_B
@@ -0,0 +1,9 @@
+293 996
+973 1865
+346 753
+897 1337
+58 1055
+35 647
+892 1158
+59 174
+342 1131
diff --git a/bottleneck/tests/data/test_770_A b/bottleneck/tests/data/test_770_A
new file mode 100644
index 0000000..edfdf26
--- /dev/null
+++ b/bottleneck/tests/data/test_770_A
@@ -0,0 +1,9 @@
+61 130
+770 1196
+740 778
+985 1720
+131 208
+740 1516
+798 1185
+609 1141
+159 389
diff --git a/bottleneck/tests/data/test_770_B b/bottleneck/tests/data/test_770_B
new file mode 100644
index 0000000..cd59228
--- /dev/null
+++ b/bottleneck/tests/data/test_770_B
@@ -0,0 +1,9 @@
+815 1216
+229 652
+696 1309
+585 1011
+882 1621
+398 670
+931 1271
+988 1333
+197 1110
diff --git a/bottleneck/tests/data/test_771_A b/bottleneck/tests/data/test_771_A
new file mode 100644
index 0000000..9c3f4ba
--- /dev/null
+++ b/bottleneck/tests/data/test_771_A
@@ -0,0 +1,9 @@
+186 373
+378 642
+448 1022
+866 911
+706 1637
+528 950
+150 216
+327 506
+898 1366
diff --git a/bottleneck/tests/data/test_771_B b/bottleneck/tests/data/test_771_B
new file mode 100644
index 0000000..8c07a06
--- /dev/null
+++ b/bottleneck/tests/data/test_771_B
@@ -0,0 +1,9 @@
+968 1807
+686 1584
+296 347
+695 1143
+614 1205
+310 502
+249 694
+420 457
+743 1113
diff --git a/bottleneck/tests/data/test_772_A b/bottleneck/tests/data/test_772_A
new file mode 100644
index 0000000..034ed92
--- /dev/null
+++ b/bottleneck/tests/data/test_772_A
@@ -0,0 +1,9 @@
+286 399
+38 700
+884 1344
+201 1085
+285 1278
+661 901
+921 966
+3 728
+237 982
diff --git a/bottleneck/tests/data/test_772_B b/bottleneck/tests/data/test_772_B
new file mode 100644
index 0000000..bc29bff
--- /dev/null
+++ b/bottleneck/tests/data/test_772_B
@@ -0,0 +1,9 @@
+148 440
+806 1799
+886 1586
+363 1211
+316 683
+229 766
+839 1204
+245 685
+43 841
diff --git a/bottleneck/tests/data/test_773_A b/bottleneck/tests/data/test_773_A
new file mode 100644
index 0000000..0601e04
--- /dev/null
+++ b/bottleneck/tests/data/test_773_A
@@ -0,0 +1,9 @@
+796 1034
+635 1409
+52 141
+974 1000
+341 800
+727 820
+343 1278
+138 153
+446 823
diff --git a/bottleneck/tests/data/test_773_B b/bottleneck/tests/data/test_773_B
new file mode 100644
index 0000000..004d2d6
--- /dev/null
+++ b/bottleneck/tests/data/test_773_B
@@ -0,0 +1,9 @@
+327 384
+214 341
+815 1156
+868 1138
+369 392
+351 1162
+829 1594
+618 783
+47 656
diff --git a/bottleneck/tests/data/test_774_A b/bottleneck/tests/data/test_774_A
new file mode 100644
index 0000000..3e211a0
--- /dev/null
+++ b/bottleneck/tests/data/test_774_A
@@ -0,0 +1,9 @@
+833 1408
+738 1321
+731 825
+670 795
+458 1062
+777 1262
+719 1131
+979 1366
+350 1290
diff --git a/bottleneck/tests/data/test_774_B b/bottleneck/tests/data/test_774_B
new file mode 100644
index 0000000..3cf3985
--- /dev/null
+++ b/bottleneck/tests/data/test_774_B
@@ -0,0 +1,9 @@
+421 1393
+851 1666
+633 1458
+560 1168
+936 1833
+855 1548
+275 1067
+899 1767
+539 947
diff --git a/bottleneck/tests/data/test_775_A b/bottleneck/tests/data/test_775_A
new file mode 100644
index 0000000..5676eb4
--- /dev/null
+++ b/bottleneck/tests/data/test_775_A
@@ -0,0 +1,9 @@
+210 651
+529 1257
+998 1304
+957 1816
+624 800
+200 460
+319 1051
+422 962
+642 1439
diff --git a/bottleneck/tests/data/test_775_B b/bottleneck/tests/data/test_775_B
new file mode 100644
index 0000000..5c4e8bc
--- /dev/null
+++ b/bottleneck/tests/data/test_775_B
@@ -0,0 +1,9 @@
+652 1315
+419 981
+912 1832
+578 1215
+317 992
+785 1422
+528 664
+968 1344
+847 993
diff --git a/bottleneck/tests/data/test_776_A b/bottleneck/tests/data/test_776_A
new file mode 100644
index 0000000..49370ff
--- /dev/null
+++ b/bottleneck/tests/data/test_776_A
@@ -0,0 +1,9 @@
+707 768
+983 1893
+386 786
+370 914
+45 501
+625 1184
+175 1073
+262 1227
+819 1257
diff --git a/bottleneck/tests/data/test_776_B b/bottleneck/tests/data/test_776_B
new file mode 100644
index 0000000..575a2d9
--- /dev/null
+++ b/bottleneck/tests/data/test_776_B
@@ -0,0 +1,9 @@
+949 1560
+757 1176
+689 1184
+819 1333
+50 884
+872 1695
+992 1145
+909 1889
+516 1376
diff --git a/bottleneck/tests/data/test_777_A b/bottleneck/tests/data/test_777_A
new file mode 100644
index 0000000..eb1c980
--- /dev/null
+++ b/bottleneck/tests/data/test_777_A
@@ -0,0 +1,9 @@
+958 1247
+143 570
+463 1343
+347 1346
+640 1203
+923 964
+489 701
+712 837
+616 978
diff --git a/bottleneck/tests/data/test_777_B b/bottleneck/tests/data/test_777_B
new file mode 100644
index 0000000..eb9c8ee
--- /dev/null
+++ b/bottleneck/tests/data/test_777_B
@@ -0,0 +1,9 @@
+781 1080
+494 1278
+123 159
+936 1305
+748 1302
+271 524
+37 953
+758 946
+182 670
diff --git a/bottleneck/tests/data/test_778_A b/bottleneck/tests/data/test_778_A
new file mode 100644
index 0000000..8392b2a
--- /dev/null
+++ b/bottleneck/tests/data/test_778_A
@@ -0,0 +1,9 @@
+544 1145
+371 1278
+417 814
+694 1566
+443 1104
+710 827
+617 714
+286 503
+191 568
diff --git a/bottleneck/tests/data/test_778_B b/bottleneck/tests/data/test_778_B
new file mode 100644
index 0000000..017b08d
--- /dev/null
+++ b/bottleneck/tests/data/test_778_B
@@ -0,0 +1,9 @@
+746 1177
+291 727
+956 1929
+255 294
+938 1415
+564 1206
+657 1586
+499 1013
+67 1035
diff --git a/bottleneck/tests/data/test_779_A b/bottleneck/tests/data/test_779_A
new file mode 100644
index 0000000..221d574
--- /dev/null
+++ b/bottleneck/tests/data/test_779_A
@@ -0,0 +1,9 @@
+771 1728
+948 1405
+842 1792
+956 1247
+194 841
+152 1145
+683 1458
+854 1851
+817 864
diff --git a/bottleneck/tests/data/test_779_B b/bottleneck/tests/data/test_779_B
new file mode 100644
index 0000000..113003e
--- /dev/null
+++ b/bottleneck/tests/data/test_779_B
@@ -0,0 +1,9 @@
+911 955
+410 1292
+972 1259
+128 1011
+362 591
+827 834
+677 1611
+783 1570
+844 1426
diff --git a/bottleneck/tests/data/test_780_A b/bottleneck/tests/data/test_780_A
new file mode 100644
index 0000000..3d9a22c
--- /dev/null
+++ b/bottleneck/tests/data/test_780_A
@@ -0,0 +1,10 @@
+183 274
+354 862
+922 1354
+560 1351
+235 292
+695 1560
+29 997
+962 1865
+141 1080
+827 1101
diff --git a/bottleneck/tests/data/test_780_B b/bottleneck/tests/data/test_780_B
new file mode 100644
index 0000000..defbae9
--- /dev/null
+++ b/bottleneck/tests/data/test_780_B
@@ -0,0 +1,10 @@
+42 318
+758 1669
+351 1022
+824 1415
+902 1400
+515 576
+260 586
+28 176
+469 1338
+909 1379
diff --git a/bottleneck/tests/data/test_781_A b/bottleneck/tests/data/test_781_A
new file mode 100644
index 0000000..72201a7
--- /dev/null
+++ b/bottleneck/tests/data/test_781_A
@@ -0,0 +1,10 @@
+329 554
+888 1476
+129 806
+786 990
+328 727
+574 1226
+864 1378
+61 561
+154 823
+922 1810
diff --git a/bottleneck/tests/data/test_781_B b/bottleneck/tests/data/test_781_B
new file mode 100644
index 0000000..85c8683
--- /dev/null
+++ b/bottleneck/tests/data/test_781_B
@@ -0,0 +1,10 @@
+193 306
+784 949
+446 467
+830 891
+36 174
+28 1028
+135 1113
+689 737
+598 669
+808 1618
diff --git a/bottleneck/tests/data/test_782_A b/bottleneck/tests/data/test_782_A
new file mode 100644
index 0000000..b376509
--- /dev/null
+++ b/bottleneck/tests/data/test_782_A
@@ -0,0 +1,10 @@
+488 967
+298 299
+687 942
+225 1184
+375 467
+17 355
+165 658
+911 1012
+970 1538
+26 194
diff --git a/bottleneck/tests/data/test_782_B b/bottleneck/tests/data/test_782_B
new file mode 100644
index 0000000..9fba291
--- /dev/null
+++ b/bottleneck/tests/data/test_782_B
@@ -0,0 +1,10 @@
+191 1062
+253 1153
+930 1745
+736 1486
+274 503
+830 1830
+769 865
+33 921
+160 304
+229 1012
diff --git a/bottleneck/tests/data/test_783_A b/bottleneck/tests/data/test_783_A
new file mode 100644
index 0000000..83593db
--- /dev/null
+++ b/bottleneck/tests/data/test_783_A
@@ -0,0 +1,10 @@
+575 1393
+206 817
+209 288
+181 466
+796 861
+885 1340
+110 346
+18 946
+769 1139
+422 1212
diff --git a/bottleneck/tests/data/test_783_B b/bottleneck/tests/data/test_783_B
new file mode 100644
index 0000000..d169a48
--- /dev/null
+++ b/bottleneck/tests/data/test_783_B
@@ -0,0 +1,10 @@
+810 1113
+997 1451
+205 1095
+621 1281
+677 1326
+911 1262
+395 916
+224 882
+708 812
+82 824
diff --git a/bottleneck/tests/data/test_784_A b/bottleneck/tests/data/test_784_A
new file mode 100644
index 0000000..b10df8b
--- /dev/null
+++ b/bottleneck/tests/data/test_784_A
@@ -0,0 +1,10 @@
+963 1352
+692 1376
+910 967
+668 831
+840 962
+348 424
+729 1606
+417 514
+350 871
+289 298
diff --git a/bottleneck/tests/data/test_784_B b/bottleneck/tests/data/test_784_B
new file mode 100644
index 0000000..ef2b466
--- /dev/null
+++ b/bottleneck/tests/data/test_784_B
@@ -0,0 +1,10 @@
+754 955
+100 1075
+199 738
+800 1132
+419 949
+729 969
+774 941
+559 1196
+692 1096
+741 1061
diff --git a/bottleneck/tests/data/test_785_A b/bottleneck/tests/data/test_785_A
new file mode 100644
index 0000000..3cdfaba
--- /dev/null
+++ b/bottleneck/tests/data/test_785_A
@@ -0,0 +1,10 @@
+797 970
+423 870
+289 692
+856 1132
+465 1409
+521 977
+322 545
+137 608
+934 1682
+77 959
diff --git a/bottleneck/tests/data/test_785_B b/bottleneck/tests/data/test_785_B
new file mode 100644
index 0000000..32fe176
--- /dev/null
+++ b/bottleneck/tests/data/test_785_B
@@ -0,0 +1,10 @@
+554 985
+793 1614
+915 1231
+215 790
+410 1181
+290 830
+733 1352
+717 829
+37 152
+989 1971
diff --git a/bottleneck/tests/data/test_786_A b/bottleneck/tests/data/test_786_A
new file mode 100644
index 0000000..2d9fcec
--- /dev/null
+++ b/bottleneck/tests/data/test_786_A
@@ -0,0 +1,10 @@
+274 873
+62 804
+282 663
+517 1295
+906 921
+967 1806
+724 1674
+976 1641
+923 1492
+529 1316
diff --git a/bottleneck/tests/data/test_786_B b/bottleneck/tests/data/test_786_B
new file mode 100644
index 0000000..417ee4b
--- /dev/null
+++ b/bottleneck/tests/data/test_786_B
@@ -0,0 +1,10 @@
+185 563
+774 1322
+467 499
+627 1251
+193 228
+528 1146
+957 1286
+882 891
+271 1024
+43 489
diff --git a/bottleneck/tests/data/test_787_A b/bottleneck/tests/data/test_787_A
new file mode 100644
index 0000000..7c056b6
--- /dev/null
+++ b/bottleneck/tests/data/test_787_A
@@ -0,0 +1,10 @@
+297 511
+275 457
+251 1094
+824 1027
+872 1563
+842 1711
+841 1094
+732 1633
+82 105
+397 900
diff --git a/bottleneck/tests/data/test_787_B b/bottleneck/tests/data/test_787_B
new file mode 100644
index 0000000..ddc126a
--- /dev/null
+++ b/bottleneck/tests/data/test_787_B
@@ -0,0 +1,10 @@
+152 438
+370 689
+859 1398
+697 1574
+294 635
+414 1138
+656 1516
+543 800
+260 902
+55 193
diff --git a/bottleneck/tests/data/test_788_A b/bottleneck/tests/data/test_788_A
new file mode 100644
index 0000000..61a58b0
--- /dev/null
+++ b/bottleneck/tests/data/test_788_A
@@ -0,0 +1,10 @@
+820 1238
+143 789
+0 482
+20 414
+838 1690
+810 1160
+178 978
+963 1890
+852 1293
+399 609
diff --git a/bottleneck/tests/data/test_788_B b/bottleneck/tests/data/test_788_B
new file mode 100644
index 0000000..d0782d9
--- /dev/null
+++ b/bottleneck/tests/data/test_788_B
@@ -0,0 +1,10 @@
+608 1470
+780 828
+436 513
+373 703
+950 1343
+608 949
+996 1248
+400 407
+911 1501
+660 1273
diff --git a/bottleneck/tests/data/test_789_A b/bottleneck/tests/data/test_789_A
new file mode 100644
index 0000000..4805534
--- /dev/null
+++ b/bottleneck/tests/data/test_789_A
@@ -0,0 +1,10 @@
+354 1062
+357 491
+915 1394
+385 1352
+461 585
+612 1103
+229 327
+741 1148
+572 1245
+399 863
diff --git a/bottleneck/tests/data/test_789_B b/bottleneck/tests/data/test_789_B
new file mode 100644
index 0000000..808dab9
--- /dev/null
+++ b/bottleneck/tests/data/test_789_B
@@ -0,0 +1,10 @@
+806 1352
+254 492
+202 1049
+571 1363
+359 1262
+828 1364
+123 603
+50 581
+502 1455
+218 1133
diff --git a/bottleneck/tests/data/test_790_A b/bottleneck/tests/data/test_790_A
new file mode 100644
index 0000000..231f25c
--- /dev/null
+++ b/bottleneck/tests/data/test_790_A
@@ -0,0 +1,10 @@
+411 1365
+920 965
+799 1463
+516 980
+775 1260
+48 353
+828 978
+166 1166
+391 992
+580 970
diff --git a/bottleneck/tests/data/test_790_B b/bottleneck/tests/data/test_790_B
new file mode 100644
index 0000000..0892cfe
--- /dev/null
+++ b/bottleneck/tests/data/test_790_B
@@ -0,0 +1,10 @@
+145 299
+605 1499
+534 1303
+440 1163
+628 1355
+2 71
+902 1181
+376 490
+696 1515
+24 40
diff --git a/bottleneck/tests/data/test_791_A b/bottleneck/tests/data/test_791_A
new file mode 100644
index 0000000..e12631e
--- /dev/null
+++ b/bottleneck/tests/data/test_791_A
@@ -0,0 +1,10 @@
+806 943
+568 1238
+44 633
+424 491
+361 1057
+583 1403
+754 1333
+843 1653
+512 1431
+768 1390
diff --git a/bottleneck/tests/data/test_791_B b/bottleneck/tests/data/test_791_B
new file mode 100644
index 0000000..62aa958
--- /dev/null
+++ b/bottleneck/tests/data/test_791_B
@@ -0,0 +1,10 @@
+850 1256
+138 1008
+948 1188
+914 1911
+659 1270
+375 986
+994 1160
+835 863
+73 849
+756 1456
diff --git a/bottleneck/tests/data/test_792_A b/bottleneck/tests/data/test_792_A
new file mode 100644
index 0000000..3b73b46
--- /dev/null
+++ b/bottleneck/tests/data/test_792_A
@@ -0,0 +1,10 @@
+610 1074
+927 1375
+497 992
+277 1026
+978 1640
+244 290
+299 814
+80 476
+599 1512
+793 824
diff --git a/bottleneck/tests/data/test_792_B b/bottleneck/tests/data/test_792_B
new file mode 100644
index 0000000..517ff30
--- /dev/null
+++ b/bottleneck/tests/data/test_792_B
@@ -0,0 +1,10 @@
+531 1350
+371 1273
+498 546
+487 1299
+347 1067
+638 1257
+205 802
+240 658
+1 249
+147 878
diff --git a/bottleneck/tests/data/test_793_A b/bottleneck/tests/data/test_793_A
new file mode 100644
index 0000000..d9b85ae
--- /dev/null
+++ b/bottleneck/tests/data/test_793_A
@@ -0,0 +1,10 @@
+267 566
+193 1014
+348 534
+640 670
+795 1157
+752 1273
+439 1172
+254 687
+959 1954
+408 1084
diff --git a/bottleneck/tests/data/test_793_B b/bottleneck/tests/data/test_793_B
new file mode 100644
index 0000000..66180dd
--- /dev/null
+++ b/bottleneck/tests/data/test_793_B
@@ -0,0 +1,10 @@
+751 1576
+410 1090
+288 1200
+430 1222
+988 1576
+152 1095
+583 596
+799 1296
+828 1022
+217 956
diff --git a/bottleneck/tests/data/test_794_A b/bottleneck/tests/data/test_794_A
new file mode 100644
index 0000000..3d5401c
--- /dev/null
+++ b/bottleneck/tests/data/test_794_A
@@ -0,0 +1,10 @@
+1 160
+264 1182
+662 1435
+659 892
+47 845
+383 744
+773 1409
+895 906
+152 735
+344 870
diff --git a/bottleneck/tests/data/test_794_B b/bottleneck/tests/data/test_794_B
new file mode 100644
index 0000000..26be9a3
--- /dev/null
+++ b/bottleneck/tests/data/test_794_B
@@ -0,0 +1,10 @@
+607 934
+865 900
+339 349
+888 1238
+981 1281
+1 554
+514 627
+77 1040
+911 1850
+276 1178
diff --git a/bottleneck/tests/data/test_795_A b/bottleneck/tests/data/test_795_A
new file mode 100644
index 0000000..7c73f4d
--- /dev/null
+++ b/bottleneck/tests/data/test_795_A
@@ -0,0 +1,10 @@
+494 905
+440 1385
+496 955
+162 1027
+237 421
+873 1102
+349 1346
+470 880
+364 822
+869 1335
diff --git a/bottleneck/tests/data/test_795_B b/bottleneck/tests/data/test_795_B
new file mode 100644
index 0000000..afc371b
--- /dev/null
+++ b/bottleneck/tests/data/test_795_B
@@ -0,0 +1,10 @@
+22 509
+741 1484
+558 982
+862 1077
+856 1695
+4 100
+995 1304
+103 990
+64 439
+883 1258
diff --git a/bottleneck/tests/data/test_796_A b/bottleneck/tests/data/test_796_A
new file mode 100644
index 0000000..a326a52
--- /dev/null
+++ b/bottleneck/tests/data/test_796_A
@@ -0,0 +1,10 @@
+16 636
+823 1691
+880 1198
+967 1441
+501 745
+318 427
+177 192
+944 1596
+229 458
+570 1267
diff --git a/bottleneck/tests/data/test_796_B b/bottleneck/tests/data/test_796_B
new file mode 100644
index 0000000..86d2cf9
--- /dev/null
+++ b/bottleneck/tests/data/test_796_B
@@ -0,0 +1,10 @@
+240 255
+28 64
+713 1016
+577 662
+838 1674
+41 365
+889 1477
+1000 1767
+58 393
+870 1574
diff --git a/bottleneck/tests/data/test_797_A b/bottleneck/tests/data/test_797_A
new file mode 100644
index 0000000..b5149bf
--- /dev/null
+++ b/bottleneck/tests/data/test_797_A
@@ -0,0 +1,10 @@
+258 711
+970 1782
+725 883
+626 1199
+785 1502
+713 820
+754 1570
+311 1068
+866 1364
+50 713
diff --git a/bottleneck/tests/data/test_797_B b/bottleneck/tests/data/test_797_B
new file mode 100644
index 0000000..45ba81b
--- /dev/null
+++ b/bottleneck/tests/data/test_797_B
@@ -0,0 +1,10 @@
+381 1350
+844 1724
+531 1460
+472 1208
+659 914
+745 757
+627 1608
+69 357
+298 621
+100 760
diff --git a/bottleneck/tests/data/test_798_A b/bottleneck/tests/data/test_798_A
new file mode 100644
index 0000000..a053ddd
--- /dev/null
+++ b/bottleneck/tests/data/test_798_A
@@ -0,0 +1,10 @@
+153 558
+364 847
+444 1083
+994 1375
+728 1585
+495 1005
+47 431
+361 1262
+645 646
+816 1742
diff --git a/bottleneck/tests/data/test_798_B b/bottleneck/tests/data/test_798_B
new file mode 100644
index 0000000..69c921b
--- /dev/null
+++ b/bottleneck/tests/data/test_798_B
@@ -0,0 +1,10 @@
+416 985
+449 995
+832 1102
+550 775
+367 614
+393 458
+340 890
+264 955
+10 50
+834 1137
diff --git a/bottleneck/tests/data/test_799_A b/bottleneck/tests/data/test_799_A
new file mode 100644
index 0000000..374e56a
--- /dev/null
+++ b/bottleneck/tests/data/test_799_A
@@ -0,0 +1,10 @@
+40 603
+309 973
+679 1580
+219 675
+92 934
+537 1366
+63 461
+408 807
+983 1016
+176 789
diff --git a/bottleneck/tests/data/test_799_B b/bottleneck/tests/data/test_799_B
new file mode 100644
index 0000000..f92c370
--- /dev/null
+++ b/bottleneck/tests/data/test_799_B
@@ -0,0 +1,10 @@
+312 772
+963 1630
+613 920
+597 1153
+941 1187
+150 434
+269 804
+885 887
+649 881
+618 973
diff --git a/bottleneck/tests/data/test_800_A b/bottleneck/tests/data/test_800_A
new file mode 100644
index 0000000..36aab61
--- /dev/null
+++ b/bottleneck/tests/data/test_800_A
@@ -0,0 +1,20 @@
+729 1257
+887 1370
+876 1762
+569 878
+13 393
+287 1169
+720 899
+338 892
+594 1438
+248 1204
+315 985
+796 1645
+730 1605
+323 490
+470 1454
+285 1067
+215 757
+92 325
+866 869
+899 1630
diff --git a/bottleneck/tests/data/test_800_B b/bottleneck/tests/data/test_800_B
new file mode 100644
index 0000000..2496bcb
--- /dev/null
+++ b/bottleneck/tests/data/test_800_B
@@ -0,0 +1,20 @@
+961 1808
+251 958
+152 851
+834 1250
+727 1719
+968 1220
+107 206
+564 1423
+475 1438
+884 1174
+928 1303
+39 708
+854 1539
+825 1094
+614 989
+281 856
+445 1141
+784 1664
+657 969
+154 1026
diff --git a/bottleneck/tests/data/test_801_A b/bottleneck/tests/data/test_801_A
new file mode 100644
index 0000000..66ed176
--- /dev/null
+++ b/bottleneck/tests/data/test_801_A
@@ -0,0 +1,20 @@
+823 1484
+877 1798
+158 361
+59 670
+365 636
+536 831
+669 1574
+51 690
+243 1047
+579 1472
+450 618
+478 706
+850 1720
+10 822
+502 1081
+815 833
+192 629
+745 909
+936 1924
+619 1215
diff --git a/bottleneck/tests/data/test_801_B b/bottleneck/tests/data/test_801_B
new file mode 100644
index 0000000..4376fcf
--- /dev/null
+++ b/bottleneck/tests/data/test_801_B
@@ -0,0 +1,20 @@
+911 924
+564 1044
+939 1177
+226 536
+692 1241
+931 1421
+750 767
+427 630
+594 1388
+751 1751
+933 1190
+379 1220
+63 623
+79 190
+650 993
+508 1351
+961 1710
+619 863
+548 1358
+727 1515
diff --git a/bottleneck/tests/data/test_802_A b/bottleneck/tests/data/test_802_A
new file mode 100644
index 0000000..6bfdeda
--- /dev/null
+++ b/bottleneck/tests/data/test_802_A
@@ -0,0 +1,20 @@
+63 288
+994 1416
+92 461
+241 742
+325 877
+466 925
+923 1215
+941 1044
+618 1396
+248 1066
+383 442
+583 1016
+947 1095
+186 602
+291 448
+339 384
+467 1107
+771 942
+92 794
+2 533
diff --git a/bottleneck/tests/data/test_802_B b/bottleneck/tests/data/test_802_B
new file mode 100644
index 0000000..eaec985
--- /dev/null
+++ b/bottleneck/tests/data/test_802_B
@@ -0,0 +1,20 @@
+350 416
+143 1004
+710 1425
+665 1101
+828 1491
+80 449
+977 1801
+497 509
+664 700
+405 670
+688 1502
+102 938
+893 1437
+245 728
+626 1333
+526 1473
+914 1253
+96 268
+693 1302
+982 1487
diff --git a/bottleneck/tests/data/test_803_A b/bottleneck/tests/data/test_803_A
new file mode 100644
index 0000000..501248d
--- /dev/null
+++ b/bottleneck/tests/data/test_803_A
@@ -0,0 +1,20 @@
+553 1373
+92 606
+892 1104
+804 1697
+653 953
+421 824
+670 1420
+621 1196
+912 1889
+482 1161
+381 691
+192 1146
+592 670
+920 1293
+754 1475
+217 379
+584 1551
+168 463
+212 251
+303 469
diff --git a/bottleneck/tests/data/test_803_B b/bottleneck/tests/data/test_803_B
new file mode 100644
index 0000000..42dadd9
--- /dev/null
+++ b/bottleneck/tests/data/test_803_B
@@ -0,0 +1,20 @@
+252 701
+398 718
+663 871
+257 475
+998 1850
+292 587
+813 1363
+374 757
+295 749
+405 607
+21 374
+489 1313
+975 1840
+773 1423
+204 693
+149 532
+57 191
+307 618
+509 1109
+308 350
diff --git a/bottleneck/tests/data/test_804_A b/bottleneck/tests/data/test_804_A
new file mode 100644
index 0000000..6af9294
--- /dev/null
+++ b/bottleneck/tests/data/test_804_A
@@ -0,0 +1,20 @@
+518 993
+44 915
+674 768
+122 870
+394 839
+631 1285
+805 1491
+521 802
+456 474
+450 1083
+555 1280
+858 1839
+131 144
+361 953
+600 985
+158 537
+771 1062
+286 1285
+168 397
+748 1722
diff --git a/bottleneck/tests/data/test_804_B b/bottleneck/tests/data/test_804_B
new file mode 100644
index 0000000..8470b65
--- /dev/null
+++ b/bottleneck/tests/data/test_804_B
@@ -0,0 +1,20 @@
+132 843
+202 982
+374 1118
+9 980
+843 852
+537 761
+645 656
+882 1627
+51 619
+217 926
+870 1398
+87 1080
+223 1189
+160 379
+406 561
+536 1522
+353 487
+312 1180
+526 1492
+249 823
diff --git a/bottleneck/tests/data/test_805_A b/bottleneck/tests/data/test_805_A
new file mode 100644
index 0000000..45a3198
--- /dev/null
+++ b/bottleneck/tests/data/test_805_A
@@ -0,0 +1,20 @@
+350 546
+268 1153
+401 757
+503 848
+981 1709
+161 948
+688 1661
+234 471
+397 801
+433 1024
+942 1394
+308 969
+32 690
+797 1248
+182 407
+714 1267
+577 1209
+775 919
+140 976
+366 1300
diff --git a/bottleneck/tests/data/test_805_B b/bottleneck/tests/data/test_805_B
new file mode 100644
index 0000000..4967cfd
--- /dev/null
+++ b/bottleneck/tests/data/test_805_B
@@ -0,0 +1,20 @@
+330 1222
+792 1359
+905 1402
+933 1482
+322 933
+440 887
+672 1438
+849 1650
+264 794
+21 219
+437 593
+159 598
+466 675
+712 1347
+566 1363
+244 382
+374 520
+729 1295
+998 1116
+954 1362
diff --git a/bottleneck/tests/data/test_806_A b/bottleneck/tests/data/test_806_A
new file mode 100644
index 0000000..8eb1e33
--- /dev/null
+++ b/bottleneck/tests/data/test_806_A
@@ -0,0 +1,20 @@
+909 1049
+241 667
+928 1287
+838 1606
+159 1145
+395 714
+445 804
+897 1289
+770 1108
+649 714
+643 684
+436 561
+125 637
+704 856
+738 913
+478 1206
+396 1306
+106 213
+840 929
+320 1037
diff --git a/bottleneck/tests/data/test_806_B b/bottleneck/tests/data/test_806_B
new file mode 100644
index 0000000..27727b2
--- /dev/null
+++ b/bottleneck/tests/data/test_806_B
@@ -0,0 +1,20 @@
+342 756
+736 1334
+769 1194
+352 967
+165 282
+209 306
+977 1040
+385 604
+141 566
+458 884
+186 477
+869 1651
+143 850
+742 1329
+212 872
+445 1214
+864 870
+836 1772
+534 1338
+338 1244
diff --git a/bottleneck/tests/data/test_807_A b/bottleneck/tests/data/test_807_A
new file mode 100644
index 0000000..4979b7d
--- /dev/null
+++ b/bottleneck/tests/data/test_807_A
@@ -0,0 +1,20 @@
+657 1104
+391 1193
+374 1227
+9 94
+458 555
+982 1529
+840 920
+831 1039
+468 1180
+912 1687
+988 1717
+33 324
+577 639
+426 1103
+733 1096
+41 421
+376 784
+823 1180
+389 1204
+788 1243
diff --git a/bottleneck/tests/data/test_807_B b/bottleneck/tests/data/test_807_B
new file mode 100644
index 0000000..67610cb
--- /dev/null
+++ b/bottleneck/tests/data/test_807_B
@@ -0,0 +1,20 @@
+295 1223
+755 1585
+860 1191
+281 873
+86 1000
+508 1264
+16 594
+616 747
+522 1196
+34 270
+422 1196
+22 801
+812 947
+91 517
+233 586
+167 475
+173 233
+130 807
+764 1691
+942 1622
diff --git a/bottleneck/tests/data/test_808_A b/bottleneck/tests/data/test_808_A
new file mode 100644
index 0000000..b35d354
--- /dev/null
+++ b/bottleneck/tests/data/test_808_A
@@ -0,0 +1,20 @@
+395 768
+234 477
+627 1516
+353 1158
+108 195
+399 496
+787 1246
+330 553
+840 1835
+474 947
+736 1100
+248 381
+559 575
+716 1583
+873 1336
+927 1293
+857 1611
+691 1202
+293 770
+27 585
diff --git a/bottleneck/tests/data/test_808_B b/bottleneck/tests/data/test_808_B
new file mode 100644
index 0000000..fb783cb
--- /dev/null
+++ b/bottleneck/tests/data/test_808_B
@@ -0,0 +1,20 @@
+801 1397
+119 551
+305 964
+706 1119
+586 1050
+925 1532
+595 1000
+898 1753
+491 699
+450 802
+499 1011
+180 468
+616 768
+179 901
+89 144
+828 1466
+927 1852
+151 584
+213 997
+952 1055
diff --git a/bottleneck/tests/data/test_809_A b/bottleneck/tests/data/test_809_A
new file mode 100644
index 0000000..e578429
--- /dev/null
+++ b/bottleneck/tests/data/test_809_A
@@ -0,0 +1,20 @@
+512 1083
+60 706
+61 93
+413 1076
+277 298
+766 1458
+984 1052
+762 1727
+356 422
+263 655
+605 968
+422 1373
+174 1033
+983 1676
+666 1005
+179 336
+553 1267
+987 1269
+756 1753
+842 1754
diff --git a/bottleneck/tests/data/test_809_B b/bottleneck/tests/data/test_809_B
new file mode 100644
index 0000000..e4deda8
--- /dev/null
+++ b/bottleneck/tests/data/test_809_B
@@ -0,0 +1,20 @@
+178 1010
+727 738
+812 1638
+893 1821
+41 650
+797 1295
+174 473
+389 1244
+289 601
+626 1188
+890 1646
+296 318
+861 1582
+860 1410
+670 1574
+310 813
+186 263
+886 1796
+263 760
+396 1314
diff --git a/bottleneck/tests/data/test_810_A b/bottleneck/tests/data/test_810_A
new file mode 100644
index 0000000..b7da658
--- /dev/null
+++ b/bottleneck/tests/data/test_810_A
@@ -0,0 +1,20 @@
+843 1230
+289 770
+614 776
+512 987
+326 1253
+651 932
+827 839
+945 1361
+492 706
+312 1139
+463 1394
+68 1045
+229 1200
+126 898
+494 1095
+893 1824
+548 889
+45 952
+136 725
+304 1154
diff --git a/bottleneck/tests/data/test_810_B b/bottleneck/tests/data/test_810_B
new file mode 100644
index 0000000..06e2af4
--- /dev/null
+++ b/bottleneck/tests/data/test_810_B
@@ -0,0 +1,20 @@
+207 249
+374 690
+287 677
+566 817
+875 1590
+570 1096
+34 543
+344 801
+31 796
+681 1566
+402 835
+404 906
+754 1339
+96 514
+549 1065
+874 1762
+935 1530
+368 1331
+465 831
+890 1413
diff --git a/bottleneck/tests/data/test_811_A b/bottleneck/tests/data/test_811_A
new file mode 100644
index 0000000..708fc33
--- /dev/null
+++ b/bottleneck/tests/data/test_811_A
@@ -0,0 +1,20 @@
+605 650
+57 484
+621 641
+794 1393
+951 1609
+132 656
+639 1132
+419 967
+741 1547
+105 466
+306 1270
+827 1475
+260 376
+418 1180
+458 1136
+957 1237
+363 749
+742 1038
+958 1157
+153 252
diff --git a/bottleneck/tests/data/test_811_B b/bottleneck/tests/data/test_811_B
new file mode 100644
index 0000000..69bffab
--- /dev/null
+++ b/bottleneck/tests/data/test_811_B
@@ -0,0 +1,20 @@
+687 1060
+622 650
+544 1212
+38 633
+280 956
+695 791
+120 956
+364 435
+825 1760
+137 303
+701 1432
+967 1395
+566 966
+695 951
+85 262
+82 595
+11 100
+312 1104
+669 1424
+157 285
diff --git a/bottleneck/tests/data/test_812_A b/bottleneck/tests/data/test_812_A
new file mode 100644
index 0000000..f592f5f
--- /dev/null
+++ b/bottleneck/tests/data/test_812_A
@@ -0,0 +1,20 @@
+333 661
+942 1519
+825 1088
+68 726
+443 1398
+918 1335
+853 1787
+163 269
+158 214
+444 1036
+163 670
+124 834
+745 890
+728 1254
+981 1370
+858 1117
+159 700
+978 1371
+554 1366
+112 689
diff --git a/bottleneck/tests/data/test_812_B b/bottleneck/tests/data/test_812_B
new file mode 100644
index 0000000..7e37dec
--- /dev/null
+++ b/bottleneck/tests/data/test_812_B
@@ -0,0 +1,20 @@
+228 896
+635 880
+250 930
+8 479
+168 214
+366 775
+41 981
+461 692
+337 839
+870 1634
+497 511
+253 389
+807 913
+487 1348
+245 1186
+222 1169
+254 810
+855 1471
+399 1155
+433 1194
diff --git a/bottleneck/tests/data/test_813_A b/bottleneck/tests/data/test_813_A
new file mode 100644
index 0000000..94bbbc3
--- /dev/null
+++ b/bottleneck/tests/data/test_813_A
@@ -0,0 +1,20 @@
+45 843
+606 637
+981 1438
+769 1525
+694 1370
+596 1454
+365 813
+164 704
+198 347
+115 553
+767 1119
+663 1052
+379 697
+294 335
+457 1253
+320 1147
+508 830
+506 738
+381 1010
+896 1376
diff --git a/bottleneck/tests/data/test_813_B b/bottleneck/tests/data/test_813_B
new file mode 100644
index 0000000..54ce63b
--- /dev/null
+++ b/bottleneck/tests/data/test_813_B
@@ -0,0 +1,20 @@
+519 1068
+65 460
+199 429
+695 1050
+407 524
+24 581
+54 728
+843 1551
+773 829
+355 644
+145 962
+837 1238
+796 830
+383 791
+86 1028
+461 1145
+270 1231
+374 837
+730 875
+659 1188
diff --git a/bottleneck/tests/data/test_814_A b/bottleneck/tests/data/test_814_A
new file mode 100644
index 0000000..3eb0a25
--- /dev/null
+++ b/bottleneck/tests/data/test_814_A
@@ -0,0 +1,20 @@
+571 1312
+384 842
+418 932
+388 1146
+857 1045
+952 1326
+551 631
+820 1105
+791 884
+50 788
+697 1165
+840 1425
+130 169
+106 615
+429 1085
+428 567
+138 762
+364 1304
+116 1013
+50 983
diff --git a/bottleneck/tests/data/test_814_B b/bottleneck/tests/data/test_814_B
new file mode 100644
index 0000000..a65d82f
--- /dev/null
+++ b/bottleneck/tests/data/test_814_B
@@ -0,0 +1,20 @@
+617 718
+320 697
+164 654
+423 821
+444 1368
+211 382
+184 857
+799 1071
+866 924
+48 829
+90 249
+378 1336
+817 832
+6 246
+115 280
+363 447
+422 964
+902 1809
+637 1073
+585 606
diff --git a/bottleneck/tests/data/test_815_A b/bottleneck/tests/data/test_815_A
new file mode 100644
index 0000000..ae366c6
--- /dev/null
+++ b/bottleneck/tests/data/test_815_A
@@ -0,0 +1,20 @@
+911 1198
+516 1091
+421 1381
+257 824
+272 394
+75 841
+659 805
+980 1436
+237 431
+668 1221
+441 1057
+560 849
+305 1270
+572 929
+460 812
+471 640
+50 773
+1 446
+895 1610
+837 1400
diff --git a/bottleneck/tests/data/test_815_B b/bottleneck/tests/data/test_815_B
new file mode 100644
index 0000000..6d11d46
--- /dev/null
+++ b/bottleneck/tests/data/test_815_B
@@ -0,0 +1,20 @@
+589 1196
+872 1375
+473 627
+522 671
+940 1274
+666 1453
+1 861
+656 1221
+669 866
+916 1378
+340 773
+454 1020
+190 561
+828 1606
+356 693
+876 1220
+644 763
+991 1241
+559 1095
+124 406
diff --git a/bottleneck/tests/data/test_816_A b/bottleneck/tests/data/test_816_A
new file mode 100644
index 0000000..54dc128
--- /dev/null
+++ b/bottleneck/tests/data/test_816_A
@@ -0,0 +1,20 @@
+376 1109
+877 1496
+817 1426
+647 703
+92 672
+909 1671
+580 965
+626 1528
+347 1159
+551 1396
+432 941
+7 766
+1 370
+664 1384
+106 448
+763 1190
+768 892
+19 465
+220 1188
+96 554
diff --git a/bottleneck/tests/data/test_816_B b/bottleneck/tests/data/test_816_B
new file mode 100644
index 0000000..56f00ce
--- /dev/null
+++ b/bottleneck/tests/data/test_816_B
@@ -0,0 +1,20 @@
+930 1560
+702 1257
+174 988
+712 777
+150 355
+146 617
+265 954
+519 820
+575 1117
+603 1133
+910 1817
+363 415
+102 347
+925 1565
+621 1336
+203 752
+743 1550
+39 310
+904 1206
+696 1445
diff --git a/bottleneck/tests/data/test_817_A b/bottleneck/tests/data/test_817_A
new file mode 100644
index 0000000..8c01be3
--- /dev/null
+++ b/bottleneck/tests/data/test_817_A
@@ -0,0 +1,20 @@
+14 829
+708 1194
+415 1028
+395 1236
+294 792
+319 730
+490 889
+424 1364
+512 864
+820 1563
+461 880
+345 686
+318 407
+993 1857
+833 882
+937 1452
+376 719
+171 852
+457 523
+156 784
diff --git a/bottleneck/tests/data/test_817_B b/bottleneck/tests/data/test_817_B
new file mode 100644
index 0000000..1aa1eaa
--- /dev/null
+++ b/bottleneck/tests/data/test_817_B
@@ -0,0 +1,20 @@
+544 1398
+776 1241
+56 1054
+942 1736
+752 1563
+475 1241
+423 923
+553 1023
+101 846
+841 1613
+895 1353
+832 1502
+300 915
+986 1488
+397 648
+823 1196
+457 1079
+371 471
+398 1114
+50 853
diff --git a/bottleneck/tests/data/test_818_A b/bottleneck/tests/data/test_818_A
new file mode 100644
index 0000000..44ac7de
--- /dev/null
+++ b/bottleneck/tests/data/test_818_A
@@ -0,0 +1,20 @@
+296 395
+102 172
+9 500
+426 574
+931 1885
+76 901
+202 1197
+462 1135
+87 907
+109 780
+186 238
+297 833
+142 360
+719 1106
+25 775
+626 1219
+911 1619
+9 322
+158 222
+843 1086
diff --git a/bottleneck/tests/data/test_818_B b/bottleneck/tests/data/test_818_B
new file mode 100644
index 0000000..83c706c
--- /dev/null
+++ b/bottleneck/tests/data/test_818_B
@@ -0,0 +1,20 @@
+989 1945
+718 1675
+126 965
+27 359
+756 962
+158 737
+149 473
+748 896
+779 1215
+685 933
+742 1449
+717 1575
+834 1467
+80 377
+634 1348
+419 766
+345 733
+111 753
+138 1014
+452 1429
diff --git a/bottleneck/tests/data/test_819_A b/bottleneck/tests/data/test_819_A
new file mode 100644
index 0000000..1065f24
--- /dev/null
+++ b/bottleneck/tests/data/test_819_A
@@ -0,0 +1,20 @@
+119 806
+187 942
+454 844
+581 583
+753 1715
+199 380
+623 697
+63 469
+929 1518
+960 1306
+996 1011
+157 203
+666 1505
+14 693
+414 536
+461 1330
+975 1260
+375 1004
+375 1145
+453 723
diff --git a/bottleneck/tests/data/test_819_B b/bottleneck/tests/data/test_819_B
new file mode 100644
index 0000000..f1c8ba3
--- /dev/null
+++ b/bottleneck/tests/data/test_819_B
@@ -0,0 +1,20 @@
+184 385
+214 473
+11 1007
+301 516
+689 820
+267 1052
+26 720
+414 726
+946 1295
+720 1275
+430 1272
+119 349
+850 1371
+738 1125
+450 1222
+728 1503
+951 1796
+843 947
+856 983
+705 996
diff --git a/bottleneck/tests/data/test_820_A b/bottleneck/tests/data/test_820_A
new file mode 100644
index 0000000..1f23572
--- /dev/null
+++ b/bottleneck/tests/data/test_820_A
@@ -0,0 +1,30 @@
+232 279
+761 1519
+175 773
+522 1293
+336 381
+478 998
+61 328
+450 1350
+669 1085
+602 870
+286 987
+593 897
+358 742
+900 1878
+441 668
+109 977
+847 1651
+41 863
+94 851
+240 491
+335 1150
+135 748
+480 1052
+420 572
+837 1662
+629 1223
+895 1453
+304 1051
+424 553
+308 714
diff --git a/bottleneck/tests/data/test_820_B b/bottleneck/tests/data/test_820_B
new file mode 100644
index 0000000..3465e1b
--- /dev/null
+++ b/bottleneck/tests/data/test_820_B
@@ -0,0 +1,30 @@
+309 934
+8 585
+213 1043
+116 589
+436 679
+70 715
+604 1194
+562 1151
+727 1616
+404 632
+948 1712
+934 1186
+690 1385
+636 682
+140 888
+738 884
+704 1593
+868 979
+954 1310
+605 1513
+955 1763
+730 1719
+393 1159
+325 1279
+35 153
+436 838
+249 1157
+394 921
+634 1242
+914 1138
diff --git a/bottleneck/tests/data/test_821_A b/bottleneck/tests/data/test_821_A
new file mode 100644
index 0000000..ab4fa20
--- /dev/null
+++ b/bottleneck/tests/data/test_821_A
@@ -0,0 +1,30 @@
+610 907
+704 897
+228 1047
+459 1435
+105 904
+492 1288
+557 863
+368 622
+715 1240
+627 1465
+823 1003
+823 891
+724 853
+227 933
+88 600
+735 1479
+591 757
+260 347
+314 1130
+342 985
+80 990
+93 137
+153 761
+91 408
+497 1011
+980 1277
+916 1437
+81 1038
+735 1143
+374 773
diff --git a/bottleneck/tests/data/test_821_B b/bottleneck/tests/data/test_821_B
new file mode 100644
index 0000000..36073ce
--- /dev/null
+++ b/bottleneck/tests/data/test_821_B
@@ -0,0 +1,30 @@
+575 1235
+999 1599
+78 560
+384 694
+217 646
+709 1344
+772 1755
+542 994
+376 1248
+924 1462
+675 892
+927 1354
+306 1292
+573 1316
+731 1424
+445 911
+145 588
+402 822
+584 920
+374 831
+636 1237
+580 614
+490 1107
+529 1074
+652 1460
+892 1245
+917 1530
+679 1511
+725 820
+620 1439
diff --git a/bottleneck/tests/data/test_822_A b/bottleneck/tests/data/test_822_A
new file mode 100644
index 0000000..38b5219
--- /dev/null
+++ b/bottleneck/tests/data/test_822_A
@@ -0,0 +1,30 @@
+416 1100
+661 1339
+612 962
+593 1233
+642 1509
+574 969
+202 450
+370 787
+14 937
+974 1336
+420 775
+808 1662
+304 319
+492 555
+740 1524
+935 1749
+88 758
+995 1590
+40 963
+141 1031
+695 886
+504 1111
+684 1360
+861 1552
+482 746
+89 547
+493 598
+190 310
+806 1384
+472 1459
diff --git a/bottleneck/tests/data/test_822_B b/bottleneck/tests/data/test_822_B
new file mode 100644
index 0000000..c61c33e
--- /dev/null
+++ b/bottleneck/tests/data/test_822_B
@@ -0,0 +1,30 @@
+843 1057
+860 1286
+703 1268
+545 1381
+515 1186
+178 952
+456 907
+713 964
+555 981
+332 1263
+11 112
+291 347
+958 1460
+723 1182
+850 865
+631 677
+227 640
+676 1506
+256 610
+581 1468
+15 619
+233 1100
+35 957
+444 817
+517 1318
+129 318
+765 1584
+733 1001
+932 998
+693 1076
diff --git a/bottleneck/tests/data/test_823_A b/bottleneck/tests/data/test_823_A
new file mode 100644
index 0000000..5d441a2
--- /dev/null
+++ b/bottleneck/tests/data/test_823_A
@@ -0,0 +1,30 @@
+817 1477
+662 1416
+722 1408
+43 588
+583 585
+159 836
+752 922
+529 727
+55 60
+447 1200
+248 735
+520 1121
+541 1379
+704 1640
+681 1454
+234 385
+884 1063
+884 1535
+612 704
+55 102
+214 913
+597 1576
+19 919
+907 951
+785 1577
+185 281
+567 680
+577 1162
+323 495
+321 920
diff --git a/bottleneck/tests/data/test_823_B b/bottleneck/tests/data/test_823_B
new file mode 100644
index 0000000..e1ae113
--- /dev/null
+++ b/bottleneck/tests/data/test_823_B
@@ -0,0 +1,30 @@
+562 1532
+19 557
+758 1238
+732 1011
+116 761
+988 1621
+783 786
+128 964
+208 249
+111 948
+510 719
+711 1630
+99 769
+159 816
+295 807
+485 1332
+848 1845
+721 1534
+344 1341
+678 1465
+665 889
+734 1611
+246 783
+238 618
+401 809
+234 571
+527 1227
+690 1550
+278 729
+454 591
diff --git a/bottleneck/tests/data/test_824_A b/bottleneck/tests/data/test_824_A
new file mode 100644
index 0000000..3bfc169
--- /dev/null
+++ b/bottleneck/tests/data/test_824_A
@@ -0,0 +1,30 @@
+333 858
+230 978
+281 1158
+880 1314
+816 1259
+840 1631
+385 979
+413 537
+378 697
+222 486
+213 285
+664 1109
+7 300
+482 903
+325 338
+616 875
+46 548
+145 965
+126 760
+873 1030
+533 1087
+417 487
+510 919
+760 1722
+144 897
+136 412
+88 137
+704 1084
+457 744
+424 1148
diff --git a/bottleneck/tests/data/test_824_B b/bottleneck/tests/data/test_824_B
new file mode 100644
index 0000000..192df92
--- /dev/null
+++ b/bottleneck/tests/data/test_824_B
@@ -0,0 +1,30 @@
+285 785
+57 516
+410 1131
+794 1019
+732 1499
+391 1297
+104 689
+294 976
+748 1061
+806 1309
+118 995
+7 994
+952 1007
+994 1296
+340 1335
+387 762
+800 946
+757 1299
+167 976
+538 802
+147 808
+51 694
+20 353
+290 376
+575 1395
+294 1074
+754 1042
+461 474
+634 1525
+491 1208
diff --git a/bottleneck/tests/data/test_825_A b/bottleneck/tests/data/test_825_A
new file mode 100644
index 0000000..5dc0d10
--- /dev/null
+++ b/bottleneck/tests/data/test_825_A
@@ -0,0 +1,30 @@
+727 1401
+217 1102
+836 1270
+380 446
+569 1295
+55 504
+239 312
+872 1710
+552 1075
+584 1470
+402 438
+441 1296
+194 1105
+643 1563
+933 1180
+448 735
+749 1583
+725 1624
+533 1043
+952 1467
+548 926
+839 926
+5 724
+768 1115
+557 578
+712 1472
+279 1121
+399 808
+601 951
+293 422
diff --git a/bottleneck/tests/data/test_825_B b/bottleneck/tests/data/test_825_B
new file mode 100644
index 0000000..e440801
--- /dev/null
+++ b/bottleneck/tests/data/test_825_B
@@ -0,0 +1,30 @@
+466 883
+492 1180
+645 1446
+138 604
+469 1261
+110 409
+923 1649
+101 397
+410 440
+655 1223
+280 822
+564 701
+736 1735
+645 1272
+495 982
+339 389
+188 738
+669 1263
+106 658
+981 1256
+815 1378
+914 1482
+193 855
+361 1134
+885 1858
+98 576
+577 897
+528 549
+152 154
+363 886
diff --git a/bottleneck/tests/data/test_826_A b/bottleneck/tests/data/test_826_A
new file mode 100644
index 0000000..8fbcf93
--- /dev/null
+++ b/bottleneck/tests/data/test_826_A
@@ -0,0 +1,30 @@
+669 1220
+577 787
+982 1553
+218 1116
+715 831
+383 780
+328 925
+216 612
+635 1185
+211 707
+915 1130
+223 693
+468 1277
+570 1219
+281 1037
+759 1522
+435 1201
+356 582
+996 1867
+369 833
+584 1415
+472 1174
+6 905
+329 358
+703 1331
+141 180
+136 204
+873 1858
+107 943
+158 1153
diff --git a/bottleneck/tests/data/test_826_B b/bottleneck/tests/data/test_826_B
new file mode 100644
index 0000000..10fe424
--- /dev/null
+++ b/bottleneck/tests/data/test_826_B
@@ -0,0 +1,30 @@
+651 1534
+143 212
+685 962
+100 862
+34 102
+333 1131
+274 651
+142 1075
+312 751
+848 1583
+396 548
+377 1071
+824 1067
+932 1352
+510 1339
+435 561
+259 1223
+434 1080
+974 1509
+618 1604
+795 1363
+668 1299
+532 1157
+326 632
+182 768
+611 1431
+62 528
+832 1370
+413 1373
+153 813
diff --git a/bottleneck/tests/data/test_827_A b/bottleneck/tests/data/test_827_A
new file mode 100644
index 0000000..c1c63c9
--- /dev/null
+++ b/bottleneck/tests/data/test_827_A
@@ -0,0 +1,30 @@
+211 875
+625 678
+698 1671
+942 1243
+129 250
+370 497
+725 1322
+195 1094
+382 1059
+973 1185
+877 1196
+863 1764
+645 1372
+4 484
+29 156
+802 1201
+195 1074
+261 1181
+139 1099
+768 1204
+882 1317
+107 693
+928 1275
+459 1071
+270 633
+384 906
+493 576
+909 1222
+212 437
+74 656
diff --git a/bottleneck/tests/data/test_827_B b/bottleneck/tests/data/test_827_B
new file mode 100644
index 0000000..57ea673
--- /dev/null
+++ b/bottleneck/tests/data/test_827_B
@@ -0,0 +1,30 @@
+804 1730
+244 333
+131 547
+866 1012
+364 546
+530 950
+702 824
+290 418
+636 795
+202 618
+858 1059
+140 687
+76 447
+60 499
+502 1080
+858 1704
+555 585
+503 1152
+151 787
+565 1211
+172 556
+322 422
+176 952
+333 572
+40 982
+656 1365
+553 1493
+600 680
+72 555
+711 769
diff --git a/bottleneck/tests/data/test_828_A b/bottleneck/tests/data/test_828_A
new file mode 100644
index 0000000..ee02128
--- /dev/null
+++ b/bottleneck/tests/data/test_828_A
@@ -0,0 +1,30 @@
+227 983
+778 1655
+311 1256
+462 911
+100 932
+411 895
+738 1086
+375 1308
+899 1896
+742 1425
+909 1290
+68 375
+148 195
+981 1120
+848 1463
+234 616
+45 314
+180 447
+368 1310
+443 734
+721 1345
+617 1376
+340 767
+420 1094
+848 979
+984 1866
+996 1169
+28 895
+203 1153
+535 1241
diff --git a/bottleneck/tests/data/test_828_B b/bottleneck/tests/data/test_828_B
new file mode 100644
index 0000000..92fae09
--- /dev/null
+++ b/bottleneck/tests/data/test_828_B
@@ -0,0 +1,30 @@
+309 789
+405 1405
+610 1330
+213 683
+768 1598
+843 1024
+898 1445
+625 1363
+557 996
+455 1026
+146 1137
+411 617
+155 969
+93 444
+92 206
+470 927
+792 1691
+871 984
+551 1271
+801 1755
+134 505
+270 1081
+382 852
+549 686
+2 314
+146 428
+460 1373
+602 1492
+950 1060
+516 1438
diff --git a/bottleneck/tests/data/test_829_A b/bottleneck/tests/data/test_829_A
new file mode 100644
index 0000000..fceb407
--- /dev/null
+++ b/bottleneck/tests/data/test_829_A
@@ -0,0 +1,30 @@
+222 1184
+346 478
+748 1587
+29 615
+190 1077
+889 1417
+381 1314
+388 448
+654 1525
+876 1242
+306 625
+289 660
+251 355
+4 963
+310 1154
+216 1065
+7 10
+75 525
+249 1084
+972 1796
+938 1780
+218 1156
+959 1810
+530 785
+562 1005
+483 751
+892 1440
+352 493
+676 1329
+718 1688
diff --git a/bottleneck/tests/data/test_829_B b/bottleneck/tests/data/test_829_B
new file mode 100644
index 0000000..85f538c
--- /dev/null
+++ b/bottleneck/tests/data/test_829_B
@@ -0,0 +1,30 @@
+910 1441
+681 1671
+845 1784
+354 1210
+4 180
+830 1486
+466 566
+808 1728
+1 589
+808 862
+404 543
+304 879
+618 1013
+905 1788
+912 1187
+228 604
+959 1487
+793 1275
+631 1205
+151 157
+984 1427
+244 578
+875 1741
+654 1288
+506 780
+827 1138
+213 928
+30 420
+670 1438
+448 737
diff --git a/bottleneck/tests/data/test_830_A b/bottleneck/tests/data/test_830_A
new file mode 100644
index 0000000..fd54955
--- /dev/null
+++ b/bottleneck/tests/data/test_830_A
@@ -0,0 +1,30 @@
+35 644
+830 1511
+414 677
+768 1461
+467 1032
+152 1060
+960 1807
+566 831
+550 1210
+521 1018
+250 651
+698 699
+979 1102
+555 1516
+463 1057
+739 896
+330 549
+412 775
+775 1433
+733 1438
+430 1342
+7 751
+338 943
+923 1173
+734 1460
+880 1453
+225 1004
+571 1375
+739 1085
+288 1202
diff --git a/bottleneck/tests/data/test_830_B b/bottleneck/tests/data/test_830_B
new file mode 100644
index 0000000..5b9d84b
--- /dev/null
+++ b/bottleneck/tests/data/test_830_B
@@ -0,0 +1,30 @@
+814 1305
+205 1199
+972 1431
+37 488
+673 1079
+630 1288
+698 828
+970 1666
+516 625
+65 209
+752 1716
+12 992
+563 1552
+821 1168
+460 943
+616 682
+386 546
+249 638
+583 1024
+38 889
+491 1020
+179 964
+995 1256
+861 1632
+252 518
+255 344
+480 1200
+89 711
+598 1022
+632 677
diff --git a/bottleneck/tests/data/test_831_A b/bottleneck/tests/data/test_831_A
new file mode 100644
index 0000000..fe09be1
--- /dev/null
+++ b/bottleneck/tests/data/test_831_A
@@ -0,0 +1,30 @@
+772 1298
+705 1567
+946 1693
+632 1045
+752 875
+919 1723
+657 884
+708 1156
+442 1086
+571 1454
+641 894
+371 1152
+762 952
+684 760
+275 369
+858 994
+485 730
+921 1267
+643 928
+353 1307
+384 406
+154 380
+299 998
+378 1208
+27 265
+948 1081
+551 1512
+50 308
+773 1297
+134 514
diff --git a/bottleneck/tests/data/test_831_B b/bottleneck/tests/data/test_831_B
new file mode 100644
index 0000000..1f4d148
--- /dev/null
+++ b/bottleneck/tests/data/test_831_B
@@ -0,0 +1,30 @@
+757 1588
+145 1094
+523 1331
+687 1430
+877 1046
+573 696
+359 1012
+711 734
+368 552
+588 1267
+231 702
+64 429
+901 1202
+93 467
+647 1449
+747 994
+364 692
+384 833
+143 390
+445 1283
+248 696
+397 451
+695 1014
+852 1363
+512 1491
+983 1278
+506 841
+533 1031
+26 813
+850 1601
diff --git a/bottleneck/tests/data/test_832_A b/bottleneck/tests/data/test_832_A
new file mode 100644
index 0000000..79d3383
--- /dev/null
+++ b/bottleneck/tests/data/test_832_A
@@ -0,0 +1,30 @@
+373 1269
+753 1101
+529 825
+462 539
+52 293
+878 1396
+67 683
+106 1096
+973 1589
+129 911
+556 1327
+743 1248
+687 1505
+804 1322
+338 703
+438 1149
+539 730
+802 1046
+462 803
+175 506
+382 796
+470 1219
+608 1146
+12 757
+713 1367
+719 1001
+451 585
+408 1308
+29 510
+67 866
diff --git a/bottleneck/tests/data/test_832_B b/bottleneck/tests/data/test_832_B
new file mode 100644
index 0000000..9106904
--- /dev/null
+++ b/bottleneck/tests/data/test_832_B
@@ -0,0 +1,30 @@
+239 1006
+358 806
+53 229
+529 931
+923 1837
+644 1410
+761 1240
+511 966
+639 1127
+874 1114
+604 995
+916 1100
+634 1043
+317 607
+43 613
+9 216
+349 1035
+48 193
+396 986
+809 1193
+307 832
+86 786
+934 1164
+534 1434
+960 1092
+13 799
+658 1056
+411 1382
+378 568
+808 1400
diff --git a/bottleneck/tests/data/test_833_A b/bottleneck/tests/data/test_833_A
new file mode 100644
index 0000000..1dbdd95
--- /dev/null
+++ b/bottleneck/tests/data/test_833_A
@@ -0,0 +1,30 @@
+505 885
+170 695
+258 297
+652 996
+987 1055
+937 1159
+846 1133
+984 1715
+243 1199
+596 827
+40 585
+589 1356
+305 943
+974 1253
+965 1615
+840 1238
+842 1407
+596 1296
+603 741
+839 966
+300 951
+852 1656
+783 1676
+45 631
+973 1199
+513 725
+133 391
+633 1132
+442 1271
+100 401
diff --git a/bottleneck/tests/data/test_833_B b/bottleneck/tests/data/test_833_B
new file mode 100644
index 0000000..a325070
--- /dev/null
+++ b/bottleneck/tests/data/test_833_B
@@ -0,0 +1,30 @@
+152 524
+210 255
+714 1034
+808 1480
+594 1020
+33 742
+285 562
+437 1341
+716 903
+767 1201
+146 938
+608 1275
+54 601
+752 1037
+896 1514
+113 321
+986 1932
+453 1382
+93 547
+687 1677
+134 1122
+5 268
+31 66
+832 1755
+313 966
+602 834
+433 679
+548 789
+414 1414
+734 1061
diff --git a/bottleneck/tests/data/test_834_A b/bottleneck/tests/data/test_834_A
new file mode 100644
index 0000000..7088d54
--- /dev/null
+++ b/bottleneck/tests/data/test_834_A
@@ -0,0 +1,30 @@
+709 1214
+541 1328
+291 925
+23 570
+334 447
+648 808
+532 1226
+315 509
+796 1147
+435 1417
+336 1183
+401 893
+184 721
+496 509
+274 841
+463 625
+906 1694
+512 1242
+617 1494
+874 1805
+162 621
+802 1074
+904 993
+124 653
+44 818
+577 1417
+520 1294
+574 709
+317 394
+643 1152
diff --git a/bottleneck/tests/data/test_834_B b/bottleneck/tests/data/test_834_B
new file mode 100644
index 0000000..5dd4204
--- /dev/null
+++ b/bottleneck/tests/data/test_834_B
@@ -0,0 +1,30 @@
+176 662
+579 764
+544 706
+68 939
+230 345
+901 1737
+714 1299
+482 1000
+290 802
+760 1461
+647 1412
+781 1498
+354 780
+697 818
+375 709
+794 1664
+989 1869
+320 729
+688 1029
+853 1290
+679 1504
+918 1749
+767 1734
+300 996
+625 900
+123 496
+89 408
+255 679
+329 1248
+659 1003
diff --git a/bottleneck/tests/data/test_835_A b/bottleneck/tests/data/test_835_A
new file mode 100644
index 0000000..47e934b
--- /dev/null
+++ b/bottleneck/tests/data/test_835_A
@@ -0,0 +1,30 @@
+554 1108
+257 549
+102 222
+531 715
+977 1231
+292 534
+624 1603
+394 508
+936 1007
+139 427
+457 1069
+873 1535
+789 887
+912 1213
+503 1307
+734 889
+789 1372
+811 1701
+558 1477
+485 763
+711 876
+961 1691
+294 635
+963 1955
+737 1563
+15 980
+23 339
+770 1156
+399 1341
+886 1049
diff --git a/bottleneck/tests/data/test_835_B b/bottleneck/tests/data/test_835_B
new file mode 100644
index 0000000..9a3edbe
--- /dev/null
+++ b/bottleneck/tests/data/test_835_B
@@ -0,0 +1,30 @@
+38 645
+994 1933
+145 1066
+900 1210
+691 1208
+672 959
+349 445
+567 1137
+547 1325
+943 1437
+591 712
+526 750
+2 227
+108 667
+137 722
+327 1192
+396 1374
+390 1069
+396 783
+927 1242
+870 1797
+532 1049
+543 1081
+470 917
+738 1731
+814 1558
+794 1555
+439 499
+593 1490
+349 410
diff --git a/bottleneck/tests/data/test_836_A b/bottleneck/tests/data/test_836_A
new file mode 100644
index 0000000..1a9885f
--- /dev/null
+++ b/bottleneck/tests/data/test_836_A
@@ -0,0 +1,30 @@
+790 1396
+959 1240
+518 1462
+797 1737
+356 649
+304 716
+773 1583
+888 1299
+355 801
+318 1109
+271 1257
+645 820
+292 1221
+792 968
+879 1494
+253 642
+105 802
+917 1305
+648 1646
+724 1157
+566 1056
+868 1437
+398 1098
+601 917
+436 1368
+26 933
+670 1615
+189 367
+79 1050
+955 1528
diff --git a/bottleneck/tests/data/test_836_B b/bottleneck/tests/data/test_836_B
new file mode 100644
index 0000000..8335ddf
--- /dev/null
+++ b/bottleneck/tests/data/test_836_B
@@ -0,0 +1,30 @@
+135 337
+332 1300
+859 1117
+591 988
+441 1441
+174 635
+78 703
+10 648
+188 422
+292 830
+492 1179
+104 276
+263 640
+63 760
+993 1248
+107 644
+723 747
+85 698
+276 410
+407 735
+229 810
+512 561
+802 1555
+542 818
+666 1499
+383 754
+132 216
+581 723
+775 1446
+908 1029
diff --git a/bottleneck/tests/data/test_837_A b/bottleneck/tests/data/test_837_A
new file mode 100644
index 0000000..8d3facc
--- /dev/null
+++ b/bottleneck/tests/data/test_837_A
@@ -0,0 +1,30 @@
+456 998
+976 1929
+745 1606
+77 375
+149 692
+508 1466
+68 113
+493 1163
+185 1109
+761 1172
+313 1261
+508 1091
+122 834
+766 1333
+996 1208
+161 468
+688 903
+551 744
+745 1522
+579 1022
+149 722
+458 652
+8 758
+801 1344
+96 696
+589 1125
+589 989
+941 1492
+851 1168
+670 728
diff --git a/bottleneck/tests/data/test_837_B b/bottleneck/tests/data/test_837_B
new file mode 100644
index 0000000..8439a1f
--- /dev/null
+++ b/bottleneck/tests/data/test_837_B
@@ -0,0 +1,30 @@
+102 508
+437 603
+199 669
+853 1602
+106 722
+732 771
+301 538
+505 988
+731 1707
+276 1142
+923 1449
+366 1330
+221 833
+107 174
+914 1231
+651 1411
+137 666
+781 1074
+459 655
+509 1344
+74 234
+927 1739
+960 1461
+556 608
+644 805
+457 971
+992 1522
+798 887
+147 944
+96 111
diff --git a/bottleneck/tests/data/test_838_A b/bottleneck/tests/data/test_838_A
new file mode 100644
index 0000000..9f6e83e
--- /dev/null
+++ b/bottleneck/tests/data/test_838_A
@@ -0,0 +1,30 @@
+918 952
+225 1163
+801 1184
+786 1485
+512 747
+389 756
+966 1924
+542 720
+742 1207
+329 891
+273 1268
+701 1015
+29 682
+303 1139
+716 1617
+362 1135
+540 1071
+58 497
+725 1445
+46 688
+931 1327
+467 1229
+303 916
+702 1067
+862 1258
+535 1347
+640 1252
+619 1377
+702 1237
+971 1779
diff --git a/bottleneck/tests/data/test_838_B b/bottleneck/tests/data/test_838_B
new file mode 100644
index 0000000..227776e
--- /dev/null
+++ b/bottleneck/tests/data/test_838_B
@@ -0,0 +1,30 @@
+898 1448
+295 893
+829 1147
+149 339
+529 1046
+729 1258
+602 1296
+571 672
+953 1890
+26 777
+984 1487
+879 1533
+456 1103
+741 1227
+235 718
+65 102
+432 1037
+307 824
+977 1325
+275 582
+753 1683
+809 1622
+63 478
+648 1273
+945 1446
+234 843
+354 1134
+298 1160
+471 882
+911 1296
diff --git a/bottleneck/tests/data/test_839_A b/bottleneck/tests/data/test_839_A
new file mode 100644
index 0000000..073be3c
--- /dev/null
+++ b/bottleneck/tests/data/test_839_A
@@ -0,0 +1,30 @@
+488 765
+890 1359
+573 1009
+876 1603
+430 1408
+774 1380
+786 881
+392 1227
+506 755
+844 1516
+716 1555
+697 1415
+816 908
+981 1231
+775 1437
+224 582
+657 1045
+937 1441
+428 682
+865 1547
+802 1736
+700 1196
+881 1569
+507 875
+884 1852
+176 345
+278 338
+78 384
+562 781
+463 1403
diff --git a/bottleneck/tests/data/test_839_B b/bottleneck/tests/data/test_839_B
new file mode 100644
index 0000000..ca5ee3e
--- /dev/null
+++ b/bottleneck/tests/data/test_839_B
@@ -0,0 +1,30 @@
+768 1077
+971 1887
+547 1058
+468 905
+54 250
+727 782
+101 407
+111 1085
+637 826
+209 531
+690 1134
+989 1111
+817 848
+862 952
+530 679
+431 823
+958 1666
+973 1598
+423 766
+42 736
+833 1832
+206 848
+148 336
+804 1691
+186 361
+53 288
+449 1314
+618 904
+759 1339
+8 923
diff --git a/bottleneck/tests/data/test_840_A b/bottleneck/tests/data/test_840_A
new file mode 100644
index 0000000..02ed823
--- /dev/null
+++ b/bottleneck/tests/data/test_840_A
@@ -0,0 +1,50 @@
+121 1010
+730 1566
+866 872
+984 1105
+12 455
+503 963
+956 1410
+986 1887
+929 1377
+809 823
+129 1090
+545 640
+641 921
+786 916
+222 474
+464 677
+357 1055
+199 1046
+327 892
+449 1272
+564 1505
+867 1494
+383 585
+617 1200
+254 997
+528 994
+458 507
+250 1217
+141 1104
+710 1191
+565 1355
+959 1876
+323 665
+290 1141
+749 1035
+641 817
+855 1596
+296 610
+144 215
+563 776
+77 599
+380 1160
+720 811
+55 905
+389 830
+268 1170
+579 1272
+240 811
+552 737
+498 844
diff --git a/bottleneck/tests/data/test_840_B b/bottleneck/tests/data/test_840_B
new file mode 100644
index 0000000..4bd5737
--- /dev/null
+++ b/bottleneck/tests/data/test_840_B
@@ -0,0 +1,50 @@
+156 272
+847 1154
+32 482
+781 1129
+956 1017
+429 1305
+312 1054
+11 979
+495 1463
+645 1524
+521 901
+685 1414
+741 1123
+179 428
+475 1073
+360 1315
+435 524
+897 1422
+668 1253
+538 802
+79 329
+791 1484
+557 772
+831 950
+640 666
+196 358
+214 394
+738 1566
+788 1752
+932 1820
+853 1847
+561 1446
+671 1490
+792 1123
+892 1481
+9 650
+92 308
+760 1021
+807 1449
+721 1693
+932 1892
+674 734
+837 1338
+313 507
+300 686
+264 1045
+210 788
+426 1169
+354 1154
+711 1322
diff --git a/bottleneck/tests/data/test_841_A b/bottleneck/tests/data/test_841_A
new file mode 100644
index 0000000..d6b2c08
--- /dev/null
+++ b/bottleneck/tests/data/test_841_A
@@ -0,0 +1,50 @@
+932 1449
+350 597
+425 503
+858 1265
+781 1372
+293 300
+593 806
+958 1619
+647 819
+598 1284
+160 571
+651 955
+521 1143
+906 1546
+848 1529
+729 1180
+990 1245
+54 398
+404 1096
+88 896
+679 1094
+737 1504
+609 1460
+32 747
+338 1060
+565 1216
+637 1537
+449 1042
+889 1510
+184 241
+103 584
+136 919
+503 659
+848 1333
+890 941
+360 836
+418 506
+750 994
+963 1068
+712 1501
+331 396
+515 617
+555 728
+81 401
+186 654
+934 1122
+649 843
+953 1342
+316 622
+866 1234
diff --git a/bottleneck/tests/data/test_841_B b/bottleneck/tests/data/test_841_B
new file mode 100644
index 0000000..9775dd8
--- /dev/null
+++ b/bottleneck/tests/data/test_841_B
@@ -0,0 +1,50 @@
+381 908
+662 956
+316 894
+326 664
+655 1453
+261 430
+385 866
+630 1168
+117 237
+603 1595
+19 419
+375 1154
+982 1372
+897 1324
+347 687
+868 1049
+53 1031
+722 1078
+918 1107
+675 1326
+485 505
+777 1032
+76 273
+231 1113
+751 1180
+937 1635
+156 873
+641 1316
+632 1052
+54 1021
+993 1159
+905 1039
+606 1293
+235 364
+530 540
+326 843
+636 1442
+474 814
+176 942
+924 1685
+668 817
+560 1090
+805 1794
+679 1076
+409 1108
+582 1311
+21 449
+142 622
+614 1153
+570 908
diff --git a/bottleneck/tests/data/test_842_A b/bottleneck/tests/data/test_842_A
new file mode 100644
index 0000000..49124dc
--- /dev/null
+++ b/bottleneck/tests/data/test_842_A
@@ -0,0 +1,50 @@
+205 815
+309 971
+468 1170
+602 1127
+239 434
+403 631
+80 500
+14 864
+594 1199
+406 407
+30 360
+188 993
+381 1063
+175 1087
+357 1063
+153 1117
+600 1365
+662 1189
+513 744
+339 1332
+860 1720
+897 1406
+462 808
+191 234
+542 729
+425 738
+159 160
+821 1536
+327 355
+616 1302
+699 1148
+870 1512
+810 1146
+448 564
+881 1246
+364 833
+889 1160
+102 175
+385 731
+86 659
+14 321
+257 1193
+685 1606
+174 925
+165 1021
+116 419
+775 1510
+53 614
+18 39
+561 670
diff --git a/bottleneck/tests/data/test_842_B b/bottleneck/tests/data/test_842_B
new file mode 100644
index 0000000..36715f2
--- /dev/null
+++ b/bottleneck/tests/data/test_842_B
@@ -0,0 +1,50 @@
+577 1182
+779 1169
+525 1384
+851 968
+906 1679
+221 445
+494 653
+813 1061
+478 1174
+37 224
+700 1239
+338 855
+82 670
+159 872
+932 1231
+89 411
+869 1484
+708 966
+814 1075
+108 203
+603 691
+797 1680
+869 1223
+162 165
+281 333
+650 721
+200 665
+692 1332
+497 1331
+948 1098
+351 1188
+844 1508
+319 762
+302 442
+320 617
+220 649
+498 882
+411 711
+833 1373
+943 1586
+310 544
+24 818
+485 903
+58 1028
+84 1023
+69 823
+399 634
+755 945
+460 764
+583 800
diff --git a/bottleneck/tests/data/test_843_A b/bottleneck/tests/data/test_843_A
new file mode 100644
index 0000000..aa5cea9
--- /dev/null
+++ b/bottleneck/tests/data/test_843_A
@@ -0,0 +1,50 @@
+855 1686
+375 653
+487 968
+501 1179
+269 747
+102 128
+756 1241
+934 1507
+707 1166
+438 644
+215 482
+186 1134
+588 1179
+323 806
+260 948
+999 1181
+809 866
+383 618
+667 1211
+697 1543
+216 289
+618 1318
+230 633
+261 439
+36 430
+926 1424
+573 1382
+545 1489
+198 254
+997 1313
+625 1138
+71 216
+123 152
+966 1260
+583 1455
+685 1595
+319 803
+809 1754
+543 672
+973 1482
+282 1191
+94 413
+933 1847
+593 770
+384 463
+301 531
+306 832
+645 679
+863 1024
+257 716
diff --git a/bottleneck/tests/data/test_843_B b/bottleneck/tests/data/test_843_B
new file mode 100644
index 0000000..b14eed6
--- /dev/null
+++ b/bottleneck/tests/data/test_843_B
@@ -0,0 +1,50 @@
+36 726
+683 1328
+991 1393
+822 1642
+499 1065
+41 726
+770 903
+83 190
+993 1392
+584 1281
+520 643
+878 1560
+461 694
+715 1155
+752 1593
+592 622
+8 746
+280 816
+571 797
+24 712
+799 1664
+988 1479
+397 1339
+827 1088
+466 1179
+701 1236
+841 1384
+360 1235
+425 739
+982 1503
+188 345
+161 405
+366 1067
+245 975
+834 1160
+19 508
+594 1292
+149 267
+201 891
+22 922
+984 1108
+731 1251
+871 1092
+946 1519
+772 1388
+738 1194
+924 1862
+35 765
+904 1276
+190 235
diff --git a/bottleneck/tests/data/test_844_A b/bottleneck/tests/data/test_844_A
new file mode 100644
index 0000000..753b2fc
--- /dev/null
+++ b/bottleneck/tests/data/test_844_A
@@ -0,0 +1,50 @@
+207 275
+665 774
+655 1360
+274 366
+83 646
+435 599
+479 793
+74 1043
+604 1048
+106 557
+885 1524
+694 1680
+770 833
+38 261
+6 547
+893 1287
+732 1589
+343 1201
+531 1088
+962 1666
+979 1708
+206 538
+73 114
+354 1140
+220 330
+299 833
+694 883
+651 701
+256 425
+551 612
+709 1304
+806 1613
+193 901
+29 916
+257 313
+806 1193
+205 530
+981 1851
+878 1208
+327 799
+958 1874
+783 1109
+466 537
+349 1191
+410 630
+513 837
+587 1033
+777 1202
+90 503
+893 1737
diff --git a/bottleneck/tests/data/test_844_B b/bottleneck/tests/data/test_844_B
new file mode 100644
index 0000000..373d26c
--- /dev/null
+++ b/bottleneck/tests/data/test_844_B
@@ -0,0 +1,50 @@
+67 793
+551 1443
+572 1395
+51 149
+805 920
+541 1479
+365 1244
+997 1447
+234 900
+144 1068
+418 929
+720 903
+155 219
+937 1905
+371 1112
+983 1372
+607 1244
+259 1217
+708 850
+992 1713
+398 968
+0 588
+167 742
+465 577
+188 892
+924 1045
+103 892
+489 1072
+170 195
+448 1141
+990 1075
+880 894
+703 1565
+318 785
+843 1614
+326 995
+104 185
+333 1186
+483 631
+246 797
+407 701
+333 545
+73 181
+591 1202
+851 1721
+615 1260
+504 1421
+472 486
+65 189
+986 1801
diff --git a/bottleneck/tests/data/test_845_A b/bottleneck/tests/data/test_845_A
new file mode 100644
index 0000000..2015fbb
--- /dev/null
+++ b/bottleneck/tests/data/test_845_A
@@ -0,0 +1,50 @@
+446 1114
+872 1568
+544 1415
+144 507
+256 602
+208 382
+899 1217
+756 1597
+428 574
+201 843
+609 770
+443 531
+479 955
+959 1238
+821 1798
+564 1526
+26 545
+264 633
+34 527
+153 213
+215 703
+925 964
+651 1041
+32 797
+234 1162
+166 544
+407 981
+817 1528
+883 1412
+867 1173
+327 358
+326 330
+540 1054
+632 1503
+632 1465
+240 799
+954 1859
+214 374
+546 1395
+914 1529
+680 1588
+367 377
+890 971
+289 1247
+31 846
+810 1172
+658 1366
+537 1089
+256 1134
+16 1008
diff --git a/bottleneck/tests/data/test_845_B b/bottleneck/tests/data/test_845_B
new file mode 100644
index 0000000..b053f52
--- /dev/null
+++ b/bottleneck/tests/data/test_845_B
@@ -0,0 +1,50 @@
+537 582
+313 723
+386 619
+121 1100
+466 1044
+502 581
+16 838
+599 1395
+899 1523
+589 591
+36 928
+896 1718
+16 252
+99 722
+925 1343
+328 1244
+245 973
+596 1499
+122 763
+945 1563
+38 452
+680 890
+499 1247
+295 803
+385 1357
+885 1780
+597 637
+193 313
+951 1019
+679 1344
+991 1447
+697 1551
+834 1223
+57 795
+657 775
+374 1093
+187 398
+706 1353
+904 1801
+538 932
+843 1632
+370 1250
+590 957
+996 1385
+364 714
+307 689
+866 1687
+547 1072
+451 864
+746 900
diff --git a/bottleneck/tests/data/test_846_A b/bottleneck/tests/data/test_846_A
new file mode 100644
index 0000000..520c6d4
--- /dev/null
+++ b/bottleneck/tests/data/test_846_A
@@ -0,0 +1,50 @@
+659 889
+754 1573
+955 1466
+177 454
+109 235
+107 1086
+741 949
+689 1029
+288 564
+987 1133
+235 240
+398 1178
+27 395
+483 863
+509 1192
+920 1870
+732 1501
+494 1321
+190 362
+278 778
+726 1309
+397 1117
+7 888
+514 1366
+598 902
+48 950
+103 506
+770 1359
+689 1403
+340 1072
+191 850
+512 742
+441 507
+67 201
+50 781
+649 1619
+457 843
+756 993
+343 361
+505 1029
+687 707
+496 1371
+854 990
+555 1488
+217 249
+477 837
+150 258
+514 1286
+170 982
+160 521
diff --git a/bottleneck/tests/data/test_846_B b/bottleneck/tests/data/test_846_B
new file mode 100644
index 0000000..3046f20
--- /dev/null
+++ b/bottleneck/tests/data/test_846_B
@@ -0,0 +1,50 @@
+701 1467
+679 1557
+705 1082
+845 1787
+776 824
+890 1825
+867 1265
+105 710
+282 1235
+900 1455
+598 1253
+642 794
+304 961
+492 778
+16 233
+301 1249
+524 1358
+884 1577
+542 1423
+856 1110
+768 883
+226 755
+18 940
+846 916
+512 1411
+598 1196
+841 1345
+306 891
+571 981
+353 918
+840 1652
+886 1748
+269 1233
+940 1583
+364 1070
+187 683
+350 1141
+730 1223
+333 701
+284 449
+846 1539
+509 1400
+21 696
+543 778
+714 1428
+304 348
+475 1353
+594 1122
+426 946
+418 1312
diff --git a/bottleneck/tests/data/test_847_A b/bottleneck/tests/data/test_847_A
new file mode 100644
index 0000000..ee5c8c1
--- /dev/null
+++ b/bottleneck/tests/data/test_847_A
@@ -0,0 +1,50 @@
+780 1633
+384 1190
+605 779
+787 1716
+504 698
+879 1796
+446 1258
+386 649
+830 1220
+576 717
+888 1126
+457 1259
+975 1588
+717 1266
+737 914
+103 695
+906 1516
+454 516
+696 899
+43 921
+613 781
+325 858
+655 1647
+72 601
+143 707
+293 1064
+13 310
+610 1021
+975 1576
+185 1017
+983 1261
+197 286
+68 472
+997 1630
+197 1191
+11 58
+804 1741
+364 519
+977 1124
+557 1184
+727 1681
+652 918
+928 1838
+675 1074
+551 976
+320 1244
+675 1477
+962 1898
+843 1490
+449 640
diff --git a/bottleneck/tests/data/test_847_B b/bottleneck/tests/data/test_847_B
new file mode 100644
index 0000000..de6f45a
--- /dev/null
+++ b/bottleneck/tests/data/test_847_B
@@ -0,0 +1,50 @@
+198 500
+390 1022
+911 1544
+842 1778
+213 793
+173 1093
+61 455
+340 1005
+905 1418
+814 1236
+476 518
+133 382
+291 1249
+350 359
+967 1585
+441 810
+324 836
+769 1325
+828 1770
+758 1471
+9 499
+649 882
+418 1135
+28 97
+703 1400
+316 535
+799 1286
+16 348
+323 536
+113 864
+248 745
+468 597
+689 1618
+278 1208
+978 1589
+339 402
+232 442
+236 928
+856 1570
+709 1560
+34 260
+810 1365
+787 1781
+675 1043
+800 1255
+479 1118
+363 592
+97 729
+929 1430
+860 1219
diff --git a/bottleneck/tests/data/test_848_A b/bottleneck/tests/data/test_848_A
new file mode 100644
index 0000000..e9e603b
--- /dev/null
+++ b/bottleneck/tests/data/test_848_A
@@ -0,0 +1,50 @@
+697 1454
+137 892
+466 950
+881 1230
+539 1162
+247 1065
+859 1032
+861 1215
+8 142
+772 1757
+458 1102
+382 730
+166 1086
+606 1008
+74 82
+967 1701
+562 1019
+648 764
+759 1745
+483 1208
+501 808
+942 1717
+569 888
+686 1292
+68 796
+504 1268
+655 1529
+335 451
+139 339
+709 1570
+238 542
+999 1912
+904 1545
+735 1386
+265 909
+935 1749
+745 787
+397 1083
+295 963
+12 523
+769 943
+998 1204
+531 1528
+596 1140
+173 1030
+810 1356
+728 750
+554 1185
+334 643
+879 1368
diff --git a/bottleneck/tests/data/test_848_B b/bottleneck/tests/data/test_848_B
new file mode 100644
index 0000000..00005be
--- /dev/null
+++ b/bottleneck/tests/data/test_848_B
@@ -0,0 +1,50 @@
+885 1435
+500 978
+291 765
+353 1157
+527 1446
+734 904
+302 393
+199 918
+561 744
+96 349
+338 631
+503 1162
+286 589
+492 544
+826 1742
+924 1340
+707 877
+691 1487
+883 1530
+233 810
+73 252
+192 595
+271 491
+915 1426
+128 781
+906 1244
+268 308
+979 1349
+823 1647
+993 1177
+318 961
+619 1143
+857 1682
+92 110
+676 1202
+485 1468
+968 1064
+565 634
+49 1043
+487 1316
+668 1425
+552 1443
+589 655
+515 850
+858 1826
+514 779
+322 506
+422 996
+213 1013
+897 1711
diff --git a/bottleneck/tests/data/test_849_A b/bottleneck/tests/data/test_849_A
new file mode 100644
index 0000000..7938a96
--- /dev/null
+++ b/bottleneck/tests/data/test_849_A
@@ -0,0 +1,50 @@
+785 1228
+858 997
+734 1553
+888 1700
+553 1433
+352 385
+851 1468
+803 950
+358 715
+376 1290
+419 784
+38 689
+504 1285
+250 768
+344 1015
+295 1063
+501 1219
+995 1383
+781 1320
+260 1154
+290 942
+683 918
+623 1468
+74 654
+742 1201
+919 974
+718 1316
+591 821
+864 1035
+591 951
+922 1553
+751 1468
+57 832
+809 1103
+243 322
+605 919
+947 1101
+7 1003
+655 1586
+737 1610
+537 935
+185 455
+466 834
+160 599
+386 1035
+381 448
+841 1005
+898 1693
+493 729
+506 685
diff --git a/bottleneck/tests/data/test_849_B b/bottleneck/tests/data/test_849_B
new file mode 100644
index 0000000..21da75d
--- /dev/null
+++ b/bottleneck/tests/data/test_849_B
@@ -0,0 +1,50 @@
+87 1055
+578 1265
+657 1071
+939 1551
+679 1032
+768 1665
+668 1163
+689 1159
+229 1083
+358 1158
+515 595
+972 1301
+764 1428
+551 1533
+770 929
+104 172
+948 1359
+48 854
+510 995
+914 1735
+228 440
+854 1064
+351 908
+664 1290
+919 1050
+882 1794
+472 819
+826 1133
+279 944
+363 1081
+296 934
+227 749
+172 931
+583 1524
+409 848
+284 804
+436 1098
+96 768
+632 646
+832 1167
+862 1470
+544 1519
+889 1030
+422 1414
+948 1105
+967 1273
+552 589
+986 1793
+52 252
+430 864
diff --git a/bottleneck/tests/data/test_850_A b/bottleneck/tests/data/test_850_A
new file mode 100644
index 0000000..dfb2165
--- /dev/null
+++ b/bottleneck/tests/data/test_850_A
@@ -0,0 +1,50 @@
+819 907
+322 836
+10 262
+950 1844
+280 419
+724 1489
+982 1737
+183 305
+393 1066
+958 1033
+328 554
+609 1374
+512 835
+563 1444
+671 972
+161 838
+631 851
+867 1362
+995 1134
+990 1841
+479 839
+439 502
+408 917
+879 1633
+725 863
+271 614
+757 1203
+70 980
+745 841
+739 1679
+269 934
+926 1412
+977 1200
+532 1251
+607 708
+524 726
+737 983
+700 1200
+715 1247
+301 596
+136 869
+290 397
+88 764
+250 945
+0 378
+595 1513
+612 874
+706 757
+353 712
+509 953
diff --git a/bottleneck/tests/data/test_850_B b/bottleneck/tests/data/test_850_B
new file mode 100644
index 0000000..573788d
--- /dev/null
+++ b/bottleneck/tests/data/test_850_B
@@ -0,0 +1,50 @@
+602 1008
+42 926
+253 1183
+404 631
+779 1700
+698 1638
+92 1004
+296 370
+204 378
+225 593
+685 1259
+982 1447
+544 951
+682 1653
+449 1092
+664 1035
+856 1428
+658 1320
+615 1113
+83 285
+276 745
+297 363
+590 732
+547 999
+440 901
+337 830
+492 595
+487 1018
+159 1115
+853 1350
+139 377
+9 573
+47 505
+187 480
+374 510
+831 1626
+948 1484
+450 1028
+840 1390
+132 288
+472 1025
+74 260
+281 518
+95 248
+699 735
+275 1183
+802 971
+119 1091
+709 1224
+397 855
diff --git a/bottleneck/tests/data/test_851_A b/bottleneck/tests/data/test_851_A
new file mode 100644
index 0000000..0a2f88e
--- /dev/null
+++ b/bottleneck/tests/data/test_851_A
@@ -0,0 +1,50 @@
+390 859
+367 1332
+230 1179
+734 1289
+67 554
+186 319
+787 841
+516 1218
+616 1597
+551 1223
+669 862
+265 888
+24 428
+841 1616
+816 1058
+922 1460
+749 1311
+734 1658
+581 973
+780 1708
+99 1091
+851 1503
+161 1118
+944 1804
+456 458
+395 1163
+880 1842
+850 1397
+359 461
+996 1098
+337 1164
+975 994
+512 816
+436 648
+42 59
+586 841
+48 65
+352 821
+58 171
+870 1085
+639 763
+415 1274
+549 913
+37 47
+820 1311
+120 854
+924 1272
+325 800
+483 888
+167 512
diff --git a/bottleneck/tests/data/test_851_B b/bottleneck/tests/data/test_851_B
new file mode 100644
index 0000000..8e4b97e
--- /dev/null
+++ b/bottleneck/tests/data/test_851_B
@@ -0,0 +1,50 @@
+173 900
+214 742
+715 941
+288 723
+561 1288
+482 789
+555 1396
+244 1162
+24 229
+897 1127
+809 1700
+785 1558
+76 361
+453 827
+61 728
+600 986
+237 887
+720 1191
+834 1643
+576 1344
+764 1307
+417 1377
+780 1174
+187 235
+776 1010
+952 970
+377 1184
+454 979
+758 970
+330 1179
+364 1105
+101 909
+481 692
+579 1234
+623 1088
+425 464
+360 503
+534 882
+363 1011
+973 1732
+413 504
+171 514
+89 282
+430 1044
+531 610
+713 873
+737 1131
+807 1603
+584 1034
+887 1189
diff --git a/bottleneck/tests/data/test_852_A b/bottleneck/tests/data/test_852_A
new file mode 100644
index 0000000..3d8f706
--- /dev/null
+++ b/bottleneck/tests/data/test_852_A
@@ -0,0 +1,50 @@
+473 535
+32 734
+940 1633
+31 264
+217 284
+963 1618
+780 1453
+436 606
+958 1899
+509 1436
+1000 1824
+793 889
+667 1236
+647 1383
+588 1280
+682 1431
+617 765
+740 799
+640 1082
+724 1466
+540 1456
+772 1324
+551 1437
+270 1096
+709 1110
+317 876
+6 185
+612 686
+220 1032
+55 414
+272 669
+233 973
+264 825
+58 779
+92 330
+837 910
+106 237
+980 1316
+806 1161
+433 1270
+304 900
+569 882
+459 563
+991 1221
+33 686
+228 429
+527 542
+911 1456
+395 938
+825 1625
diff --git a/bottleneck/tests/data/test_852_B b/bottleneck/tests/data/test_852_B
new file mode 100644
index 0000000..9de826f
--- /dev/null
+++ b/bottleneck/tests/data/test_852_B
@@ -0,0 +1,50 @@
+380 777
+698 1291
+826 1366
+108 741
+88 586
+50 631
+333 860
+51 355
+746 1232
+864 1129
+312 868
+514 591
+818 940
+561 1106
+997 1618
+986 1648
+417 1273
+544 1325
+343 1332
+852 1788
+740 1072
+890 957
+880 1540
+110 1072
+969 1706
+964 1771
+366 1347
+542 631
+863 1294
+216 864
+766 1148
+436 1431
+227 989
+694 786
+216 801
+119 946
+607 1270
+300 1178
+338 572
+374 509
+233 934
+531 542
+174 504
+521 738
+837 1202
+231 528
+595 1041
+530 1474
+218 852
+874 1675
diff --git a/bottleneck/tests/data/test_853_A b/bottleneck/tests/data/test_853_A
new file mode 100644
index 0000000..bcf5afe
--- /dev/null
+++ b/bottleneck/tests/data/test_853_A
@@ -0,0 +1,50 @@
+200 886
+263 814
+456 853
+495 694
+864 1233
+80 743
+147 356
+164 450
+250 1230
+759 792
+417 1228
+572 1002
+854 1634
+806 1057
+522 1196
+684 1295
+999 1547
+301 1014
+772 1685
+816 923
+820 876
+118 348
+340 849
+686 824
+874 1610
+510 1503
+602 1309
+677 1497
+146 1008
+853 1484
+729 1333
+617 1097
+511 935
+143 938
+485 552
+433 980
+859 1077
+3 717
+176 1136
+436 1213
+163 418
+505 889
+303 689
+837 1225
+296 345
+814 1699
+603 1524
+679 1224
+729 1714
+760 953
diff --git a/bottleneck/tests/data/test_853_B b/bottleneck/tests/data/test_853_B
new file mode 100644
index 0000000..d294f05
--- /dev/null
+++ b/bottleneck/tests/data/test_853_B
@@ -0,0 +1,50 @@
+223 899
+821 1752
+179 260
+757 1350
+661 1211
+397 1004
+114 557
+579 1379
+752 1531
+292 818
+459 580
+715 1007
+849 1067
+495 1197
+803 991
+588 1569
+362 1316
+38 961
+899 1762
+325 906
+411 1364
+320 1221
+301 674
+811 1126
+464 1441
+220 1130
+514 784
+196 240
+946 1543
+614 928
+610 626
+628 1059
+576 829
+363 1272
+338 888
+470 497
+767 824
+578 645
+136 573
+563 731
+794 1510
+466 1243
+341 1080
+34 787
+901 1260
+339 1068
+406 746
+135 590
+507 1272
+705 756
diff --git a/bottleneck/tests/data/test_854_A b/bottleneck/tests/data/test_854_A
new file mode 100644
index 0000000..4765953
--- /dev/null
+++ b/bottleneck/tests/data/test_854_A
@@ -0,0 +1,50 @@
+670 1518
+858 1578
+59 559
+503 768
+14 876
+830 858
+978 1670
+648 1003
+620 1028
+522 809
+678 1574
+303 1157
+238 748
+886 987
+445 1100
+994 1772
+50 602
+134 315
+885 1274
+862 1737
+369 1231
+199 594
+611 1387
+517 1513
+731 865
+357 1222
+137 822
+894 1389
+839 1547
+962 1432
+170 512
+596 907
+480 545
+416 889
+311 1213
+897 1057
+394 1075
+943 1054
+342 1014
+137 742
+163 843
+655 763
+642 1182
+753 1458
+200 958
+289 311
+726 808
+614 1330
+796 1506
+292 555
diff --git a/bottleneck/tests/data/test_854_B b/bottleneck/tests/data/test_854_B
new file mode 100644
index 0000000..aa949eb
--- /dev/null
+++ b/bottleneck/tests/data/test_854_B
@@ -0,0 +1,50 @@
+232 702
+892 1789
+441 1152
+710 975
+908 1187
+315 530
+255 334
+502 1485
+820 1718
+531 1002
+694 1032
+183 594
+924 1037
+948 1015
+465 906
+854 1761
+257 924
+588 1298
+382 1070
+315 646
+68 997
+924 1788
+927 1813
+522 1496
+667 1585
+884 1720
+373 1104
+140 1087
+988 1426
+690 796
+538 1095
+458 489
+685 805
+554 1389
+708 1480
+155 566
+704 891
+194 356
+607 1330
+512 725
+343 985
+660 1310
+117 1001
+454 1189
+554 1122
+722 1493
+805 1093
+60 419
+403 1277
+847 1750
diff --git a/bottleneck/tests/data/test_855_A b/bottleneck/tests/data/test_855_A
new file mode 100644
index 0000000..ab7ec0b
--- /dev/null
+++ b/bottleneck/tests/data/test_855_A
@@ -0,0 +1,50 @@
+614 654
+663 1260
+449 1202
+762 985
+173 235
+219 556
+230 1224
+569 739
+65 145
+814 1671
+395 1280
+224 1211
+349 1209
+628 1611
+680 1532
+644 1398
+971 1611
+574 1353
+832 1740
+866 1082
+822 1654
+786 1770
+200 1071
+709 1343
+955 1924
+78 546
+168 872
+251 735
+505 1392
+719 799
+321 327
+823 1682
+327 788
+85 640
+423 1306
+581 665
+476 665
+257 926
+305 600
+828 1419
+957 1645
+22 783
+760 1281
+890 1141
+756 1272
+852 1339
+162 1155
+661 1360
+328 597
+81 549
diff --git a/bottleneck/tests/data/test_855_B b/bottleneck/tests/data/test_855_B
new file mode 100644
index 0000000..be6ff94
--- /dev/null
+++ b/bottleneck/tests/data/test_855_B
@@ -0,0 +1,50 @@
+758 1131
+201 805
+622 704
+457 770
+211 1153
+604 1593
+658 1229
+845 1733
+3 55
+813 1682
+926 1122
+87 399
+415 1287
+943 1357
+538 884
+39 447
+678 1201
+469 977
+445 1406
+931 992
+137 843
+914 1789
+736 1382
+933 1376
+426 1190
+332 715
+385 1226
+727 1493
+972 1306
+674 1674
+801 1277
+542 1301
+591 1067
+318 1136
+90 552
+168 232
+814 1715
+860 1249
+104 353
+841 1674
+775 1615
+517 693
+103 261
+472 517
+56 570
+767 1433
+839 1303
+683 1605
+311 700
+89 256
diff --git a/bottleneck/tests/data/test_856_A b/bottleneck/tests/data/test_856_A
new file mode 100644
index 0000000..3cbfae3
--- /dev/null
+++ b/bottleneck/tests/data/test_856_A
@@ -0,0 +1,50 @@
+719 1457
+209 663
+890 1735
+774 1570
+582 935
+231 1051
+723 1681
+341 1197
+4 150
+30 263
+38 984
+950 1487
+523 609
+453 854
+956 1422
+180 436
+690 966
+848 1237
+972 1095
+120 843
+523 1438
+49 182
+294 622
+586 1385
+750 786
+856 1407
+327 1270
+655 957
+373 1358
+372 785
+727 1497
+308 567
+784 1046
+315 913
+862 1742
+699 1337
+24 662
+407 455
+24 393
+913 1501
+13 1005
+709 1107
+264 1079
+107 781
+275 805
+164 179
+445 1355
+907 1785
+571 629
+953 1080
diff --git a/bottleneck/tests/data/test_856_B b/bottleneck/tests/data/test_856_B
new file mode 100644
index 0000000..ec34ae9
--- /dev/null
+++ b/bottleneck/tests/data/test_856_B
@@ -0,0 +1,50 @@
+724 1643
+458 1388
+638 1303
+431 1405
+710 861
+659 723
+714 1351
+402 1186
+730 1584
+304 788
+845 850
+331 451
+421 1121
+821 1257
+2 923
+246 1167
+776 1109
+307 963
+553 1262
+841 1061
+27 290
+507 1297
+471 935
+583 1176
+781 955
+286 703
+178 303
+674 1372
+942 968
+521 1497
+6 593
+198 375
+263 1085
+486 1143
+807 1093
+17 795
+921 1559
+577 1316
+45 282
+670 1319
+228 400
+480 1047
+477 1308
+971 1055
+336 396
+731 941
+995 1354
+535 1309
+648 1642
+441 1432
diff --git a/bottleneck/tests/data/test_857_A b/bottleneck/tests/data/test_857_A
new file mode 100644
index 0000000..6bbbf0b
--- /dev/null
+++ b/bottleneck/tests/data/test_857_A
@@ -0,0 +1,50 @@
+155 1103
+527 601
+613 714
+27 82
+288 1267
+522 713
+839 925
+554 1132
+148 255
+692 1319
+216 257
+11 251
+199 862
+371 724
+728 1561
+314 918
+452 540
+30 958
+745 1698
+434 1341
+469 1469
+913 1715
+599 1267
+260 953
+182 511
+504 1442
+597 1080
+300 888
+459 1000
+563 1521
+563 1468
+760 1702
+8 519
+393 910
+108 255
+375 1168
+344 1257
+563 1052
+813 1139
+999 1599
+175 785
+847 882
+825 1567
+977 1567
+218 847
+921 1150
+888 1280
+395 761
+495 1444
+195 1091
diff --git a/bottleneck/tests/data/test_857_B b/bottleneck/tests/data/test_857_B
new file mode 100644
index 0000000..2d0ac7d
--- /dev/null
+++ b/bottleneck/tests/data/test_857_B
@@ -0,0 +1,50 @@
+781 853
+693 1641
+405 573
+301 1124
+303 1182
+839 1546
+597 1040
+56 318
+13 902
+667 878
+555 979
+486 1277
+647 782
+602 1195
+218 288
+59 487
+581 822
+703 842
+123 587
+173 609
+841 975
+554 641
+828 1660
+872 1486
+511 1069
+454 942
+933 1266
+416 643
+59 582
+278 354
+687 901
+1 930
+473 917
+604 950
+122 639
+126 987
+105 1046
+705 1298
+749 1143
+394 417
+15 16
+356 751
+955 1065
+599 813
+881 1008
+984 1857
+531 1371
+354 668
+747 1406
+738 1675
diff --git a/bottleneck/tests/data/test_858_A b/bottleneck/tests/data/test_858_A
new file mode 100644
index 0000000..1d3b9ad
--- /dev/null
+++ b/bottleneck/tests/data/test_858_A
@@ -0,0 +1,50 @@
+997 1050
+873 1795
+636 907
+851 1847
+38 669
+941 1873
+706 814
+776 882
+723 1329
+578 1461
+697 727
+369 1010
+426 1101
+552 720
+196 1177
+346 515
+701 1633
+399 514
+937 1425
+566 1446
+605 962
+260 696
+675 1180
+359 672
+192 355
+919 1323
+38 663
+688 1298
+239 504
+349 402
+842 1446
+831 1046
+442 770
+78 160
+351 1088
+577 1360
+29 290
+290 507
+467 1363
+1000 1796
+58 709
+428 615
+397 470
+628 1481
+874 1036
+32 84
+349 524
+244 821
+552 654
+762 1121
diff --git a/bottleneck/tests/data/test_858_B b/bottleneck/tests/data/test_858_B
new file mode 100644
index 0000000..a982114
--- /dev/null
+++ b/bottleneck/tests/data/test_858_B
@@ -0,0 +1,50 @@
+788 1123
+394 925
+228 647
+718 993
+774 961
+984 1106
+712 1001
+607 1594
+627 967
+971 1710
+166 510
+25 544
+985 1358
+205 1127
+844 1792
+510 518
+479 517
+828 1454
+61 1061
+647 1410
+727 1585
+94 479
+768 922
+162 895
+735 754
+951 1358
+747 1267
+933 980
+319 1007
+183 1000
+521 778
+129 375
+235 1221
+392 808
+872 1465
+380 794
+915 1896
+242 621
+908 1118
+341 593
+393 1304
+469 1169
+733 1077
+979 1477
+786 1583
+923 1650
+867 896
+714 1479
+860 907
+310 461
diff --git a/bottleneck/tests/data/test_859_A b/bottleneck/tests/data/test_859_A
new file mode 100644
index 0000000..24bd533
--- /dev/null
+++ b/bottleneck/tests/data/test_859_A
@@ -0,0 +1,50 @@
+305 883
+599 1497
+157 582
+832 1048
+62 403
+263 1151
+898 962
+258 428
+309 729
+626 1318
+279 415
+635 1029
+898 974
+733 1187
+661 1430
+243 1046
+498 865
+70 189
+834 1801
+820 1278
+972 1686
+255 826
+761 1694
+383 593
+326 491
+442 684
+523 1381
+229 1215
+402 551
+514 1133
+493 677
+415 996
+301 389
+586 1554
+21 956
+861 1058
+625 1082
+599 1208
+672 1147
+335 1229
+119 282
+114 772
+104 250
+236 977
+804 1446
+310 1229
+727 1176
+660 1484
+650 1188
+782 1781
diff --git a/bottleneck/tests/data/test_859_B b/bottleneck/tests/data/test_859_B
new file mode 100644
index 0000000..ac8c3b7
--- /dev/null
+++ b/bottleneck/tests/data/test_859_B
@@ -0,0 +1,50 @@
+676 874
+562 574
+260 841
+590 1249
+517 1185
+85 807
+447 909
+50 185
+961 1522
+825 1594
+159 879
+105 1015
+767 1661
+828 1827
+341 355
+104 716
+1000 1615
+135 156
+580 1099
+898 1322
+797 1442
+145 272
+397 427
+289 717
+147 535
+543 1442
+491 761
+315 888
+943 1377
+941 1582
+703 1561
+873 1055
+981 1494
+933 989
+54 194
+842 1269
+901 1394
+346 1035
+858 1198
+864 1606
+122 873
+587 936
+705 1286
+176 754
+690 1066
+950 1037
+346 781
+474 1279
+180 1172
+957 1613
diff --git a/bottleneck/tests/data/test_860_A b/bottleneck/tests/data/test_860_A
new file mode 100644
index 0000000..bef7e26
--- /dev/null
+++ b/bottleneck/tests/data/test_860_A
@@ -0,0 +1,100 @@
+286 883
+351 366
+209 489
+760 1212
+838 1652
+595 660
+603 1448
+39 243
+601 832
+245 589
+258 1170
+586 1359
+639 1499
+233 1078
+722 781
+998 1722
+867 952
+85 635
+625 1224
+545 1458
+103 885
+227 270
+397 911
+28 776
+893 1191
+600 929
+554 1437
+510 611
+768 769
+396 540
+753 1168
+508 915
+609 874
+804 1177
+777 1596
+547 844
+63 286
+979 1153
+672 1523
+620 1414
+189 629
+841 889
+329 1319
+234 432
+267 1009
+441 1379
+954 1894
+908 1341
+313 1305
+671 1250
+296 992
+518 1355
+596 905
+169 366
+333 524
+73 352
+670 1216
+459 560
+945 1546
+279 561
+27 773
+701 1354
+768 1673
+778 829
+698 1194
+680 1054
+138 954
+957 1332
+873 1110
+215 605
+997 1772
+785 935
+985 1406
+999 1441
+849 924
+547 721
+80 977
+181 321
+44 87
+561 763
+448 1065
+694 711
+539 904
+522 1201
+951 1434
+467 766
+261 1178
+900 1180
+440 1158
+134 1038
+375 383
+383 722
+974 1675
+105 380
+42 94
+855 877
+176 220
+379 952
+415 1095
+273 1064
diff --git a/bottleneck/tests/data/test_860_B b/bottleneck/tests/data/test_860_B
new file mode 100644
index 0000000..36f7915
--- /dev/null
+++ b/bottleneck/tests/data/test_860_B
@@ -0,0 +1,100 @@
+54 531
+338 1142
+464 1266
+979 1648
+714 782
+478 592
+490 1025
+958 1817
+518 1232
+259 955
+628 1122
+47 423
+831 1649
+30 971
+833 1292
+304 784
+824 1612
+267 1156
+839 926
+190 200
+817 1817
+876 1083
+654 1410
+665 1309
+226 671
+584 640
+234 1111
+806 1282
+227 642
+80 717
+608 1151
+60 808
+216 928
+177 644
+218 1177
+690 1266
+450 1313
+309 861
+979 1696
+210 1066
+461 1403
+317 680
+313 722
+112 770
+166 746
+275 515
+566 1020
+575 931
+483 851
+807 1561
+137 467
+539 1148
+539 1511
+323 563
+633 1434
+287 1046
+260 320
+785 1657
+665 1299
+123 1038
+731 1330
+844 1161
+783 785
+212 619
+712 1288
+617 761
+367 381
+613 1128
+249 372
+977 1165
+202 504
+553 1006
+760 1241
+621 1168
+761 1372
+920 1579
+541 1430
+890 1618
+20 801
+495 809
+685 1544
+709 1130
+321 1130
+802 1219
+122 740
+660 1369
+283 810
+424 425
+475 580
+616 1579
+669 1244
+223 1000
+57 188
+365 1019
+775 1711
+451 512
+234 627
+741 1601
+526 1293
+911 1233
diff --git a/bottleneck/tests/data/test_861_A b/bottleneck/tests/data/test_861_A
new file mode 100644
index 0000000..1058733
--- /dev/null
+++ b/bottleneck/tests/data/test_861_A
@@ -0,0 +1,100 @@
+127 281
+555 671
+852 1188
+977 1877
+824 1400
+698 772
+759 1378
+901 1755
+445 1382
+653 1090
+781 1672
+314 1003
+826 861
+86 713
+880 1567
+253 886
+285 1117
+742 1603
+867 1483
+14 632
+845 1280
+649 1074
+322 897
+68 387
+618 679
+918 935
+89 1077
+586 1247
+52 917
+550 1169
+426 952
+535 860
+485 1229
+152 400
+241 1071
+77 181
+795 948
+942 1437
+728 811
+119 577
+433 921
+492 1054
+582 881
+813 1720
+40 497
+389 500
+542 570
+570 580
+672 953
+754 1221
+362 468
+707 1394
+146 927
+142 1098
+820 1494
+539 1194
+422 1194
+277 1109
+975 1238
+718 1181
+1 133
+887 1015
+961 1428
+758 1212
+48 554
+945 1432
+302 1165
+742 1046
+941 1415
+468 634
+964 1097
+220 232
+970 1602
+876 1222
+712 737
+131 471
+939 1209
+579 1496
+953 1937
+295 1269
+757 1470
+141 236
+649 712
+895 1621
+806 1653
+61 736
+695 948
+986 1051
+630 1053
+637 643
+951 1857
+991 1205
+982 1752
+395 549
+216 323
+803 1202
+976 1731
+866 1223
+540 1029
+786 805
diff --git a/bottleneck/tests/data/test_861_B b/bottleneck/tests/data/test_861_B
new file mode 100644
index 0000000..a6a11d7
--- /dev/null
+++ b/bottleneck/tests/data/test_861_B
@@ -0,0 +1,100 @@
+517 1489
+251 612
+436 1287
+158 969
+181 653
+176 187
+494 1323
+174 1154
+896 926
+101 733
+416 984
+583 763
+161 512
+111 495
+991 1712
+827 854
+342 877
+13 212
+808 1594
+423 1182
+219 666
+195 233
+347 708
+979 1787
+758 1254
+414 1279
+421 563
+340 722
+209 552
+258 704
+776 1610
+672 972
+412 1195
+48 846
+946 1569
+844 1094
+891 1866
+430 925
+661 1317
+819 1214
+837 1824
+731 982
+14 53
+333 1086
+512 868
+789 1264
+15 313
+256 973
+678 1052
+259 1229
+969 1150
+602 1255
+302 1291
+257 1082
+756 1579
+103 110
+125 960
+368 1258
+183 1001
+559 1106
+447 944
+784 1446
+947 1735
+982 1775
+586 1368
+239 1171
+210 856
+94 1017
+138 1075
+59 657
+440 1015
+978 1530
+785 1259
+381 963
+463 1115
+785 1398
+0 147
+952 1432
+573 1345
+592 1443
+829 1357
+250 966
+948 1110
+848 1569
+251 904
+945 1606
+99 1025
+799 863
+690 1141
+21 445
+860 1338
+43 130
+148 853
+261 979
+177 324
+400 1084
+277 1098
+888 1223
+948 1629
+573 1197
diff --git a/bottleneck/tests/data/test_862_A b/bottleneck/tests/data/test_862_A
new file mode 100644
index 0000000..d37d3ef
--- /dev/null
+++ b/bottleneck/tests/data/test_862_A
@@ -0,0 +1,100 @@
+102 300
+352 359
+521 683
+515 1057
+914 1269
+100 498
+589 1272
+77 129
+417 487
+579 1450
+101 780
+36 807
+588 1009
+556 1004
+875 1497
+488 1097
+842 1462
+221 1204
+328 518
+186 828
+870 992
+309 931
+56 558
+780 1456
+164 1070
+472 934
+412 1210
+842 872
+575 1445
+755 1457
+250 571
+426 1223
+367 1073
+648 749
+303 1009
+147 491
+118 1002
+320 398
+473 1445
+817 1679
+35 369
+170 947
+953 1168
+169 278
+307 547
+260 507
+901 1598
+116 381
+241 765
+98 970
+216 1171
+746 1175
+605 1578
+601 1019
+598 967
+316 723
+838 1609
+78 357
+563 893
+545 1089
+813 1743
+981 1110
+454 514
+613 799
+742 1712
+620 764
+464 702
+643 1186
+674 1638
+418 669
+310 1147
+325 1015
+983 1678
+625 951
+407 750
+973 1792
+552 1354
+391 1120
+463 829
+716 1387
+6 403
+177 756
+505 708
+219 471
+187 714
+852 1248
+913 1610
+971 1722
+943 1812
+452 726
+509 624
+178 767
+699 1085
+771 1634
+140 251
+646 822
+456 754
+263 1179
+430 540
+96 810
diff --git a/bottleneck/tests/data/test_862_B b/bottleneck/tests/data/test_862_B
new file mode 100644
index 0000000..a18168e
--- /dev/null
+++ b/bottleneck/tests/data/test_862_B
@@ -0,0 +1,100 @@
+123 340
+973 1465
+652 1288
+89 1046
+165 777
+390 986
+139 396
+378 927
+426 1167
+32 223
+259 1177
+771 1250
+494 1143
+528 759
+515 912
+319 992
+134 169
+851 1595
+676 816
+111 304
+35 872
+58 456
+522 1458
+392 1221
+112 1035
+471 1214
+495 580
+339 1276
+143 268
+12 788
+723 1470
+745 1088
+664 1449
+442 463
+268 1026
+289 910
+141 162
+411 1163
+626 1174
+743 1627
+261 1211
+950 1869
+214 1114
+995 1678
+586 960
+754 1098
+363 1013
+808 1761
+58 601
+267 1109
+571 1518
+639 1092
+565 785
+256 537
+490 509
+467 1036
+931 1450
+891 1584
+701 1280
+939 1642
+416 834
+72 964
+530 553
+224 331
+234 683
+722 1338
+190 496
+282 1201
+174 1133
+348 690
+799 1606
+891 1085
+408 1263
+204 522
+867 1729
+856 1102
+175 589
+827 1559
+880 1479
+558 720
+810 1534
+954 1315
+501 901
+675 1031
+721 1091
+265 1103
+670 1553
+587 614
+712 735
+713 1167
+565 714
+67 594
+928 1456
+375 449
+893 1022
+319 500
+101 783
+637 1572
+26 620
+107 845
diff --git a/bottleneck/tests/data/test_863_A b/bottleneck/tests/data/test_863_A
new file mode 100644
index 0000000..011d452
--- /dev/null
+++ b/bottleneck/tests/data/test_863_A
@@ -0,0 +1,100 @@
+596 1590
+388 1099
+928 1387
+473 1128
+595 925
+188 767
+40 804
+542 1405
+661 1245
+579 666
+526 616
+235 378
+379 477
+257 781
+910 1279
+882 1387
+562 1374
+499 603
+342 1317
+184 581
+315 1198
+987 1072
+696 1049
+498 1250
+782 1609
+771 1330
+203 354
+227 1171
+506 939
+360 1303
+969 1942
+772 850
+615 1079
+542 1186
+644 1583
+676 1131
+496 1300
+825 1120
+492 1332
+408 1051
+768 1110
+466 1044
+795 1594
+56 577
+529 1378
+899 1752
+943 1916
+509 780
+609 1175
+999 1928
+360 1164
+901 1764
+558 592
+665 752
+7 82
+919 1683
+772 1057
+211 928
+494 1347
+568 1412
+661 1649
+466 551
+75 498
+329 577
+143 636
+112 144
+217 221
+340 1208
+259 1177
+36 364
+63 299
+74 513
+67 186
+201 672
+508 1253
+96 129
+301 991
+925 1873
+340 1050
+237 672
+445 816
+836 1594
+649 1458
+227 1152
+880 933
+209 939
+822 890
+760 1131
+274 1096
+706 1604
+33 589
+552 1228
+69 615
+794 914
+305 423
+956 1053
+914 1411
+421 1282
+261 1067
+967 1966
diff --git a/bottleneck/tests/data/test_863_B b/bottleneck/tests/data/test_863_B
new file mode 100644
index 0000000..d9daaae
--- /dev/null
+++ b/bottleneck/tests/data/test_863_B
@@ -0,0 +1,100 @@
+986 1775
+226 644
+68 818
+739 1449
+962 1111
+850 1460
+306 1206
+901 1742
+171 513
+83 396
+776 1243
+646 948
+693 1431
+219 627
+247 813
+243 1070
+452 1130
+315 1227
+16 808
+977 1035
+454 583
+566 1521
+437 507
+484 1294
+494 506
+752 1161
+152 1081
+566 1413
+141 331
+706 1243
+258 849
+729 1447
+988 1985
+774 1653
+972 1907
+510 589
+402 905
+981 1420
+688 1112
+291 1016
+975 1800
+240 879
+643 1264
+448 458
+707 1075
+157 654
+51 635
+639 677
+688 1518
+99 198
+914 1734
+445 1036
+897 941
+504 1318
+192 479
+287 1003
+624 1444
+815 961
+956 1436
+445 656
+52 574
+787 987
+994 1875
+354 1317
+189 1072
+264 418
+645 1086
+319 942
+202 676
+841 1204
+695 1354
+289 748
+631 649
+894 1632
+909 1782
+794 1065
+0 430
+4 209
+286 1174
+327 1132
+342 641
+455 1256
+295 819
+749 1381
+811 1469
+69 514
+54 1044
+262 1176
+418 854
+819 1524
+861 1796
+242 996
+990 1068
+19 519
+831 1475
+782 1334
+748 986
+869 1569
+556 1535
+685 1411
diff --git a/bottleneck/tests/data/test_864_A b/bottleneck/tests/data/test_864_A
new file mode 100644
index 0000000..f82ed50
--- /dev/null
+++ b/bottleneck/tests/data/test_864_A
@@ -0,0 +1,100 @@
+698 789
+78 479
+383 639
+731 1686
+306 787
+614 696
+719 1184
+404 852
+317 776
+91 656
+126 806
+19 775
+976 1941
+876 1716
+501 1160
+851 1078
+547 641
+187 372
+654 1080
+745 1229
+151 577
+219 600
+318 1253
+317 362
+720 1487
+147 720
+900 1717
+402 1317
+187 1156
+573 1301
+173 479
+613 889
+956 1747
+583 1203
+478 1031
+498 1031
+394 1197
+118 842
+204 246
+562 1361
+340 835
+749 871
+847 1637
+776 1643
+731 1242
+302 741
+312 369
+903 1276
+814 1418
+205 336
+485 1196
+897 1667
+442 562
+319 1253
+56 469
+674 923
+51 642
+487 739
+32 759
+631 1091
+219 293
+381 419
+179 761
+935 1358
+408 636
+355 831
+677 1286
+98 306
+893 922
+275 1275
+350 923
+583 1490
+562 1545
+213 634
+538 870
+270 301
+536 1323
+663 1279
+286 325
+1 331
+927 1472
+998 1673
+404 484
+368 1234
+650 803
+238 845
+956 1851
+278 1002
+767 1110
+176 190
+808 841
+910 1693
+242 1010
+523 1133
+364 543
+915 1652
+401 1326
+787 1236
+250 985
+884 1153
diff --git a/bottleneck/tests/data/test_864_B b/bottleneck/tests/data/test_864_B
new file mode 100644
index 0000000..0b56a95
--- /dev/null
+++ b/bottleneck/tests/data/test_864_B
@@ -0,0 +1,100 @@
+11 893
+131 282
+718 1633
+802 822
+342 857
+797 1757
+703 704
+296 1271
+439 868
+143 1065
+860 1380
+62 101
+536 1375
+526 533
+482 1222
+338 1199
+665 770
+85 713
+829 930
+366 710
+300 757
+561 1556
+904 905
+711 1575
+30 766
+710 898
+476 897
+592 1142
+731 1153
+799 1176
+31 769
+570 718
+620 1438
+718 1198
+938 1650
+31 296
+342 929
+953 1681
+650 896
+868 1404
+800 1680
+776 1229
+612 1330
+362 1338
+958 1066
+269 978
+981 1035
+160 322
+673 795
+150 1117
+564 1490
+737 1617
+492 1040
+599 954
+261 1094
+691 734
+318 1231
+157 546
+329 916
+982 1956
+211 719
+665 1381
+911 1689
+368 425
+459 749
+706 1410
+103 539
+134 476
+209 341
+469 589
+350 462
+789 1113
+945 1335
+936 1272
+886 1823
+958 1528
+96 492
+532 1243
+119 577
+322 367
+518 1434
+692 839
+509 1104
+668 1357
+139 1127
+258 300
+307 382
+156 403
+171 582
+411 701
+794 944
+937 1602
+6 60
+593 929
+977 1052
+221 1209
+603 832
+881 1176
+394 710
+660 1260
diff --git a/bottleneck/tests/data/test_865_A b/bottleneck/tests/data/test_865_A
new file mode 100644
index 0000000..7453ead
--- /dev/null
+++ b/bottleneck/tests/data/test_865_A
@@ -0,0 +1,100 @@
+680 1206
+916 1092
+447 722
+821 1233
+565 1508
+548 1163
+973 1156
+229 1196
+378 542
+334 619
+581 606
+171 644
+143 407
+857 1539
+129 337
+582 780
+378 441
+196 340
+619 746
+28 94
+294 590
+881 1520
+113 174
+1000 1989
+343 395
+633 1542
+348 988
+973 1914
+58 903
+510 767
+440 448
+876 1806
+932 1554
+367 917
+465 820
+359 1185
+793 820
+999 1064
+193 871
+409 1286
+224 631
+381 793
+650 1047
+493 524
+698 1162
+846 1083
+536 1456
+909 1650
+245 982
+714 1104
+867 1447
+709 1527
+831 859
+170 266
+31 541
+578 650
+960 1059
+147 741
+202 407
+110 136
+747 1087
+781 1489
+759 1738
+945 1542
+790 1588
+52 259
+290 1116
+561 1416
+200 740
+50 629
+907 1349
+312 708
+87 433
+33 920
+934 1278
+530 706
+760 879
+834 1301
+819 1372
+656 1622
+950 1152
+452 692
+426 798
+469 811
+158 554
+563 1532
+713 1332
+567 964
+111 921
+237 1102
+156 1100
+113 344
+553 1386
+880 982
+355 655
+81 959
+203 437
+848 1389
+7 377
+305 717
diff --git a/bottleneck/tests/data/test_865_B b/bottleneck/tests/data/test_865_B
new file mode 100644
index 0000000..265e3bd
--- /dev/null
+++ b/bottleneck/tests/data/test_865_B
@@ -0,0 +1,100 @@
+121 979
+358 852
+219 696
+216 239
+200 737
+859 1771
+323 826
+192 1007
+129 389
+489 1130
+227 568
+806 1657
+613 1508
+626 1325
+643 1425
+905 1619
+123 372
+26 371
+949 1838
+399 1361
+516 652
+273 485
+346 753
+975 1839
+276 789
+824 893
+937 1262
+34 37
+444 993
+133 860
+190 421
+978 1903
+56 733
+421 756
+583 590
+133 371
+881 1309
+897 1347
+442 979
+700 941
+871 1095
+34 182
+206 603
+858 1533
+284 821
+241 1167
+623 989
+715 1664
+187 822
+970 1681
+26 153
+533 648
+406 873
+791 862
+217 983
+211 930
+781 1001
+973 1393
+204 845
+23 894
+11 772
+863 1663
+126 233
+306 835
+85 370
+802 1738
+526 1171
+429 1118
+697 1462
+196 512
+887 902
+7 401
+881 1262
+743 1392
+676 733
+527 1394
+911 1179
+816 1280
+513 1072
+842 1750
+942 1260
+841 1438
+86 704
+308 639
+478 1085
+56 220
+411 1045
+185 1141
+941 1695
+465 1360
+157 665
+19 599
+540 891
+832 1200
+408 1232
+540 1207
+881 1721
+496 691
+623 1295
+811 873
diff --git a/bottleneck/tests/data/test_866_A b/bottleneck/tests/data/test_866_A
new file mode 100644
index 0000000..a05ad71
--- /dev/null
+++ b/bottleneck/tests/data/test_866_A
@@ -0,0 +1,100 @@
+554 1091
+21 867
+633 899
+500 663
+971 975
+410 1235
+179 1036
+438 917
+434 678
+378 520
+747 1564
+39 131
+748 1408
+581 1266
+818 915
+527 1287
+452 998
+585 1061
+224 244
+554 1427
+859 1079
+613 1539
+522 738
+392 1170
+788 1437
+288 680
+370 1117
+476 1151
+826 1129
+41 551
+96 839
+480 1110
+909 1050
+59 1059
+549 801
+124 198
+991 1323
+122 1026
+573 1345
+701 1061
+40 265
+872 1116
+579 1464
+807 1198
+269 553
+376 786
+711 866
+864 1301
+716 1185
+366 775
+1000 1991
+970 1156
+921 1050
+599 1510
+49 593
+475 1394
+764 1704
+516 912
+721 805
+986 1006
+728 852
+789 1097
+459 597
+967 1276
+261 1126
+906 920
+466 1134
+419 467
+638 818
+243 738
+188 906
+434 1199
+821 892
+885 1241
+7 664
+963 1398
+576 1142
+84 385
+20 308
+845 1162
+79 730
+203 625
+412 1054
+553 898
+752 920
+640 1312
+169 706
+920 1586
+134 246
+352 619
+90 716
+197 616
+819 1101
+805 1686
+543 1178
+482 1411
+297 1259
+957 1763
+355 808
+591 1221
diff --git a/bottleneck/tests/data/test_866_B b/bottleneck/tests/data/test_866_B
new file mode 100644
index 0000000..c3e0b3a
--- /dev/null
+++ b/bottleneck/tests/data/test_866_B
@@ -0,0 +1,100 @@
+573 1390
+68 742
+178 1172
+592 975
+294 453
+280 552
+750 1332
+947 1248
+972 1885
+868 942
+269 719
+457 944
+863 1391
+802 1524
+64 235
+161 495
+439 1397
+143 354
+974 1778
+239 643
+831 1814
+216 969
+515 1065
+334 1263
+504 1264
+950 1570
+558 976
+84 242
+125 745
+382 448
+602 1380
+98 211
+994 1767
+140 712
+694 1187
+523 901
+906 970
+65 850
+188 858
+787 1715
+836 1543
+356 1082
+9 932
+945 1142
+653 756
+934 1085
+526 1465
+636 1544
+711 1660
+63 607
+279 482
+716 768
+380 543
+210 885
+597 1476
+172 837
+542 1257
+465 557
+983 1339
+647 1098
+643 1101
+239 688
+658 1241
+448 595
+320 641
+622 673
+788 824
+2 645
+456 1068
+707 984
+334 1093
+81 601
+413 813
+311 345
+129 827
+253 556
+971 1376
+291 534
+846 1646
+61 699
+552 1406
+583 866
+285 635
+772 1351
+937 1014
+688 709
+425 906
+750 1220
+395 685
+93 392
+596 1460
+749 1123
+631 843
+100 311
+774 991
+873 1870
+297 422
+856 1311
+983 1053
+746 1722
diff --git a/bottleneck/tests/data/test_867_A b/bottleneck/tests/data/test_867_A
new file mode 100644
index 0000000..0e5ca13
--- /dev/null
+++ b/bottleneck/tests/data/test_867_A
@@ -0,0 +1,100 @@
+324 1024
+307 1299
+253 1161
+488 662
+711 1205
+481 510
+910 1280
+465 1426
+800 1294
+664 1348
+676 1342
+946 1581
+956 1482
+70 194
+312 636
+477 1373
+465 1242
+720 1446
+850 1798
+354 386
+657 998
+126 306
+800 1781
+695 1218
+69 522
+832 1255
+553 1007
+796 1602
+889 1204
+390 1048
+792 1754
+493 1394
+71 545
+200 996
+28 103
+705 1003
+315 489
+140 903
+161 296
+697 1682
+748 1663
+360 1052
+226 776
+18 564
+417 449
+234 350
+639 1585
+574 788
+862 1581
+950 1575
+268 532
+946 1194
+386 613
+782 1325
+494 1069
+792 846
+453 1409
+444 1022
+268 554
+319 792
+187 932
+491 1155
+93 253
+986 1147
+758 1167
+424 780
+194 891
+360 1218
+59 457
+625 1514
+618 919
+680 1182
+31 358
+544 744
+529 1135
+859 1346
+533 1132
+833 873
+583 733
+695 1156
+102 1023
+542 1132
+317 640
+883 1183
+696 1191
+603 1489
+492 1373
+935 1085
+235 620
+37 549
+802 1022
+211 508
+907 1146
+989 1239
+68 909
+367 919
+626 827
+770 1592
+413 414
+427 620
diff --git a/bottleneck/tests/data/test_867_B b/bottleneck/tests/data/test_867_B
new file mode 100644
index 0000000..c8eb5e0
--- /dev/null
+++ b/bottleneck/tests/data/test_867_B
@@ -0,0 +1,100 @@
+780 1730
+13 771
+347 670
+699 1353
+924 1139
+806 1496
+537 561
+756 1433
+987 1945
+689 1191
+123 972
+46 99
+468 961
+722 997
+675 1491
+626 1171
+315 1095
+582 741
+445 1083
+974 1633
+543 1308
+829 1343
+414 1038
+817 1254
+596 619
+94 438
+545 955
+832 1672
+0 240
+110 729
+444 1151
+331 1174
+684 765
+612 1448
+369 1181
+675 1243
+758 1008
+716 858
+618 931
+642 1279
+219 593
+650 751
+228 998
+40 93
+181 758
+372 658
+87 607
+190 1136
+990 1325
+232 991
+205 1111
+497 965
+767 1480
+896 1862
+777 1234
+790 1452
+734 1521
+457 1207
+934 979
+617 948
+217 767
+654 1122
+902 1565
+951 984
+250 644
+63 299
+726 1472
+406 1249
+749 777
+140 250
+235 1047
+118 1003
+728 833
+158 1021
+243 801
+112 330
+10 912
+629 796
+954 1471
+764 1267
+598 1299
+131 899
+103 405
+187 456
+985 1359
+228 599
+440 1326
+776 852
+156 847
+295 558
+453 786
+236 560
+948 1458
+599 1174
+482 869
+857 1110
+978 1947
+424 446
+699 1688
+886 1793
diff --git a/bottleneck/tests/data/test_868_A b/bottleneck/tests/data/test_868_A
new file mode 100644
index 0000000..0a0fad2
--- /dev/null
+++ b/bottleneck/tests/data/test_868_A
@@ -0,0 +1,100 @@
+430 1257
+813 1021
+677 1089
+222 1147
+837 1410
+931 1488
+664 1192
+946 1885
+492 1036
+808 1524
+389 1210
+953 1056
+96 797
+818 1592
+900 1074
+63 516
+46 961
+999 1353
+797 1101
+343 1142
+355 459
+384 1358
+401 800
+354 1100
+661 1246
+76 437
+19 581
+385 760
+704 1218
+25 332
+406 1275
+838 1648
+57 335
+501 638
+826 1431
+682 1568
+803 1533
+894 1845
+38 580
+54 835
+448 507
+132 538
+226 1080
+307 489
+339 596
+334 1283
+573 891
+844 1119
+674 949
+998 1669
+226 599
+487 527
+401 1224
+785 1065
+270 710
+410 545
+981 1732
+602 704
+38 838
+145 646
+671 1128
+621 787
+782 1217
+932 1014
+935 1117
+923 1561
+79 253
+170 548
+343 937
+966 1919
+847 1290
+41 234
+683 926
+279 457
+243 957
+316 1240
+630 1492
+901 1691
+919 1022
+385 574
+902 1474
+640 1197
+805 973
+943 1173
+24 846
+139 140
+48 425
+124 1016
+880 1326
+175 275
+835 1142
+244 331
+770 969
+386 950
+391 886
+334 1284
+754 1503
+179 842
+955 1780
+330 436
diff --git a/bottleneck/tests/data/test_868_B b/bottleneck/tests/data/test_868_B
new file mode 100644
index 0000000..00c87b2
--- /dev/null
+++ b/bottleneck/tests/data/test_868_B
@@ -0,0 +1,100 @@
+166 1061
+527 1335
+325 949
+111 649
+488 697
+766 1222
+709 1440
+141 784
+700 939
+798 1136
+861 1837
+628 1376
+473 1366
+145 643
+194 363
+986 1365
+564 979
+870 1837
+451 928
+797 1196
+521 1453
+0 285
+191 1080
+846 1666
+337 494
+790 1644
+759 1570
+46 871
+886 966
+169 897
+55 627
+538 1463
+114 429
+787 827
+850 1806
+31 827
+482 1012
+120 693
+777 1353
+271 916
+15 717
+660 943
+265 446
+985 1045
+22 519
+715 1571
+604 1475
+141 983
+395 1392
+98 851
+179 766
+237 652
+794 1439
+275 451
+47 631
+183 1091
+500 989
+727 1263
+625 1578
+327 1057
+725 1166
+212 731
+699 1449
+471 472
+787 1014
+714 1402
+412 913
+326 1203
+239 592
+920 1395
+303 410
+197 853
+101 1007
+970 1893
+925 1655
+490 670
+158 428
+413 1207
+722 1712
+776 1727
+548 1012
+891 1253
+329 1285
+576 1098
+357 878
+713 1660
+165 726
+786 1231
+447 600
+103 478
+177 764
+386 1263
+307 327
+812 1500
+685 1462
+973 1935
+973 1024
+848 868
+897 1464
+696 1688
diff --git a/bottleneck/tests/data/test_869_A b/bottleneck/tests/data/test_869_A
new file mode 100644
index 0000000..fa16527
--- /dev/null
+++ b/bottleneck/tests/data/test_869_A
@@ -0,0 +1,100 @@
+723 777
+589 1331
+521 602
+976 1210
+302 783
+550 1430
+254 453
+580 1493
+870 1136
+765 1589
+178 699
+654 1093
+505 739
+285 572
+694 975
+4 681
+733 1644
+258 639
+575 1027
+628 756
+887 1885
+430 1393
+194 371
+57 230
+275 489
+269 458
+254 354
+227 1077
+837 1711
+737 1290
+315 1159
+440 791
+922 1280
+175 615
+137 448
+712 1488
+96 617
+815 1776
+280 540
+595 1107
+545 987
+914 1273
+418 919
+135 1053
+612 653
+194 901
+99 866
+689 1038
+273 789
+350 1046
+433 828
+679 1512
+611 1131
+344 1098
+86 1055
+791 1490
+717 1192
+900 1504
+165 1119
+47 512
+452 858
+290 447
+610 774
+451 1149
+693 809
+513 889
+313 771
+290 604
+419 990
+554 728
+726 1563
+860 1471
+671 767
+735 763
+615 1318
+792 1245
+403 1356
+624 1031
+875 1372
+780 1429
+692 1291
+549 655
+412 1158
+727 982
+780 986
+899 1741
+896 1193
+958 1531
+580 698
+23 296
+735 1275
+400 495
+411 1166
+128 630
+498 1178
+195 459
+829 1674
+678 1531
+329 785
+625 1441
diff --git a/bottleneck/tests/data/test_869_B b/bottleneck/tests/data/test_869_B
new file mode 100644
index 0000000..7ffd8c9
--- /dev/null
+++ b/bottleneck/tests/data/test_869_B
@@ -0,0 +1,100 @@
+979 1349
+400 1004
+925 1748
+266 1261
+562 1050
+591 592
+63 630
+404 603
+971 1511
+352 619
+907 1852
+388 830
+8 145
+14 369
+247 938
+648 1230
+625 1083
+231 1003
+926 1824
+143 879
+689 1615
+340 1273
+565 955
+419 443
+92 867
+554 697
+774 1475
+298 1142
+677 1036
+734 811
+831 1211
+585 757
+328 573
+117 789
+575 614
+191 1007
+457 829
+35 193
+518 1335
+5 799
+505 1285
+48 381
+684 990
+767 1230
+953 1161
+51 556
+391 522
+405 419
+217 877
+793 857
+360 455
+259 791
+507 553
+505 1256
+403 842
+981 1524
+223 246
+780 1102
+707 1010
+584 1474
+529 1074
+384 464
+452 668
+28 321
+181 496
+343 1061
+764 1720
+454 1394
+768 822
+217 741
+176 476
+263 306
+914 1258
+526 584
+823 1116
+82 697
+994 1908
+667 982
+231 463
+230 807
+843 1706
+50 369
+521 740
+599 1004
+72 775
+279 502
+833 1423
+880 1593
+371 1093
+703 1272
+815 1096
+125 1058
+497 899
+991 1183
+300 1016
+394 514
+962 1608
+797 1721
+994 1473
+108 421
diff --git a/bottleneck/tests/data/test_870_A b/bottleneck/tests/data/test_870_A
new file mode 100644
index 0000000..72422f7
--- /dev/null
+++ b/bottleneck/tests/data/test_870_A
@@ -0,0 +1,100 @@
+60 817
+390 412
+83 364
+762 1271
+949 1643
+874 1468
+411 1354
+897 1800
+66 622
+763 1511
+51 1025
+882 1063
+91 96
+309 1302
+646 1599
+721 1157
+923 1112
+907 1582
+434 517
+854 1679
+719 1601
+38 615
+762 1454
+394 438
+2 40
+828 1110
+994 1556
+647 745
+610 1499
+9 27
+4 572
+829 1229
+44 319
+807 1726
+286 1104
+953 1884
+941 1314
+131 1041
+363 883
+825 1168
+975 1168
+561 1292
+151 204
+465 648
+346 459
+252 1179
+766 917
+583 1401
+353 666
+493 739
+809 1531
+391 964
+410 1172
+180 194
+865 1343
+849 1201
+839 1253
+5 590
+674 1029
+821 1333
+711 874
+557 1038
+101 163
+564 834
+696 707
+631 1249
+762 1107
+343 515
+987 1870
+525 1274
+402 1043
+164 220
+940 1422
+840 1281
+50 1012
+275 1062
+472 790
+61 306
+217 661
+283 1281
+436 972
+952 1838
+374 1049
+577 1482
+486 1288
+743 851
+469 1295
+553 1233
+11 774
+687 1381
+243 481
+399 873
+777 1539
+489 742
+293 513
+755 1047
+881 1154
+757 1457
+261 1097
+693 1283
diff --git a/bottleneck/tests/data/test_870_B b/bottleneck/tests/data/test_870_B
new file mode 100644
index 0000000..db4847d
--- /dev/null
+++ b/bottleneck/tests/data/test_870_B
@@ -0,0 +1,100 @@
+278 1098
+502 1411
+318 748
+154 189
+605 1475
+556 1482
+377 718
+168 338
+595 921
+962 1686
+301 409
+730 1138
+132 612
+988 1838
+759 1728
+170 465
+654 681
+43 199
+358 1076
+270 316
+602 1382
+657 1138
+211 448
+516 652
+781 1312
+937 1266
+30 227
+769 1102
+91 938
+737 1368
+733 1087
+511 721
+582 997
+261 635
+540 992
+503 590
+189 267
+614 824
+517 1181
+120 447
+545 650
+248 1122
+798 1437
+571 1265
+358 993
+618 1573
+406 861
+540 1382
+213 509
+964 1055
+481 858
+933 1275
+680 1433
+634 665
+963 1365
+612 1163
+895 1316
+95 814
+483 1416
+142 989
+37 588
+17 728
+137 492
+498 1010
+868 1023
+713 1344
+606 1243
+806 1540
+868 1118
+115 780
+329 690
+742 1226
+595 1135
+534 938
+53 175
+627 683
+277 1165
+323 329
+587 869
+308 1234
+266 338
+103 928
+385 863
+628 1620
+157 370
+258 731
+30 588
+202 920
+589 618
+5 221
+882 1659
+68 136
+918 1860
+466 801
+719 1236
+79 664
+562 1234
+258 784
+669 1010
+850 1761
diff --git a/bottleneck/tests/data/test_871_A b/bottleneck/tests/data/test_871_A
new file mode 100644
index 0000000..08ce8b2
--- /dev/null
+++ b/bottleneck/tests/data/test_871_A
@@ -0,0 +1,100 @@
+42 835
+829 1708
+683 1618
+329 527
+127 163
+931 1127
+902 1289
+712 755
+344 415
+991 1939
+8 415
+225 1099
+685 1632
+996 1747
+751 1238
+569 1367
+256 401
+711 1157
+58 745
+112 1087
+226 902
+560 1414
+482 1323
+243 382
+672 1335
+202 962
+803 1090
+398 967
+790 1384
+901 1648
+280 296
+684 1484
+432 498
+599 972
+86 497
+703 1327
+730 1472
+889 946
+1000 1305
+735 1569
+606 1155
+916 1843
+246 286
+102 980
+854 1598
+518 944
+341 973
+426 489
+888 1375
+359 409
+49 660
+619 1187
+635 1439
+338 1297
+347 654
+847 989
+161 915
+846 1341
+196 418
+698 1689
+535 634
+407 419
+767 1110
+154 1127
+912 1214
+982 1797
+824 1331
+38 859
+753 867
+297 988
+784 1479
+407 1024
+884 1054
+894 1476
+674 837
+402 1183
+906 1306
+27 471
+672 1594
+480 830
+174 302
+133 928
+858 1186
+541 950
+395 397
+356 1259
+219 1028
+120 465
+703 1595
+9 234
+790 1682
+322 1197
+314 655
+770 1287
+95 775
+444 520
+118 800
+852 1564
+24 333
+906 1508
diff --git a/bottleneck/tests/data/test_871_B b/bottleneck/tests/data/test_871_B
new file mode 100644
index 0000000..23c1dd8
--- /dev/null
+++ b/bottleneck/tests/data/test_871_B
@@ -0,0 +1,100 @@
+112 365
+974 1486
+76 198
+108 949
+30 308
+221 985
+687 1236
+255 744
+597 1580
+552 1173
+944 1327
+291 494
+867 1053
+73 595
+265 407
+827 1067
+990 1968
+663 948
+555 1506
+469 1046
+909 939
+59 858
+756 986
+101 335
+57 1047
+516 1348
+615 775
+578 1391
+756 1351
+341 1087
+147 471
+893 1879
+68 603
+433 867
+982 1332
+11 464
+710 1435
+337 967
+468 1092
+282 474
+712 1541
+779 1165
+255 872
+590 1550
+255 949
+316 494
+398 1017
+863 1551
+835 1072
+554 1129
+560 854
+862 1403
+97 304
+71 393
+351 1038
+624 1327
+185 1077
+311 601
+640 736
+542 980
+735 884
+78 879
+230 799
+462 1295
+249 678
+736 900
+867 984
+254 405
+408 543
+271 694
+371 1039
+38 598
+888 1058
+876 1612
+697 1333
+650 1183
+910 1895
+884 1723
+922 1772
+911 1770
+788 1139
+981 1024
+962 1552
+389 612
+661 1027
+583 1188
+649 1291
+793 1505
+442 1158
+356 832
+190 589
+643 713
+496 536
+530 1381
+153 641
+162 335
+629 1071
+110 395
+18 833
+8 423
diff --git a/bottleneck/tests/data/test_872_A b/bottleneck/tests/data/test_872_A
new file mode 100644
index 0000000..9647bed
--- /dev/null
+++ b/bottleneck/tests/data/test_872_A
@@ -0,0 +1,100 @@
+357 473
+781 1680
+963 1614
+418 582
+427 979
+738 924
+946 1432
+903 1821
+250 279
+570 1065
+305 1090
+750 756
+317 1028
+865 1402
+464 465
+316 1186
+856 1199
+763 1744
+46 424
+954 1654
+602 843
+232 426
+864 1001
+292 495
+72 455
+907 1762
+575 697
+886 1098
+954 1502
+980 1741
+317 527
+72 711
+614 695
+931 1149
+223 229
+684 1073
+221 897
+1000 1806
+165 358
+454 1067
+569 878
+162 950
+910 1768
+329 508
+247 1201
+469 849
+973 1153
+298 670
+682 1515
+230 777
+876 1085
+438 598
+72 775
+668 687
+254 502
+989 1165
+646 1375
+972 1552
+593 1408
+860 1844
+256 469
+982 1530
+834 1562
+195 280
+81 393
+470 802
+570 667
+95 558
+846 1778
+639 1120
+340 804
+527 530
+413 428
+797 1156
+610 780
+113 323
+287 441
+388 838
+418 743
+859 970
+96 898
+29 592
+396 1004
+463 1417
+641 1130
+880 1301
+176 1121
+286 325
+456 1093
+988 1077
+885 1278
+47 828
+617 1089
+595 1071
+870 895
+661 1423
+720 759
+379 924
+892 1184
+583 589
diff --git a/bottleneck/tests/data/test_872_B b/bottleneck/tests/data/test_872_B
new file mode 100644
index 0000000..1c58840
--- /dev/null
+++ b/bottleneck/tests/data/test_872_B
@@ -0,0 +1,100 @@
+153 586
+46 542
+64 130
+498 815
+144 494
+300 1100
+146 383
+431 558
+710 839
+615 648
+680 970
+995 1797
+903 1605
+994 1759
+335 810
+93 670
+928 1252
+754 1015
+941 1668
+105 746
+448 924
+419 1140
+881 1239
+500 831
+794 1571
+780 1613
+892 1155
+133 279
+869 1603
+745 1402
+463 623
+501 686
+510 1155
+806 1373
+302 821
+710 1492
+508 879
+643 787
+494 1172
+427 1018
+37 813
+394 497
+498 1374
+565 1285
+216 453
+315 1039
+356 920
+968 1326
+400 460
+779 964
+179 560
+405 1249
+64 466
+128 978
+99 582
+424 885
+39 675
+912 1624
+531 652
+617 1391
+338 788
+993 1673
+229 301
+879 1305
+356 467
+950 1787
+471 1441
+692 1677
+84 383
+767 1029
+865 1658
+468 988
+854 1028
+483 1097
+898 1321
+605 723
+632 1154
+782 1260
+797 1207
+176 445
+126 827
+333 541
+722 1131
+188 642
+287 1194
+8 607
+955 1136
+44 1000
+515 858
+39 311
+436 1200
+344 1280
+856 1776
+603 1524
+230 617
+953 1413
+592 916
+393 1116
+498 529
+283 734
diff --git a/bottleneck/tests/data/test_873_A b/bottleneck/tests/data/test_873_A
new file mode 100644
index 0000000..d9e1da9
--- /dev/null
+++ b/bottleneck/tests/data/test_873_A
@@ -0,0 +1,100 @@
+871 918
+442 1110
+786 797
+342 1125
+473 1471
+550 737
+956 1854
+259 420
+592 1059
+861 1049
+50 255
+11 163
+254 810
+649 659
+866 1083
+786 1466
+728 1162
+659 1272
+884 1597
+34 1016
+487 679
+765 1214
+145 505
+994 1925
+711 1474
+207 713
+143 567
+935 1009
+62 1036
+168 713
+7 478
+628 1423
+51 693
+391 575
+18 283
+45 308
+971 1067
+934 1548
+604 1154
+4 558
+425 998
+77 439
+513 1485
+354 1302
+317 816
+5 551
+346 804
+872 1197
+309 418
+691 886
+927 1242
+51 491
+88 645
+835 1584
+377 751
+668 684
+226 1026
+418 691
+335 939
+955 1872
+490 1173
+68 355
+689 740
+284 550
+531 1023
+312 390
+127 875
+3 408
+314 458
+907 932
+489 890
+451 1402
+52 849
+709 1325
+373 1367
+390 1030
+707 1272
+25 607
+742 996
+838 1569
+570 1522
+278 1034
+863 1805
+615 823
+865 1726
+902 1367
+81 1011
+619 1462
+18 422
+433 1195
+154 635
+27 975
+690 1465
+447 1308
+686 1058
+204 1164
+572 1531
+202 609
+772 777
+740 1633
diff --git a/bottleneck/tests/data/test_873_B b/bottleneck/tests/data/test_873_B
new file mode 100644
index 0000000..a9f3ea1
--- /dev/null
+++ b/bottleneck/tests/data/test_873_B
@@ -0,0 +1,100 @@
+816 1608
+484 669
+486 883
+131 221
+617 1433
+421 578
+277 879
+587 979
+662 783
+275 1001
+538 1142
+135 857
+984 1296
+163 997
+818 1596
+591 1112
+29 465
+156 374
+805 1436
+709 977
+650 1507
+360 1041
+940 1108
+957 1483
+628 775
+109 461
+680 1562
+457 507
+68 693
+795 935
+505 564
+706 951
+60 977
+501 1258
+441 539
+280 658
+787 1427
+311 866
+722 808
+94 679
+979 1850
+408 1002
+246 1068
+125 815
+520 819
+557 1306
+369 1123
+14 940
+666 931
+589 1555
+430 871
+105 907
+294 469
+798 1528
+30 640
+566 1287
+930 1651
+599 691
+139 256
+938 1775
+173 682
+597 899
+430 924
+201 1194
+164 611
+996 1009
+482 807
+680 1375
+281 704
+422 457
+698 963
+742 876
+839 1814
+901 1360
+775 1461
+612 801
+498 1360
+176 707
+430 596
+134 578
+408 742
+867 1346
+66 912
+390 824
+823 1332
+787 1775
+924 1615
+619 1109
+892 1583
+583 904
+591 1270
+805 815
+913 1698
+557 623
+15 98
+28 862
+775 981
+627 1137
+836 1587
+556 988
diff --git a/bottleneck/tests/data/test_874_A b/bottleneck/tests/data/test_874_A
new file mode 100644
index 0000000..4d66819
--- /dev/null
+++ b/bottleneck/tests/data/test_874_A
@@ -0,0 +1,100 @@
+401 767
+318 1182
+238 653
+420 702
+684 942
+381 618
+263 1108
+275 381
+659 1140
+301 646
+401 432
+68 350
+147 1106
+670 1593
+792 1332
+779 1462
+129 130
+604 665
+800 1027
+631 945
+961 1286
+767 1426
+123 653
+860 1160
+929 1528
+876 1665
+148 1072
+898 1869
+375 386
+135 943
+847 1128
+455 1273
+28 509
+202 1148
+241 462
+612 732
+655 667
+392 726
+525 655
+993 1778
+241 1229
+185 599
+321 836
+773 1506
+632 1023
+885 1663
+868 985
+84 664
+761 1738
+75 641
+988 1791
+178 992
+34 69
+990 1431
+460 957
+352 453
+102 946
+123 883
+535 1360
+961 1232
+825 885
+259 679
+139 620
+946 1073
+690 753
+39 1022
+741 1612
+662 1215
+156 703
+942 1906
+477 496
+499 737
+175 763
+304 563
+317 1266
+918 1673
+646 686
+941 1023
+502 1266
+811 822
+153 688
+892 1832
+737 1518
+53 475
+140 709
+379 871
+138 816
+228 1106
+272 774
+732 1715
+344 849
+580 971
+983 1855
+312 399
+561 1352
+335 1008
+268 1083
+488 921
+327 449
+177 198
diff --git a/bottleneck/tests/data/test_874_B b/bottleneck/tests/data/test_874_B
new file mode 100644
index 0000000..2142cbc
--- /dev/null
+++ b/bottleneck/tests/data/test_874_B
@@ -0,0 +1,100 @@
+682 1578
+580 1035
+713 1240
+664 1644
+492 852
+126 441
+113 329
+144 557
+829 1627
+857 1645
+332 1104
+531 773
+616 1523
+568 831
+251 340
+155 1058
+519 1241
+525 571
+182 334
+148 450
+974 1128
+508 1003
+188 738
+763 1502
+726 1288
+892 954
+418 1171
+414 927
+268 591
+529 1371
+10 396
+379 1371
+578 1428
+493 529
+79 364
+340 1082
+84 653
+847 1396
+905 1164
+526 690
+715 1436
+317 823
+161 223
+19 515
+520 1415
+871 1311
+601 1249
+533 1040
+454 1168
+35 919
+191 668
+102 424
+899 1107
+439 558
+145 1108
+138 1085
+633 756
+616 801
+795 1193
+428 892
+712 1066
+451 723
+294 640
+228 1009
+984 1910
+966 1472
+578 771
+403 896
+341 841
+441 671
+513 665
+137 386
+591 750
+881 1549
+753 1355
+66 695
+500 592
+364 715
+275 485
+841 1194
+204 386
+556 1196
+388 1345
+695 1051
+47 494
+505 1386
+427 933
+635 714
+998 1743
+637 822
+355 1048
+430 1086
+905 1747
+906 1612
+590 804
+709 1164
+852 1511
+205 626
+403 978
+706 1085
diff --git a/bottleneck/tests/data/test_875_A b/bottleneck/tests/data/test_875_A
new file mode 100644
index 0000000..1748357
--- /dev/null
+++ b/bottleneck/tests/data/test_875_A
@@ -0,0 +1,100 @@
+501 816
+326 1114
+214 1139
+167 352
+465 1246
+268 284
+830 907
+240 975
+995 1655
+583 822
+320 963
+446 975
+525 1385
+280 1057
+788 978
+238 1027
+731 1643
+154 467
+988 1430
+468 594
+170 779
+931 1377
+332 888
+432 1036
+310 841
+960 1909
+554 1147
+999 1007
+213 626
+667 862
+200 773
+166 657
+830 1352
+698 816
+455 850
+435 1100
+300 584
+935 1403
+544 1425
+78 451
+543 955
+831 1610
+530 633
+443 1150
+16 712
+798 1758
+760 1226
+839 1249
+310 891
+343 553
+341 463
+925 948
+691 851
+899 1768
+486 530
+830 1370
+515 894
+782 1153
+539 1004
+907 1348
+28 395
+335 626
+599 946
+571 1494
+607 1477
+560 1176
+27 63
+190 453
+586 1257
+659 831
+991 1363
+95 851
+226 785
+263 836
+97 531
+768 905
+970 1051
+487 1361
+96 206
+374 979
+539 1321
+837 1108
+776 1081
+381 774
+420 754
+799 983
+636 1239
+863 1608
+531 563
+703 814
+229 958
+874 1208
+553 581
+589 1387
+607 920
+928 1917
+171 351
+571 1035
+528 1318
+168 442
diff --git a/bottleneck/tests/data/test_875_B b/bottleneck/tests/data/test_875_B
new file mode 100644
index 0000000..3a5860e
--- /dev/null
+++ b/bottleneck/tests/data/test_875_B
@@ -0,0 +1,100 @@
+380 1025
+918 1126
+119 483
+810 1668
+393 693
+545 1003
+682 862
+357 966
+429 955
+776 1227
+233 522
+559 599
+514 843
+682 906
+535 810
+924 1161
+222 371
+400 741
+561 943
+60 644
+810 1317
+470 1412
+756 1724
+235 1098
+995 1942
+244 776
+189 1011
+549 622
+193 816
+336 535
+232 1076
+614 1332
+38 1001
+764 1255
+337 763
+30 878
+949 1522
+719 741
+446 749
+400 1077
+309 310
+154 677
+458 1246
+476 541
+177 660
+676 1084
+426 968
+422 888
+243 255
+724 901
+994 1350
+623 1151
+387 452
+745 1263
+142 572
+198 388
+789 1416
+445 970
+245 494
+253 499
+401 582
+217 271
+528 1475
+170 850
+978 1681
+68 170
+381 1017
+39 298
+634 1443
+288 447
+867 1061
+24 477
+345 869
+674 1544
+645 1452
+698 723
+838 1195
+419 1214
+468 476
+620 1599
+898 1491
+416 1010
+431 921
+56 242
+867 1451
+759 1102
+396 1226
+559 1364
+212 743
+292 1289
+832 1536
+271 340
+990 1428
+287 1025
+364 839
+471 1138
+17 284
+953 1212
+421 841
+527 1382
diff --git a/bottleneck/tests/data/test_876_A b/bottleneck/tests/data/test_876_A
new file mode 100644
index 0000000..1b65f8d
--- /dev/null
+++ b/bottleneck/tests/data/test_876_A
@@ -0,0 +1,100 @@
+466 895
+77 814
+639 1357
+475 1032
+941 1560
+527 749
+839 845
+96 619
+328 455
+385 828
+954 1817
+476 847
+240 463
+477 849
+965 1359
+238 991
+746 1597
+109 529
+567 616
+525 1224
+80 990
+984 1314
+591 1398
+801 1039
+237 332
+529 1232
+8 763
+665 1615
+823 1790
+746 1594
+875 1682
+302 1001
+486 840
+586 1174
+376 903
+782 1083
+680 993
+811 1136
+576 687
+330 1057
+892 963
+547 763
+17 869
+207 455
+162 612
+414 776
+446 498
+455 1151
+292 355
+240 541
+89 545
+672 1017
+375 783
+152 348
+347 525
+678 682
+538 1301
+569 1458
+624 946
+188 283
+300 456
+225 423
+925 1867
+312 600
+849 984
+148 300
+236 862
+336 806
+566 1280
+793 1411
+789 1666
+134 714
+660 1259
+870 1344
+329 1320
+136 684
+743 1016
+904 1005
+271 1059
+28 566
+482 1474
+278 614
+776 1361
+372 1174
+118 589
+793 906
+346 539
+860 892
+588 1255
+590 1394
+258 935
+452 861
+785 1525
+789 1745
+150 622
+720 1458
+486 1477
+937 1381
+317 1224
+37 301
diff --git a/bottleneck/tests/data/test_876_B b/bottleneck/tests/data/test_876_B
new file mode 100644
index 0000000..62102e9
--- /dev/null
+++ b/bottleneck/tests/data/test_876_B
@@ -0,0 +1,100 @@
+162 530
+694 1522
+850 1742
+293 471
+254 1094
+293 856
+392 411
+919 1673
+427 629
+116 390
+583 1089
+31 812
+270 769
+297 435
+933 1186
+625 741
+759 868
+632 749
+41 82
+138 528
+933 1746
+910 1135
+312 868
+955 1464
+208 1044
+84 368
+444 1114
+749 1643
+572 1339
+584 1330
+736 1483
+779 780
+459 473
+481 1392
+537 1402
+254 1114
+637 1366
+381 1339
+808 1517
+858 1513
+116 508
+102 675
+133 327
+283 1196
+126 910
+634 699
+253 1086
+75 1063
+93 247
+194 661
+848 1195
+690 1350
+816 1340
+821 1352
+387 569
+487 870
+160 1012
+483 1120
+916 1704
+519 975
+324 533
+791 1611
+128 1011
+477 741
+884 930
+773 1424
+904 1238
+252 1162
+730 750
+292 441
+747 1242
+525 1071
+373 1261
+706 1402
+877 1639
+848 1474
+652 884
+995 1061
+509 1496
+970 1168
+855 1167
+94 289
+759 1697
+153 239
+483 1315
+694 1110
+93 255
+564 1525
+632 1562
+218 1068
+548 1072
+167 906
+803 1710
+635 914
+923 1918
+99 633
+8 712
+138 565
+698 1179
+928 1611
diff --git a/bottleneck/tests/data/test_877_A b/bottleneck/tests/data/test_877_A
new file mode 100644
index 0000000..c60479b
--- /dev/null
+++ b/bottleneck/tests/data/test_877_A
@@ -0,0 +1,100 @@
+300 707
+123 319
+525 876
+685 1396
+289 961
+27 123
+884 1628
+982 1831
+634 1123
+383 831
+279 637
+349 474
+352 856
+253 1047
+431 679
+986 1871
+923 1654
+991 1073
+686 1337
+848 1810
+180 753
+423 529
+318 466
+356 742
+953 997
+861 865
+205 1200
+423 1141
+976 1485
+698 775
+445 1410
+83 322
+11 585
+384 468
+674 1121
+544 1216
+205 648
+474 745
+860 1595
+624 1216
+970 1721
+505 1397
+886 1137
+184 706
+817 1142
+781 1282
+299 965
+835 940
+954 1359
+304 502
+309 949
+347 441
+80 406
+804 910
+895 1394
+835 1328
+586 634
+790 1152
+884 1203
+252 899
+91 828
+501 968
+971 1076
+676 1214
+217 318
+932 1399
+404 451
+235 1091
+765 1022
+974 1189
+353 989
+828 1769
+948 1846
+914 1206
+589 1406
+551 1139
+317 367
+616 1284
+567 895
+229 528
+533 911
+514 1260
+905 1811
+421 863
+681 925
+252 1023
+365 573
+195 886
+169 710
+327 1311
+348 388
+26 56
+534 1014
+187 263
+927 1764
+3 29
+469 1008
+968 1729
+279 611
+944 1650
diff --git a/bottleneck/tests/data/test_877_B b/bottleneck/tests/data/test_877_B
new file mode 100644
index 0000000..728311d
--- /dev/null
+++ b/bottleneck/tests/data/test_877_B
@@ -0,0 +1,100 @@
+628 985
+787 1122
+361 604
+695 1462
+712 977
+294 738
+893 1223
+582 1579
+908 1112
+827 1451
+360 465
+273 375
+123 803
+853 1841
+381 948
+549 868
+34 995
+285 1076
+233 561
+232 1170
+663 1129
+17 34
+41 274
+881 1726
+551 1357
+193 916
+754 852
+384 1061
+745 1426
+954 1188
+950 1469
+493 565
+307 1174
+486 1222
+443 1433
+722 973
+912 1453
+973 1474
+398 1142
+85 779
+961 1952
+928 1842
+351 814
+147 519
+729 877
+26 60
+406 1082
+579 602
+893 1692
+837 1802
+306 457
+945 1792
+461 897
+794 894
+767 1178
+469 1423
+129 833
+251 563
+887 1856
+426 1380
+173 539
+398 1249
+890 1101
+40 864
+481 1123
+651 1126
+520 926
+885 1396
+791 896
+416 1283
+646 1571
+246 1002
+249 394
+650 1543
+378 1225
+918 1043
+58 188
+568 671
+256 796
+315 1143
+840 1449
+709 1260
+730 1655
+525 1409
+561 1149
+338 1162
+204 252
+935 1919
+438 1194
+727 1497
+876 1461
+920 1163
+19 767
+379 427
+953 1926
+912 1022
+423 584
+333 642
+726 1473
+421 1106
diff --git a/bottleneck/tests/data/test_878_A b/bottleneck/tests/data/test_878_A
new file mode 100644
index 0000000..c8d0724
--- /dev/null
+++ b/bottleneck/tests/data/test_878_A
@@ -0,0 +1,100 @@
+279 1254
+922 1250
+849 997
+144 505
+218 1071
+540 1361
+681 773
+572 1345
+827 848
+105 244
+299 1253
+172 784
+730 1315
+488 1249
+803 1175
+139 611
+910 1599
+387 1304
+851 1418
+392 1256
+642 655
+323 338
+594 802
+761 1161
+980 1822
+272 811
+385 474
+70 568
+518 1331
+528 1188
+138 465
+71 1033
+258 968
+242 319
+644 1125
+988 1292
+828 1367
+726 1657
+61 520
+734 1189
+142 615
+794 1276
+267 575
+738 1043
+653 753
+484 1337
+680 761
+963 972
+415 1343
+167 685
+93 861
+263 506
+609 829
+145 436
+302 484
+10 881
+431 603
+638 764
+723 1348
+470 581
+418 1249
+61 814
+992 1096
+776 1386
+406 842
+204 1047
+450 710
+639 765
+272 807
+932 1571
+982 1321
+559 770
+255 363
+648 1136
+668 1322
+332 588
+387 390
+309 737
+561 1463
+958 981
+359 1053
+994 1768
+243 381
+971 1245
+96 704
+353 1090
+589 1261
+46 789
+459 519
+262 425
+154 710
+870 1103
+30 653
+672 1521
+824 1677
+763 835
+143 753
+658 1168
+8 563
+971 1095
diff --git a/bottleneck/tests/data/test_878_B b/bottleneck/tests/data/test_878_B
new file mode 100644
index 0000000..32723ce
--- /dev/null
+++ b/bottleneck/tests/data/test_878_B
@@ -0,0 +1,100 @@
+284 785
+695 1555
+939 1668
+395 439
+587 754
+586 996
+831 1534
+296 1185
+379 1162
+243 923
+818 1623
+410 644
+43 356
+929 1429
+83 937
+885 1611
+427 526
+225 804
+717 1460
+30 590
+125 1119
+600 1356
+803 1729
+462 542
+225 785
+26 79
+780 1711
+372 1148
+113 547
+589 1288
+673 1638
+56 555
+569 1078
+687 1547
+201 777
+860 1372
+317 1268
+481 1465
+577 1347
+355 639
+199 560
+669 911
+64 1003
+654 1047
+254 700
+126 542
+418 1041
+242 1075
+642 1349
+476 1047
+614 1041
+365 507
+117 842
+147 929
+369 835
+138 1031
+177 707
+857 968
+803 821
+562 1007
+231 1021
+872 1803
+84 613
+315 562
+962 965
+648 1619
+425 574
+303 654
+766 1676
+17 975
+127 960
+439 645
+646 1215
+448 1375
+697 1654
+294 314
+151 661
+800 1084
+760 1457
+944 1538
+224 895
+309 355
+688 1059
+509 1108
+770 793
+884 947
+147 963
+708 1229
+398 816
+8 872
+617 1057
+642 1609
+558 1128
+409 705
+777 1406
+454 640
+882 1002
+391 1241
+609 1380
+455 863
diff --git a/bottleneck/tests/data/test_879_A b/bottleneck/tests/data/test_879_A
new file mode 100644
index 0000000..7a92be6
--- /dev/null
+++ b/bottleneck/tests/data/test_879_A
@@ -0,0 +1,100 @@
+939 1572
+712 1236
+114 128
+992 1777
+566 617
+460 1258
+681 1380
+716 832
+375 960
+912 1414
+63 1058
+943 1482
+278 690
+123 616
+31 641
+382 862
+962 1798
+709 1518
+190 487
+84 723
+419 515
+105 915
+184 641
+952 1441
+139 760
+462 879
+431 577
+502 1482
+252 1124
+166 413
+406 426
+40 921
+538 936
+850 1574
+64 139
+472 1374
+171 944
+81 128
+107 521
+426 855
+273 278
+139 208
+763 893
+623 973
+433 565
+353 915
+404 945
+981 1151
+200 894
+476 1268
+913 1287
+609 1592
+984 1462
+878 1037
+255 1113
+845 1766
+257 265
+550 1385
+753 1597
+412 1269
+251 1120
+167 851
+288 1117
+392 1279
+213 534
+623 987
+975 1806
+924 1066
+52 676
+822 974
+239 557
+679 1158
+268 524
+241 500
+281 401
+993 1711
+539 1414
+677 1108
+377 482
+315 845
+981 1605
+426 447
+479 1372
+820 1416
+916 1423
+677 1165
+388 1322
+990 1641
+909 914
+814 1225
+851 1151
+78 235
+635 1581
+229 431
+125 877
+708 1338
+763 1354
+877 1794
+225 1171
+232 435
diff --git a/bottleneck/tests/data/test_879_B b/bottleneck/tests/data/test_879_B
new file mode 100644
index 0000000..f4c4a36
--- /dev/null
+++ b/bottleneck/tests/data/test_879_B
@@ -0,0 +1,100 @@
+826 1808
+951 1166
+931 1147
+239 288
+607 762
+103 692
+78 132
+14 502
+666 982
+207 961
+303 690
+492 1135
+528 1499
+979 1576
+584 704
+921 1134
+874 1791
+51 789
+824 1574
+534 1078
+304 1104
+288 828
+445 1433
+492 788
+158 159
+374 863
+313 766
+716 1156
+540 624
+963 1803
+144 341
+415 1223
+314 501
+203 739
+674 1323
+604 705
+958 1738
+33 994
+179 1002
+23 278
+387 460
+857 1659
+563 865
+248 1032
+612 1147
+809 1802
+488 1003
+572 1525
+197 664
+120 648
+290 793
+475 1101
+97 479
+517 703
+843 1555
+292 482
+293 846
+969 1431
+525 552
+299 795
+543 1520
+685 1208
+689 1139
+564 1021
+478 969
+219 646
+361 718
+390 1038
+167 677
+968 1814
+663 1192
+446 1405
+337 1080
+403 564
+167 1159
+717 1483
+707 1224
+923 1698
+564 833
+988 1819
+48 300
+5 540
+252 378
+385 1039
+65 366
+473 1119
+369 989
+804 1501
+333 580
+321 1033
+693 1147
+291 408
+498 1244
+923 1204
+758 1214
+85 561
+550 647
+589 1155
+512 687
+110 459
diff --git a/bottleneck/tests/data/test_list.txt b/bottleneck/tests/data/test_list.txt
new file mode 100644
index 0000000..24b462a
--- /dev/null
+++ b/bottleneck/tests/data/test_list.txt
@@ -0,0 +1,792 @@
+test_001_A test_001_B 0.01 1 -1 0 0 -1
+test_002_A test_002_B 0.01 0.2 0 0
+test_003_A test_003_B 0.01 2 1 1
+test_004_A test_004_B 0.01 inf -1 -1
+test_005_A test_005_B 0.01 4 5 5
+test_008_A test_008_B 0.01 0.55 0 -1
+test_009_A test_009_B 0.01 0.55 0 -1
+test_010_A test_010_B 0.01 1.32937
+test_011_A test_011_B 0.01 1.03125
+test_014_A test_014_B 0.01 0
+test_015_A test_015_B 0.01 0
+test_016_A test_016_B 0.01 0
+test_100_A test_100_B 0.01 1.5
+test_101_A test_101_B 0.01 1.5
+test_102_A test_102_B 0.01 4.5
+test_103_A test_103_B 0.01 3
+test_104_A test_104_B 0.01 3.5
+test_105_A test_105_B 0.01 3.5
+test_106_A test_106_B 0.01 3
+test_107_A test_107_B 0.01 5
+test_108_A test_108_B 0.01 5
+test_109_A test_109_B 0.01 3
+test_110_A test_110_B 0.01 4.5
+test_111_A test_111_B 0.01 4
+test_112_A test_112_B 0.01 4
+test_113_A test_113_B 0.01 2.5
+test_114_A test_114_B 0.01 4.5
+test_115_A test_115_B 0.01 4
+test_116_A test_116_B 0.01 4
+test_117_A test_117_B 0.01 2.5
+test_118_A test_118_B 0.01 3
+test_119_A test_119_B 0.01 5
+test_120_A test_120_B 0.01 2
+test_121_A test_121_B 0.01 3
+test_122_A test_122_B 0.01 1
+test_123_A test_123_B 0.01 4
+test_124_A test_124_B 0.01 4
+test_125_A test_125_B 0.01 4.5
+test_126_A test_126_B 0.01 3
+test_127_A test_127_B 0.01 2.5
+test_128_A test_128_B 0.01 2
+test_129_A test_129_B 0.01 3
+test_130_A test_130_B 0.01 5
+test_131_A test_131_B 0.01 5
+test_132_A test_132_B 0.01 2
+test_133_A test_133_B 0.01 3
+test_134_A test_134_B 0.01 3
+test_135_A test_135_B 0.01 4
+test_136_A test_136_B 0.01 2
+test_137_A test_137_B 0.01 3
+test_138_A test_138_B 0.01 2
+test_139_A test_139_B 0.01 2.5
+test_140_A test_140_B 0.01 2
+test_141_A test_141_B 0.01 4
+test_142_A test_142_B 0.01 3
+test_143_A test_143_B 0.01 4
+test_144_A test_144_B 0.01 3
+test_145_A test_145_B 0.01 4
+test_146_A test_146_B 0.01 3
+test_147_A test_147_B 0.01 4
+test_148_A test_148_B 0.01 3
+test_149_A test_149_B 0.01 4
+test_150_A test_150_B 0.01 3
+test_151_A test_151_B 0.01 4
+test_152_A test_152_B 0.01 3.5
+test_153_A test_153_B 0.01 4
+test_154_A test_154_B 0.01 3.5
+test_155_A test_155_B 0.01 3
+test_156_A test_156_B 0.01 3
+test_157_A test_157_B 0.01 4.5
+test_158_A test_158_B 0.01 3.5
+test_159_A test_159_B 0.01 1
+test_160_A test_160_B 0.01 4
+test_161_A test_161_B 0.01 4
+test_162_A test_162_B 0.01 3
+test_163_A test_163_B 0.01 5
+test_164_A test_164_B 0.01 4
+test_165_A test_165_B 0.01 4
+test_166_A test_166_B 0.01 4
+test_167_A test_167_B 0.01 4.5
+test_168_A test_168_B 0.01 4
+test_169_A test_169_B 0.01 3.5
+test_170_A test_170_B 0.01 4
+test_171_A test_171_B 0.01 2
+test_172_A test_172_B 0.01 3
+test_173_A test_173_B 0.01 4
+test_174_A test_174_B 0.01 3
+test_175_A test_175_B 0.01 5
+test_176_A test_176_B 0.01 4.5
+test_177_A test_177_B 0.01 4.5
+test_178_A test_178_B 0.01 4.5
+test_179_A test_179_B 0.01 4
+test_180_A test_180_B 0.01 5
+test_181_A test_181_B 0.01 4
+test_182_A test_182_B 0.01 4.5
+test_183_A test_183_B 0.01 5
+test_184_A test_184_B 0.01 4
+test_185_A test_185_B 0.01 4.5
+test_186_A test_186_B 0.01 3
+test_187_A test_187_B 0.01 4.5
+test_188_A test_188_B 0.01 3
+test_189_A test_189_B 0.01 2
+test_190_A test_190_B 0.01 3
+test_191_A test_191_B 0.01 3
+test_192_A test_192_B 0.01 3.5
+test_193_A test_193_B 0.01 4.5
+test_194_A test_194_B 0.01 3
+test_195_A test_195_B 0.01 3
+test_196_A test_196_B 0.01 3
+test_197_A test_197_B 0.01 3
+test_198_A test_198_B 0.01 5
+test_199_A test_199_B 0.01 3.5
+test_200_A test_200_B 0.01 3
+test_201_A test_201_B 0.01 5
+test_202_A test_202_B 0.01 3
+test_203_A test_203_B 0.01 4
+test_204_A test_204_B 0.01 2.5
+test_205_A test_205_B 0.01 4
+test_206_A test_206_B 0.01 3.5
+test_207_A test_207_B 0.01 3
+test_208_A test_208_B 0.01 4
+test_209_A test_209_B 0.01 3
+test_210_A test_210_B 0.01 5
+test_211_A test_211_B 0.01 3
+test_212_A test_212_B 0.01 3
+test_213_A test_213_B 0.01 3.5
+test_214_A test_214_B 0.01 4
+test_215_A test_215_B 0.01 3
+test_216_A test_216_B 0.01 3.5
+test_217_A test_217_B 0.01 4
+test_218_A test_218_B 0.01 4
+test_219_A test_219_B 0.01 4
+test_220_A test_220_B 0.01 3
+test_221_A test_221_B 0.01 4
+test_222_A test_222_B 0.01 4
+test_223_A test_223_B 0.01 4
+test_224_A test_224_B 0.01 3
+test_225_A test_225_B 0.01 3
+test_226_A test_226_B 0.01 4
+test_227_A test_227_B 0.01 4
+test_228_A test_228_B 0.01 4
+test_229_A test_229_B 0.01 3
+test_230_A test_230_B 0.01 3
+test_231_A test_231_B 0.01 4
+test_232_A test_232_B 0.01 4
+test_233_A test_233_B 0.01 2
+test_234_A test_234_B 0.01 3.5
+test_235_A test_235_B 0.01 4
+test_236_A test_236_B 0.01 3
+test_237_A test_237_B 0.01 3.5
+test_238_A test_238_B 0.01 4
+test_239_A test_239_B 0.01 3
+test_240_A test_240_B 0.01 3
+test_241_A test_241_B 0.01 5
+test_242_A test_242_B 0.01 4.5
+test_243_A test_243_B 0.01 4
+test_244_A test_244_B 0.01 3.5
+test_245_A test_245_B 0.01 5
+test_246_A test_246_B 0.01 2.5
+test_247_A test_247_B 0.01 3
+test_248_A test_248_B 0.01 4
+test_249_A test_249_B 0.01 2
+test_250_A test_250_B 0.01 5
+test_251_A test_251_B 0.01 4
+test_252_A test_252_B 0.01 4
+test_253_A test_253_B 0.01 4.5
+test_254_A test_254_B 0.01 4
+test_255_A test_255_B 0.01 3
+test_256_A test_256_B 0.01 4.5
+test_257_A test_257_B 0.01 4
+test_258_A test_258_B 0.01 5
+test_259_A test_259_B 0.01 4
+test_260_A test_260_B 0.01 4
+test_261_A test_261_B 0.01 2.5
+test_262_A test_262_B 0.01 2
+test_263_A test_263_B 0.01 4.5
+test_264_A test_264_B 0.01 3.5
+test_265_A test_265_B 0.01 4
+test_266_A test_266_B 0.01 3
+test_267_A test_267_B 0.01 5
+test_268_A test_268_B 0.01 4
+test_269_A test_269_B 0.01 4
+test_270_A test_270_B 0.01 3
+test_271_A test_271_B 0.01 4
+test_272_A test_272_B 0.01 4
+test_273_A test_273_B 0.01 2
+test_274_A test_274_B 0.01 3
+test_275_A test_275_B 0.01 3
+test_276_A test_276_B 0.01 4
+test_277_A test_277_B 0.01 5
+test_278_A test_278_B 0.01 4
+test_279_A test_279_B 0.01 4.5
+test_280_A test_280_B 0.01 3.5
+test_281_A test_281_B 0.01 2
+test_282_A test_282_B 0.01 3
+test_283_A test_283_B 0.01 3
+test_284_A test_284_B 0.01 3
+test_285_A test_285_B 0.01 3
+test_286_A test_286_B 0.01 3
+test_287_A test_287_B 0.01 3.5
+test_288_A test_288_B 0.01 3
+test_289_A test_289_B 0.01 2
+test_290_A test_290_B 0.01 4
+test_291_A test_291_B 0.01 3
+test_292_A test_292_B 0.01 4
+test_293_A test_293_B 0.01 2.5
+test_294_A test_294_B 0.01 4
+test_295_A test_295_B 0.01 3.5
+test_296_A test_296_B 0.01 3
+test_297_A test_297_B 0.01 3
+test_298_A test_298_B 0.01 4
+test_299_A test_299_B 0.01 4
+test_300_A test_300_B 0.01 3
+test_301_A test_301_B 0.01 2
+test_302_A test_302_B 0.01 2
+test_303_A test_303_B 0.01 3
+test_304_A test_304_B 0.01 3
+test_305_A test_305_B 0.01 3
+test_306_A test_306_B 0.01 3
+test_307_A test_307_B 0.01 2
+test_308_A test_308_B 0.01 3
+test_309_A test_309_B 0.01 2.5
+test_310_A test_310_B 0.01 4
+test_311_A test_311_B 0.01 3
+test_312_A test_312_B 0.01 3.5
+test_313_A test_313_B 0.01 3
+test_314_A test_314_B 0.01 2
+test_315_A test_315_B 0.01 3
+test_316_A test_316_B 0.01 4.5
+test_317_A test_317_B 0.01 3
+test_318_A test_318_B 0.01 3
+test_319_A test_319_B 0.01 3
+test_320_A test_320_B 0.01 4
+test_321_A test_321_B 0.01 2
+test_322_A test_322_B 0.01 3
+test_323_A test_323_B 0.01 3
+test_324_A test_324_B 0.01 2
+test_325_A test_325_B 0.01 3
+test_326_A test_326_B 0.01 2
+test_327_A test_327_B 0.01 3
+test_328_A test_328_B 0.01 3
+test_329_A test_329_B 0.01 4
+test_330_A test_330_B 0.01 3
+test_331_A test_331_B 0.01 3
+test_332_A test_332_B 0.01 2
+test_333_A test_333_B 0.01 2
+test_334_A test_334_B 0.01 3
+test_335_A test_335_B 0.01 2
+test_336_A test_336_B 0.01 3
+test_337_A test_337_B 0.01 2
+test_338_A test_338_B 0.01 2
+test_339_A test_339_B 0.01 2
+test_340_A test_340_B 0.01 1
+test_341_A test_341_B 0.01 2
+test_342_A test_342_B 0.01 2
+test_343_A test_343_B 0.01 2
+test_344_A test_344_B 0.01 2
+test_345_A test_345_B 0.01 2
+test_346_A test_346_B 0.01 2
+test_347_A test_347_B 0.01 2
+test_348_A test_348_B 0.01 2
+test_349_A test_349_B 0.01 2
+test_350_A test_350_B 0.01 2
+test_351_A test_351_B 0.01 2
+test_352_A test_352_B 0.01 2
+test_353_A test_353_B 0.01 2.5
+test_354_A test_354_B 0.01 2
+test_355_A test_355_B 0.01 2
+test_356_A test_356_B 0.01 2
+test_357_A test_357_B 0.01 2
+test_358_A test_358_B 0.01 2
+test_359_A test_359_B 0.01 2
+test_360_A test_360_B 0.01 32
+test_361_A test_361_B 0.01 8
+test_362_A test_362_B 0.01 29.5
+test_363_A test_363_B 0.01 41
+test_364_A test_364_B 0.01 41.5
+test_365_A test_365_B 0.01 27.5
+test_366_A test_366_B 0.01 46
+test_367_A test_367_B 0.01 37.5
+test_368_A test_368_B 0.01 27
+test_369_A test_369_B 0.01 42
+test_370_A test_370_B 0.01 45.5
+test_371_A test_371_B 0.01 34
+test_372_A test_372_B 0.01 19.5
+test_373_A test_373_B 0.01 24
+test_374_A test_374_B 0.01 10
+test_375_A test_375_B 0.01 17.5
+test_376_A test_376_B 0.01 28.5
+test_377_A test_377_B 0.01 40
+test_378_A test_378_B 0.01 40
+test_379_A test_379_B 0.01 24.5
+test_380_A test_380_B 0.01 36
+test_381_A test_381_B 0.01 38
+test_382_A test_382_B 0.01 48
+test_383_A test_383_B 0.01 32.5
+test_384_A test_384_B 0.01 44
+test_385_A test_385_B 0.01 44.5
+test_386_A test_386_B 0.01 11
+test_387_A test_387_B 0.01 47.5
+test_388_A test_388_B 0.01 28
+test_389_A test_389_B 0.01 32
+test_390_A test_390_B 0.01 24.5
+test_391_A test_391_B 0.01 47
+test_392_A test_392_B 0.01 28
+test_393_A test_393_B 0.01 16
+test_394_A test_394_B 0.01 44
+test_395_A test_395_B 0.01 38
+test_396_A test_396_B 0.01 47.5
+test_397_A test_397_B 0.01 35
+test_398_A test_398_B 0.01 33
+test_399_A test_399_B 0.01 33
+test_400_A test_400_B 0.01 31
+test_401_A test_401_B 0.01 48
+test_402_A test_402_B 0.01 37.5
+test_403_A test_403_B 0.01 40
+test_404_A test_404_B 0.01 47
+test_405_A test_405_B 0.01 23
+test_406_A test_406_B 0.01 40
+test_407_A test_407_B 0.01 46
+test_408_A test_408_B 0.01 39
+test_409_A test_409_B 0.01 26
+test_410_A test_410_B 0.01 28
+test_411_A test_411_B 0.01 27
+test_412_A test_412_B 0.01 33
+test_413_A test_413_B 0.01 36
+test_414_A test_414_B 0.01 42.5
+test_415_A test_415_B 0.01 40
+test_416_A test_416_B 0.01 37
+test_417_A test_417_B 0.01 43
+test_418_A test_418_B 0.01 16
+test_419_A test_419_B 0.01 34
+test_420_A test_420_B 0.01 42.5
+test_421_A test_421_B 0.01 38
+test_422_A test_422_B 0.01 30
+test_423_A test_423_B 0.01 44
+test_424_A test_424_B 0.01 46
+test_425_A test_425_B 0.01 38
+test_426_A test_426_B 0.01 35.5
+test_427_A test_427_B 0.01 29
+test_428_A test_428_B 0.01 43.5
+test_429_A test_429_B 0.01 34
+test_430_A test_430_B 0.01 48
+test_431_A test_431_B 0.01 41
+test_432_A test_432_B 0.01 35
+test_433_A test_433_B 0.01 32
+test_434_A test_434_B 0.01 36
+test_435_A test_435_B 0.01 43.5
+test_436_A test_436_B 0.01 32.5
+test_437_A test_437_B 0.01 40
+test_438_A test_438_B 0.01 34
+test_439_A test_439_B 0.01 31.5
+test_440_A test_440_B 0.01 26.5
+test_441_A test_441_B 0.01 49.5
+test_442_A test_442_B 0.01 30
+test_443_A test_443_B 0.01 29
+test_444_A test_444_B 0.01 29
+test_445_A test_445_B 0.01 48
+test_446_A test_446_B 0.01 35
+test_447_A test_447_B 0.01 43
+test_448_A test_448_B 0.01 19
+test_449_A test_449_B 0.01 34
+test_450_A test_450_B 0.01 44
+test_451_A test_451_B 0.01 36
+test_452_A test_452_B 0.01 32
+test_453_A test_453_B 0.01 49
+test_454_A test_454_B 0.01 48.5
+test_455_A test_455_B 0.01 46
+test_456_A test_456_B 0.01 33.5
+test_457_A test_457_B 0.01 49.5
+test_458_A test_458_B 0.01 38
+test_459_A test_459_B 0.01 21
+test_460_A test_460_B 0.01 40
+test_461_A test_461_B 0.01 32
+test_462_A test_462_B 0.01 37
+test_463_A test_463_B 0.01 23
+test_464_A test_464_B 0.01 19
+test_465_A test_465_B 0.01 29
+test_466_A test_466_B 0.01 38
+test_467_A test_467_B 0.01 29
+test_468_A test_468_B 0.01 45
+test_469_A test_469_B 0.01 27.5
+test_470_A test_470_B 0.01 43
+test_471_A test_471_B 0.01 24.5
+test_472_A test_472_B 0.01 42
+test_473_A test_473_B 0.01 36.5
+test_474_A test_474_B 0.01 46.5
+test_475_A test_475_B 0.01 18
+test_476_A test_476_B 0.01 29
+test_477_A test_477_B 0.01 44
+test_478_A test_478_B 0.01 49
+test_479_A test_479_B 0.01 33
+test_480_A test_480_B 0.01 43
+test_481_A test_481_B 0.01 42
+test_482_A test_482_B 0.01 31
+test_483_A test_483_B 0.01 37
+test_484_A test_484_B 0.01 25
+test_485_A test_485_B 0.01 33
+test_486_A test_486_B 0.01 35
+test_487_A test_487_B 0.01 39
+test_488_A test_488_B 0.01 26.5
+test_489_A test_489_B 0.01 39.5
+test_490_A test_490_B 0.01 26
+test_491_A test_491_B 0.01 45
+test_492_A test_492_B 0.01 21
+test_493_A test_493_B 0.01 37
+test_494_A test_494_B 0.01 50
+test_495_A test_495_B 0.01 41
+test_496_A test_496_B 0.01 34
+test_497_A test_497_B 0.01 35
+test_498_A test_498_B 0.01 34
+test_499_A test_499_B 0.01 30
+test_500_A test_500_B 0.01 39
+test_501_A test_501_B 0.01 36
+test_502_A test_502_B 0.01 36
+test_503_A test_503_B 0.01 49.5
+test_504_A test_504_B 0.01 40.5
+test_505_A test_505_B 0.01 29
+test_506_A test_506_B 0.01 33
+test_507_A test_507_B 0.01 38
+test_508_A test_508_B 0.01 21.5
+test_509_A test_509_B 0.01 27
+test_510_A test_510_B 0.01 43
+test_511_A test_511_B 0.01 34
+test_512_A test_512_B 0.01 25.5
+test_513_A test_513_B 0.01 19
+test_514_A test_514_B 0.01 28
+test_515_A test_515_B 0.01 41.5
+test_516_A test_516_B 0.01 46
+test_517_A test_517_B 0.01 34
+test_518_A test_518_B 0.01 33
+test_519_A test_519_B 0.01 37.5
+test_520_A test_520_B 0.01 37
+test_521_A test_521_B 0.01 42.5
+test_522_A test_522_B 0.01 44
+test_523_A test_523_B 0.01 36.5
+test_524_A test_524_B 0.01 40
+test_525_A test_525_B 0.01 36.5
+test_526_A test_526_B 0.01 24
+test_527_A test_527_B 0.01 34
+test_528_A test_528_B 0.01 23.5
+test_529_A test_529_B 0.01 30
+test_530_A test_530_B 0.01 50
+test_531_A test_531_B 0.01 33
+test_532_A test_532_B 0.01 36
+test_533_A test_533_B 0.01 24
+test_534_A test_534_B 0.01 46.5
+test_535_A test_535_B 0.01 39
+test_536_A test_536_B 0.01 26
+test_537_A test_537_B 0.01 30
+test_538_A test_538_B 0.01 27.5
+test_539_A test_539_B 0.01 26
+test_540_A test_540_B 0.01 23
+test_541_A test_541_B 0.01 26.5
+test_542_A test_542_B 0.01 40.5
+test_543_A test_543_B 0.01 41
+test_544_A test_544_B 0.01 46
+test_545_A test_545_B 0.01 33
+test_546_A test_546_B 0.01 38
+test_547_A test_547_B 0.01 33
+test_548_A test_548_B 0.01 28
+test_549_A test_549_B 0.01 29
+test_550_A test_550_B 0.01 33
+test_551_A test_551_B 0.01 20
+test_552_A test_552_B 0.01 27
+test_553_A test_553_B 0.01 21.5
+test_554_A test_554_B 0.01 28
+test_555_A test_555_B 0.01 31
+test_556_A test_556_B 0.01 31
+test_557_A test_557_B 0.01 30
+test_558_A test_558_B 0.01 29
+test_559_A test_559_B 0.01 30
+test_560_A test_560_B 0.01 21
+test_561_A test_561_B 0.01 37.5
+test_562_A test_562_B 0.01 40
+test_563_A test_563_B 0.01 25
+test_564_A test_564_B 0.01 22
+test_565_A test_565_B 0.01 24
+test_566_A test_566_B 0.01 39
+test_567_A test_567_B 0.01 27
+test_568_A test_568_B 0.01 30
+test_569_A test_569_B 0.01 35
+test_570_A test_570_B 0.01 29
+test_571_A test_571_B 0.01 27
+test_572_A test_572_B 0.01 23
+test_573_A test_573_B 0.01 34
+test_574_A test_574_B 0.01 26
+test_575_A test_575_B 0.01 28
+test_576_A test_576_B 0.01 22
+test_577_A test_577_B 0.01 29
+test_578_A test_578_B 0.01 24
+test_579_A test_579_B 0.01 22
+test_580_A test_580_B 0.01 31
+test_581_A test_581_B 0.01 39
+test_582_A test_582_B 0.01 21
+test_583_A test_583_B 0.01 32
+test_584_A test_584_B 0.01 22
+test_585_A test_585_B 0.01 26
+test_586_A test_586_B 0.01 20
+test_587_A test_587_B 0.01 28
+test_588_A test_588_B 0.01 22
+test_589_A test_589_B 0.01 20
+test_590_A test_590_B 0.01 17
+test_591_A test_591_B 0.01 24
+test_592_A test_592_B 0.01 27.5
+test_593_A test_593_B 0.01 31
+test_594_A test_594_B 0.01 18
+test_595_A test_595_B 0.01 18
+test_596_A test_596_B 0.01 32
+test_597_A test_597_B 0.01 17
+test_598_A test_598_B 0.01 19
+test_599_A test_599_B 0.01 23
+test_600_A test_600_B 0.01 16
+test_601_A test_601_B 0.01 13
+test_602_A test_602_B 0.01 25
+test_603_A test_603_B 0.01 17
+test_604_A test_604_B 0.01 18
+test_605_A test_605_B 0.01 20
+test_606_A test_606_B 0.01 16
+test_607_A test_607_B 0.01 19
+test_608_A test_608_B 0.01 22
+test_609_A test_609_B 0.01 18
+test_610_A test_610_B 0.01 22
+test_611_A test_611_B 0.01 18
+test_612_A test_612_B 0.01 21
+test_613_A test_613_B 0.01 23
+test_614_A test_614_B 0.01 14
+test_615_A test_615_B 0.01 21
+test_616_A test_616_B 0.01 20
+test_617_A test_617_B 0.01 17
+test_618_A test_618_B 0.01 15
+test_619_A test_619_B 0.01 18
+test_620_A test_620_B 0.01 346.5
+test_621_A test_621_B 0.01 414
+test_622_A test_622_B 0.01 321
+test_623_A test_623_B 0.01 428
+test_624_A test_624_B 0.01 137.5
+test_625_A test_625_B 0.01 272
+test_626_A test_626_B 0.01 257
+test_627_A test_627_B 0.01 261
+test_628_A test_628_B 0.01 480.5
+test_629_A test_629_B 0.01 378
+test_630_A test_630_B 0.01 153.5
+test_631_A test_631_B 0.01 199
+test_632_A test_632_B 0.01 457
+test_633_A test_633_B 0.01 358.5
+test_634_A test_634_B 0.01 357
+test_635_A test_635_B 0.01 216
+test_636_A test_636_B 0.01 460.5
+test_637_A test_637_B 0.01 314
+test_638_A test_638_B 0.01 322
+test_639_A test_639_B 0.01 440.5
+test_640_A test_640_B 0.01 324
+test_641_A test_641_B 0.01 265
+test_642_A test_642_B 0.01 395.5
+test_643_A test_643_B 0.01 397
+test_644_A test_644_B 0.01 308
+test_645_A test_645_B 0.01 199
+test_646_A test_646_B 0.01 256.5
+test_647_A test_647_B 0.01 293
+test_648_A test_648_B 0.01 297
+test_649_A test_649_B 0.01 410.5
+test_650_A test_650_B 0.01 322
+test_651_A test_651_B 0.01 458
+test_652_A test_652_B 0.01 420.5
+test_653_A test_653_B 0.01 235
+test_654_A test_654_B 0.01 220
+test_655_A test_655_B 0.01 257
+test_656_A test_656_B 0.01 305
+test_657_A test_657_B 0.01 230.5
+test_658_A test_658_B 0.01 500
+test_659_A test_659_B 0.01 155
+test_660_A test_660_B 0.01 418
+test_661_A test_661_B 0.01 403.5
+test_662_A test_662_B 0.01 296
+test_663_A test_663_B 0.01 297.5
+test_664_A test_664_B 0.01 219
+test_665_A test_665_B 0.01 476.5
+test_666_A test_666_B 0.01 347
+test_667_A test_667_B 0.01 284
+test_668_A test_668_B 0.01 324.5
+test_669_A test_669_B 0.01 231
+test_670_A test_670_B 0.01 410
+test_671_A test_671_B 0.01 206
+test_672_A test_672_B 0.01 266
+test_673_A test_673_B 0.01 319.5
+test_674_A test_674_B 0.01 483
+test_675_A test_675_B 0.01 355.5
+test_676_A test_676_B 0.01 316.5
+test_677_A test_677_B 0.01 297
+test_678_A test_678_B 0.01 458
+test_679_A test_679_B 0.01 398.5
+test_680_A test_680_B 0.01 371.5
+test_681_A test_681_B 0.01 338
+test_682_A test_682_B 0.01 461
+test_683_A test_683_B 0.01 298.5
+test_684_A test_684_B 0.01 303.5
+test_685_A test_685_B 0.01 265
+test_686_A test_686_B 0.01 400.5
+test_687_A test_687_B 0.01 264
+test_688_A test_688_B 0.01 303
+test_689_A test_689_B 0.01 360
+test_690_A test_690_B 0.01 325
+test_691_A test_691_B 0.01 217
+test_692_A test_692_B 0.01 313
+test_693_A test_693_B 0.01 491
+test_694_A test_694_B 0.01 367.5
+test_695_A test_695_B 0.01 285
+test_696_A test_696_B 0.01 314
+test_697_A test_697_B 0.01 379
+test_698_A test_698_B 0.01 277.5
+test_699_A test_699_B 0.01 302
+test_700_A test_700_B 0.01 299
+test_701_A test_701_B 0.01 439.5
+test_702_A test_702_B 0.01 289
+test_703_A test_703_B 0.01 460.5
+test_704_A test_704_B 0.01 210
+test_705_A test_705_B 0.01 491
+test_706_A test_706_B 0.01 438.5
+test_707_A test_707_B 0.01 323
+test_708_A test_708_B 0.01 427
+test_709_A test_709_B 0.01 364
+test_710_A test_710_B 0.01 434
+test_711_A test_711_B 0.01 434
+test_712_A test_712_B 0.01 391
+test_713_A test_713_B 0.01 356
+test_714_A test_714_B 0.01 420
+test_715_A test_715_B 0.01 354
+test_716_A test_716_B 0.01 281
+test_717_A test_717_B 0.01 359.5
+test_718_A test_718_B 0.01 345
+test_719_A test_719_B 0.01 341.5
+test_720_A test_720_B 0.01 497.5
+test_721_A test_721_B 0.01 199
+test_722_A test_722_B 0.01 452
+test_723_A test_723_B 0.01 335.5
+test_724_A test_724_B 0.01 311
+test_725_A test_725_B 0.01 336
+test_726_A test_726_B 0.01 300
+test_727_A test_727_B 0.01 317
+test_728_A test_728_B 0.01 492
+test_729_A test_729_B 0.01 304
+test_730_A test_730_B 0.01 217
+test_731_A test_731_B 0.01 322
+test_732_A test_732_B 0.01 289
+test_733_A test_733_B 0.01 182
+test_734_A test_734_B 0.01 410.5
+test_735_A test_735_B 0.01 306
+test_736_A test_736_B 0.01 294
+test_737_A test_737_B 0.01 254
+test_738_A test_738_B 0.01 338.5
+test_739_A test_739_B 0.01 225
+test_740_A test_740_B 0.01 280
+test_741_A test_741_B 0.01 454
+test_742_A test_742_B 0.01 226
+test_743_A test_743_B 0.01 365
+test_744_A test_744_B 0.01 456
+test_745_A test_745_B 0.01 405
+test_746_A test_746_B 0.01 322
+test_747_A test_747_B 0.01 279
+test_748_A test_748_B 0.01 311.5
+test_749_A test_749_B 0.01 308
+test_750_A test_750_B 0.01 322
+test_751_A test_751_B 0.01 409
+test_752_A test_752_B 0.01 277
+test_753_A test_753_B 0.01 318
+test_754_A test_754_B 0.01 299.5
+test_755_A test_755_B 0.01 462.5
+test_756_A test_756_B 0.01 314
+test_757_A test_757_B 0.01 300
+test_758_A test_758_B 0.01 455
+test_759_A test_759_B 0.01 422.5
+test_760_A test_760_B 0.01 433.5
+test_761_A test_761_B 0.01 278
+test_762_A test_762_B 0.01 484.5
+test_763_A test_763_B 0.01 348
+test_764_A test_764_B 0.01 491
+test_765_A test_765_B 0.01 280
+test_766_A test_766_B 0.01 259
+test_767_A test_767_B 0.01 275.5
+test_768_A test_768_B 0.01 348
+test_769_A test_769_B 0.01 330
+test_770_A test_770_B 0.01 412
+test_771_A test_771_B 0.01 262
+test_772_A test_772_B 0.01 455
+test_773_A test_773_B 0.01 294
+test_774_A test_774_B 0.01 425
+test_775_A test_775_B 0.01 220.5
+test_776_A test_776_B 0.01 411.5
+test_777_A test_777_B 0.01 383
+test_778_A test_778_B 0.01 363
+test_779_A test_779_B 0.01 302
+test_780_A test_780_B 0.01 328
+test_781_A test_781_B 0.01 294
+test_782_A test_782_B 0.01 407.5
+test_783_A test_783_B 0.01 260.5
+test_784_A test_784_B 0.01 410
+test_785_A test_785_B 0.01 328
+test_786_A test_786_B 0.01 419.5
+test_787_A test_787_B 0.01 165
+test_788_A test_788_B 0.01 389
+test_789_A test_789_B 0.01 254
+test_790_A test_790_B 0.01 311
+test_791_A test_791_B 0.01 258
+test_792_A test_792_B 0.01 331
+test_793_A test_793_B 0.01 378
+test_794_A test_794_B 0.01 415
+test_795_A test_795_B 0.01 364
+test_796_A test_796_B 0.01 279
+test_797_A test_797_B 0.01 249
+test_798_A test_798_B 0.01 463
+test_799_A test_799_B 0.01 304
+test_800_A test_800_B 0.01 187
+test_801_A test_801_B 0.01 305.5
+test_802_A test_802_B 0.01 385
+test_803_A test_803_B 0.01 360.5
+test_804_A test_804_B 0.01 269
+test_805_A test_805_B 0.01 294
+test_806_A test_806_B 0.01 362
+test_807_A test_807_B 0.01 354
+test_808_A test_808_B 0.01 196
+test_809_A test_809_B 0.01 248
+test_810_A test_810_B 0.01 297.5
+test_811_A test_811_B 0.01 243
+test_812_A test_812_B 0.01 312
+test_813_A test_813_B 0.01 241
+test_814_A test_814_B 0.01 384
+test_815_A test_815_B 0.01 250
+test_816_A test_816_B 0.01 205
+test_817_A test_817_B 0.01 308
+test_818_A test_818_B 0.01 356
+test_819_A test_819_B 0.01 230
+test_820_A test_820_B 0.01 178
+test_821_A test_821_B 0.01 294
+test_822_A test_822_B 0.01 227
+test_823_A test_823_B 0.01 234
+test_824_A test_824_B 0.01 241
+test_825_A test_825_B 0.01 233
+test_826_A test_826_B 0.01 284
+test_827_A test_827_B 0.01 287
+test_828_A test_828_B 0.01 192
+test_829_A test_829_B 0.01 359
+test_830_A test_830_B 0.01 225
+test_831_A test_831_B 0.01 273
+test_832_A test_832_B 0.01 248
+test_833_A test_833_B 0.01 217
+test_834_A test_834_B 0.01 332
+test_835_A test_835_B 0.01 218
+test_836_A test_836_B 0.01 335
+test_837_A test_837_B 0.01 192
+test_838_A test_838_B 0.01 188
+test_839_A test_839_B 0.01 347
+test_840_A test_840_B 0.01 273
+test_841_A test_841_B 0.01 187
+test_842_A test_842_B 0.01 170
+test_843_A test_843_B 0.01 230
+test_844_A test_844_B 0.01 206.5
+test_845_A test_845_B 0.01 177
+test_846_A test_846_B 0.01 251
+test_847_A test_847_B 0.01 163
+test_848_A test_848_B 0.01 174
+test_849_A test_849_B 0.01 177
+test_850_A test_850_B 0.01 252
+test_851_A test_851_B 0.01 262
+test_852_A test_852_B 0.01 174
+test_853_A test_853_B 0.01 169
+test_854_A test_854_B 0.01 200
+test_855_A test_855_B 0.01 189
+test_856_A test_856_B 0.01 206.5
+test_857_A test_857_B 0.01 260
+test_858_A test_858_B 0.01 191
+test_859_A test_859_B 0.01 216
+test_860_A test_860_B 0.01 181.5
+test_861_A test_861_B 0.01 219
+test_862_A test_862_B 0.01 143
+test_863_A test_863_B 0.01 173
+test_864_A test_864_B 0.01 134
+test_865_A test_865_B 0.01 159
+test_866_A test_866_B 0.01 205
+test_867_A test_867_B 0.01 178
+test_868_A test_868_B 0.01 189.5
+test_869_A test_869_B 0.01 145
+test_870_A test_870_B 0.01 179
+test_871_A test_871_B 0.01 167
+test_872_A test_872_B 0.01 149
+test_873_A test_873_B 0.01 149
+test_874_A test_874_B 0.01 187
+test_875_A test_875_B 0.01 193
+test_876_A test_876_B 0.01 165
+test_877_A test_877_B 0.01 190
+test_878_A test_878_B 0.01 242
+test_879_A test_879_B 0.01 187
diff --git a/bottleneck/tests/data/test_list.txt.bak b/bottleneck/tests/data/test_list.txt.bak
new file mode 100644
index 0000000..71b89ed
--- /dev/null
+++ b/bottleneck/tests/data/test_list.txt.bak
@@ -0,0 +1,792 @@
+test_001_A test_001_B 0.01 1 -1 0 0 -1
+test_002_A test_002_B 0.01 0.2 0 0
+test_003_A test_003_B 0.01 2 1 1
+test_004_A test_004_B 0.01 inf -1 -1
+test_005_A test_005_B 0.01 4 5 5
+test_010_A test_010_B 0.01 1.32937
+test_011_A test_011_B 0.01 1.03125
+test_012_A test_012_B 0.01 0.56679
+test_013_A test_013_B 0.01 1.26332
+test_014_A test_014_B 0.01 0
+test_015_A test_015_B 0.01 0
+test_016_A test_016_B 0.01 0
+test_100_A test_100_B 0.01 1.5
+test_101_A test_101_B 0.01 1.5
+test_102_A test_102_B 0.01 4.5
+test_103_A test_103_B 0.01 3
+test_104_A test_104_B 0.01 3.5
+test_105_A test_105_B 0.01 3.5
+test_106_A test_106_B 0.01 3
+test_107_A test_107_B 0.01 5
+test_108_A test_108_B 0.01 5
+test_109_A test_109_B 0.01 3
+test_110_A test_110_B 0.01 4.5
+test_111_A test_111_B 0.01 4
+test_112_A test_112_B 0.01 4
+test_113_A test_113_B 0.01 2.5
+test_114_A test_114_B 0.01 4.5
+test_115_A test_115_B 0.01 4
+test_116_A test_116_B 0.01 4
+test_117_A test_117_B 0.01 2.5
+test_118_A test_118_B 0.01 3
+test_119_A test_119_B 0.01 5
+test_120_A test_120_B 0.01 2
+test_121_A test_121_B 0.01 3
+test_122_A test_122_B 0.01 1
+test_123_A test_123_B 0.01 4
+test_124_A test_124_B 0.01 4
+test_125_A test_125_B 0.01 4.5
+test_126_A test_126_B 0.01 3
+test_127_A test_127_B 0.01 2.5
+test_128_A test_128_B 0.01 2
+test_129_A test_129_B 0.01 3
+test_130_A test_130_B 0.01 5
+test_131_A test_131_B 0.01 5
+test_132_A test_132_B 0.01 2
+test_133_A test_133_B 0.01 3
+test_134_A test_134_B 0.01 3
+test_135_A test_135_B 0.01 4
+test_136_A test_136_B 0.01 2
+test_137_A test_137_B 0.01 3
+test_138_A test_138_B 0.01 2
+test_139_A test_139_B 0.01 2.5
+test_140_A test_140_B 0.01 2
+test_141_A test_141_B 0.01 4
+test_142_A test_142_B 0.01 3
+test_143_A test_143_B 0.01 4
+test_144_A test_144_B 0.01 3
+test_145_A test_145_B 0.01 4
+test_146_A test_146_B 0.01 3
+test_147_A test_147_B 0.01 4
+test_148_A test_148_B 0.01 3
+test_149_A test_149_B 0.01 4
+test_150_A test_150_B 0.01 3
+test_151_A test_151_B 0.01 4
+test_152_A test_152_B 0.01 3.5
+test_153_A test_153_B 0.01 4
+test_154_A test_154_B 0.01 3.5
+test_155_A test_155_B 0.01 3
+test_156_A test_156_B 0.01 3
+test_157_A test_157_B 0.01 4.5
+test_158_A test_158_B 0.01 3.5
+test_159_A test_159_B 0.01 1
+test_160_A test_160_B 0.01 4
+test_161_A test_161_B 0.01 4
+test_162_A test_162_B 0.01 3
+test_163_A test_163_B 0.01 5
+test_164_A test_164_B 0.01 4
+test_165_A test_165_B 0.01 4
+test_166_A test_166_B 0.01 4
+test_167_A test_167_B 0.01 4.5
+test_168_A test_168_B 0.01 4
+test_169_A test_169_B 0.01 3.5
+test_170_A test_170_B 0.01 4
+test_171_A test_171_B 0.01 2
+test_172_A test_172_B 0.01 3
+test_173_A test_173_B 0.01 4
+test_174_A test_174_B 0.01 3
+test_175_A test_175_B 0.01 5
+test_176_A test_176_B 0.01 4.5
+test_177_A test_177_B 0.01 4.5
+test_178_A test_178_B 0.01 4.5
+test_179_A test_179_B 0.01 4
+test_180_A test_180_B 0.01 5
+test_181_A test_181_B 0.01 4
+test_182_A test_182_B 0.01 4.5
+test_183_A test_183_B 0.01 5
+test_184_A test_184_B 0.01 4
+test_185_A test_185_B 0.01 4.5
+test_186_A test_186_B 0.01 3
+test_187_A test_187_B 0.01 4.5
+test_188_A test_188_B 0.01 3
+test_189_A test_189_B 0.01 2
+test_190_A test_190_B 0.01 3
+test_191_A test_191_B 0.01 3
+test_192_A test_192_B 0.01 3.5
+test_193_A test_193_B 0.01 4.5
+test_194_A test_194_B 0.01 3
+test_195_A test_195_B 0.01 3
+test_196_A test_196_B 0.01 3
+test_197_A test_197_B 0.01 3
+test_198_A test_198_B 0.01 5
+test_199_A test_199_B 0.01 3.5
+test_200_A test_200_B 0.01 3
+test_201_A test_201_B 0.01 5
+test_202_A test_202_B 0.01 3
+test_203_A test_203_B 0.01 4
+test_204_A test_204_B 0.01 2.5
+test_205_A test_205_B 0.01 4
+test_206_A test_206_B 0.01 3.5
+test_207_A test_207_B 0.01 3
+test_208_A test_208_B 0.01 4
+test_209_A test_209_B 0.01 3
+test_210_A test_210_B 0.01 5
+test_211_A test_211_B 0.01 3
+test_212_A test_212_B 0.01 3
+test_213_A test_213_B 0.01 3.5
+test_214_A test_214_B 0.01 4
+test_215_A test_215_B 0.01 3
+test_216_A test_216_B 0.01 3.5
+test_217_A test_217_B 0.01 4
+test_218_A test_218_B 0.01 4
+test_219_A test_219_B 0.01 4
+test_220_A test_220_B 0.01 3
+test_221_A test_221_B 0.01 4
+test_222_A test_222_B 0.01 4
+test_223_A test_223_B 0.01 4
+test_224_A test_224_B 0.01 3
+test_225_A test_225_B 0.01 3
+test_226_A test_226_B 0.01 4
+test_227_A test_227_B 0.01 4
+test_228_A test_228_B 0.01 4
+test_229_A test_229_B 0.01 3
+test_230_A test_230_B 0.01 3
+test_231_A test_231_B 0.01 4
+test_232_A test_232_B 0.01 4
+test_233_A test_233_B 0.01 2
+test_234_A test_234_B 0.01 3.5
+test_235_A test_235_B 0.01 4
+test_236_A test_236_B 0.01 3
+test_237_A test_237_B 0.01 3.5
+test_238_A test_238_B 0.01 4
+test_239_A test_239_B 0.01 3
+test_240_A test_240_B 0.01 3
+test_241_A test_241_B 0.01 5
+test_242_A test_242_B 0.01 4.5
+test_243_A test_243_B 0.01 4
+test_244_A test_244_B 0.01 3.5
+test_245_A test_245_B 0.01 5
+test_246_A test_246_B 0.01 2.5
+test_247_A test_247_B 0.01 3
+test_248_A test_248_B 0.01 4
+test_249_A test_249_B 0.01 2
+test_250_A test_250_B 0.01 5
+test_251_A test_251_B 0.01 4
+test_252_A test_252_B 0.01 4
+test_253_A test_253_B 0.01 4.5
+test_254_A test_254_B 0.01 4
+test_255_A test_255_B 0.01 3
+test_256_A test_256_B 0.01 4.5
+test_257_A test_257_B 0.01 4
+test_258_A test_258_B 0.01 5
+test_259_A test_259_B 0.01 4
+test_260_A test_260_B 0.01 4
+test_261_A test_261_B 0.01 2.5
+test_262_A test_262_B 0.01 2
+test_263_A test_263_B 0.01 4.5
+test_264_A test_264_B 0.01 3.5
+test_265_A test_265_B 0.01 4
+test_266_A test_266_B 0.01 3
+test_267_A test_267_B 0.01 5
+test_268_A test_268_B 0.01 4
+test_269_A test_269_B 0.01 4
+test_270_A test_270_B 0.01 3
+test_271_A test_271_B 0.01 4
+test_272_A test_272_B 0.01 4
+test_273_A test_273_B 0.01 2
+test_274_A test_274_B 0.01 3
+test_275_A test_275_B 0.01 3
+test_276_A test_276_B 0.01 4
+test_277_A test_277_B 0.01 5
+test_278_A test_278_B 0.01 4
+test_279_A test_279_B 0.01 4.5
+test_280_A test_280_B 0.01 3.5
+test_281_A test_281_B 0.01 2
+test_282_A test_282_B 0.01 3
+test_283_A test_283_B 0.01 3
+test_284_A test_284_B 0.01 3
+test_285_A test_285_B 0.01 3
+test_286_A test_286_B 0.01 3
+test_287_A test_287_B 0.01 3.5
+test_288_A test_288_B 0.01 3
+test_289_A test_289_B 0.01 2
+test_290_A test_290_B 0.01 4
+test_291_A test_291_B 0.01 3
+test_292_A test_292_B 0.01 4
+test_293_A test_293_B 0.01 2.5
+test_294_A test_294_B 0.01 4
+test_295_A test_295_B 0.01 3.5
+test_296_A test_296_B 0.01 3
+test_297_A test_297_B 0.01 3
+test_298_A test_298_B 0.01 4
+test_299_A test_299_B 0.01 4
+test_300_A test_300_B 0.01 3
+test_301_A test_301_B 0.01 2
+test_302_A test_302_B 0.01 2
+test_303_A test_303_B 0.01 3
+test_304_A test_304_B 0.01 3
+test_305_A test_305_B 0.01 3
+test_306_A test_306_B 0.01 3
+test_307_A test_307_B 0.01 2
+test_308_A test_308_B 0.01 3
+test_309_A test_309_B 0.01 2.5
+test_310_A test_310_B 0.01 4
+test_311_A test_311_B 0.01 3
+test_312_A test_312_B 0.01 3.5
+test_313_A test_313_B 0.01 3
+test_314_A test_314_B 0.01 2
+test_315_A test_315_B 0.01 3
+test_316_A test_316_B 0.01 4.5
+test_317_A test_317_B 0.01 3
+test_318_A test_318_B 0.01 3
+test_319_A test_319_B 0.01 3
+test_320_A test_320_B 0.01 4
+test_321_A test_321_B 0.01 2
+test_322_A test_322_B 0.01 3
+test_323_A test_323_B 0.01 3
+test_324_A test_324_B 0.01 2
+test_325_A test_325_B 0.01 3
+test_326_A test_326_B 0.01 2
+test_327_A test_327_B 0.01 3
+test_328_A test_328_B 0.01 3
+test_329_A test_329_B 0.01 4
+test_330_A test_330_B 0.01 3
+test_331_A test_331_B 0.01 3
+test_332_A test_332_B 0.01 2
+test_333_A test_333_B 0.01 2
+test_334_A test_334_B 0.01 3
+test_335_A test_335_B 0.01 2
+test_336_A test_336_B 0.01 3
+test_337_A test_337_B 0.01 2
+test_338_A test_338_B 0.01 2
+test_339_A test_339_B 0.01 2
+test_340_A test_340_B 0.01 1
+test_341_A test_341_B 0.01 2
+test_342_A test_342_B 0.01 2
+test_343_A test_343_B 0.01 2
+test_344_A test_344_B 0.01 2
+test_345_A test_345_B 0.01 2
+test_346_A test_346_B 0.01 2
+test_347_A test_347_B 0.01 2
+test_348_A test_348_B 0.01 2
+test_349_A test_349_B 0.01 2
+test_350_A test_350_B 0.01 2
+test_351_A test_351_B 0.01 2
+test_352_A test_352_B 0.01 2
+test_353_A test_353_B 0.01 2.5
+test_354_A test_354_B 0.01 2
+test_355_A test_355_B 0.01 2
+test_356_A test_356_B 0.01 2
+test_357_A test_357_B 0.01 2
+test_358_A test_358_B 0.01 2
+test_359_A test_359_B 0.01 2
+test_360_A test_360_B 0.01 32
+test_361_A test_361_B 0.01 8
+test_362_A test_362_B 0.01 29.5
+test_363_A test_363_B 0.01 41
+test_364_A test_364_B 0.01 41.5
+test_365_A test_365_B 0.01 27.5
+test_366_A test_366_B 0.01 46
+test_367_A test_367_B 0.01 37.5
+test_368_A test_368_B 0.01 27
+test_369_A test_369_B 0.01 42
+test_370_A test_370_B 0.01 45.5
+test_371_A test_371_B 0.01 34
+test_372_A test_372_B 0.01 19.5
+test_373_A test_373_B 0.01 24
+test_374_A test_374_B 0.01 10
+test_375_A test_375_B 0.01 17.5
+test_376_A test_376_B 0.01 28.5
+test_377_A test_377_B 0.01 40
+test_378_A test_378_B 0.01 40
+test_379_A test_379_B 0.01 24.5
+test_380_A test_380_B 0.01 36
+test_381_A test_381_B 0.01 38
+test_382_A test_382_B 0.01 48
+test_383_A test_383_B 0.01 32.5
+test_384_A test_384_B 0.01 44
+test_385_A test_385_B 0.01 44.5
+test_386_A test_386_B 0.01 11
+test_387_A test_387_B 0.01 47.5
+test_388_A test_388_B 0.01 28
+test_389_A test_389_B 0.01 32
+test_390_A test_390_B 0.01 24.5
+test_391_A test_391_B 0.01 47
+test_392_A test_392_B 0.01 28
+test_393_A test_393_B 0.01 16
+test_394_A test_394_B 0.01 44
+test_395_A test_395_B 0.01 38
+test_396_A test_396_B 0.01 47.5
+test_397_A test_397_B 0.01 35
+test_398_A test_398_B 0.01 33
+test_399_A test_399_B 0.01 33
+test_400_A test_400_B 0.01 31
+test_401_A test_401_B 0.01 48
+test_402_A test_402_B 0.01 37.5
+test_403_A test_403_B 0.01 40
+test_404_A test_404_B 0.01 47
+test_405_A test_405_B 0.01 23
+test_406_A test_406_B 0.01 40
+test_407_A test_407_B 0.01 46
+test_408_A test_408_B 0.01 39
+test_409_A test_409_B 0.01 26
+test_410_A test_410_B 0.01 28
+test_411_A test_411_B 0.01 27
+test_412_A test_412_B 0.01 33
+test_413_A test_413_B 0.01 36
+test_414_A test_414_B 0.01 42.5
+test_415_A test_415_B 0.01 40
+test_416_A test_416_B 0.01 37
+test_417_A test_417_B 0.01 43
+test_418_A test_418_B 0.01 16
+test_419_A test_419_B 0.01 34
+test_420_A test_420_B 0.01 42.5
+test_421_A test_421_B 0.01 38
+test_422_A test_422_B 0.01 30
+test_423_A test_423_B 0.01 44
+test_424_A test_424_B 0.01 46
+test_425_A test_425_B 0.01 38
+test_426_A test_426_B 0.01 35.5
+test_427_A test_427_B 0.01 29
+test_428_A test_428_B 0.01 43.5
+test_429_A test_429_B 0.01 34
+test_430_A test_430_B 0.01 48
+test_431_A test_431_B 0.01 41
+test_432_A test_432_B 0.01 35
+test_433_A test_433_B 0.01 32
+test_434_A test_434_B 0.01 36
+test_435_A test_435_B 0.01 43.5
+test_436_A test_436_B 0.01 32.5
+test_437_A test_437_B 0.01 40
+test_438_A test_438_B 0.01 34
+test_439_A test_439_B 0.01 31.5
+test_440_A test_440_B 0.01 26.5
+test_441_A test_441_B 0.01 49.5
+test_442_A test_442_B 0.01 30
+test_443_A test_443_B 0.01 29
+test_444_A test_444_B 0.01 29
+test_445_A test_445_B 0.01 48
+test_446_A test_446_B 0.01 35
+test_447_A test_447_B 0.01 43
+test_448_A test_448_B 0.01 19
+test_449_A test_449_B 0.01 34
+test_450_A test_450_B 0.01 44
+test_451_A test_451_B 0.01 36
+test_452_A test_452_B 0.01 32
+test_453_A test_453_B 0.01 49
+test_454_A test_454_B 0.01 48.5
+test_455_A test_455_B 0.01 46
+test_456_A test_456_B 0.01 33.5
+test_457_A test_457_B 0.01 49.5
+test_458_A test_458_B 0.01 38
+test_459_A test_459_B 0.01 21
+test_460_A test_460_B 0.01 40
+test_461_A test_461_B 0.01 32
+test_462_A test_462_B 0.01 37
+test_463_A test_463_B 0.01 23
+test_464_A test_464_B 0.01 19
+test_465_A test_465_B 0.01 29
+test_466_A test_466_B 0.01 38
+test_467_A test_467_B 0.01 29
+test_468_A test_468_B 0.01 45
+test_469_A test_469_B 0.01 27.5
+test_470_A test_470_B 0.01 43
+test_471_A test_471_B 0.01 24.5
+test_472_A test_472_B 0.01 42
+test_473_A test_473_B 0.01 36.5
+test_474_A test_474_B 0.01 46.5
+test_475_A test_475_B 0.01 18
+test_476_A test_476_B 0.01 29
+test_477_A test_477_B 0.01 44
+test_478_A test_478_B 0.01 49
+test_479_A test_479_B 0.01 33
+test_480_A test_480_B 0.01 43
+test_481_A test_481_B 0.01 42
+test_482_A test_482_B 0.01 31
+test_483_A test_483_B 0.01 37
+test_484_A test_484_B 0.01 25
+test_485_A test_485_B 0.01 33
+test_486_A test_486_B 0.01 35
+test_487_A test_487_B 0.01 39
+test_488_A test_488_B 0.01 26.5
+test_489_A test_489_B 0.01 39.5
+test_490_A test_490_B 0.01 26
+test_491_A test_491_B 0.01 45
+test_492_A test_492_B 0.01 21
+test_493_A test_493_B 0.01 37
+test_494_A test_494_B 0.01 50
+test_495_A test_495_B 0.01 41
+test_496_A test_496_B 0.01 34
+test_497_A test_497_B 0.01 35
+test_498_A test_498_B 0.01 34
+test_499_A test_499_B 0.01 30
+test_500_A test_500_B 0.01 39
+test_501_A test_501_B 0.01 36
+test_502_A test_502_B 0.01 36
+test_503_A test_503_B 0.01 49.5
+test_504_A test_504_B 0.01 40.5
+test_505_A test_505_B 0.01 29
+test_506_A test_506_B 0.01 33
+test_507_A test_507_B 0.01 38
+test_508_A test_508_B 0.01 21.5
+test_509_A test_509_B 0.01 27
+test_510_A test_510_B 0.01 43
+test_511_A test_511_B 0.01 34
+test_512_A test_512_B 0.01 25.5
+test_513_A test_513_B 0.01 19
+test_514_A test_514_B 0.01 28
+test_515_A test_515_B 0.01 41.5
+test_516_A test_516_B 0.01 46
+test_517_A test_517_B 0.01 34
+test_518_A test_518_B 0.01 33
+test_519_A test_519_B 0.01 37.5
+test_520_A test_520_B 0.01 37
+test_521_A test_521_B 0.01 42.5
+test_522_A test_522_B 0.01 44
+test_523_A test_523_B 0.01 36.5
+test_524_A test_524_B 0.01 40
+test_525_A test_525_B 0.01 36.5
+test_526_A test_526_B 0.01 24
+test_527_A test_527_B 0.01 34
+test_528_A test_528_B 0.01 23.5
+test_529_A test_529_B 0.01 30
+test_530_A test_530_B 0.01 50
+test_531_A test_531_B 0.01 33
+test_532_A test_532_B 0.01 36
+test_533_A test_533_B 0.01 24
+test_534_A test_534_B 0.01 46.5
+test_535_A test_535_B 0.01 39
+test_536_A test_536_B 0.01 26
+test_537_A test_537_B 0.01 30
+test_538_A test_538_B 0.01 27.5
+test_539_A test_539_B 0.01 26
+test_540_A test_540_B 0.01 23
+test_541_A test_541_B 0.01 26.5
+test_542_A test_542_B 0.01 40.5
+test_543_A test_543_B 0.01 41
+test_544_A test_544_B 0.01 46
+test_545_A test_545_B 0.01 33
+test_546_A test_546_B 0.01 38
+test_547_A test_547_B 0.01 33
+test_548_A test_548_B 0.01 28
+test_549_A test_549_B 0.01 29
+test_550_A test_550_B 0.01 33
+test_551_A test_551_B 0.01 20
+test_552_A test_552_B 0.01 27
+test_553_A test_553_B 0.01 21.5
+test_554_A test_554_B 0.01 28
+test_555_A test_555_B 0.01 31
+test_556_A test_556_B 0.01 31
+test_557_A test_557_B 0.01 30
+test_558_A test_558_B 0.01 29
+test_559_A test_559_B 0.01 30
+test_560_A test_560_B 0.01 21
+test_561_A test_561_B 0.01 37.5
+test_562_A test_562_B 0.01 40
+test_563_A test_563_B 0.01 25
+test_564_A test_564_B 0.01 22
+test_565_A test_565_B 0.01 24
+test_566_A test_566_B 0.01 39
+test_567_A test_567_B 0.01 27
+test_568_A test_568_B 0.01 30
+test_569_A test_569_B 0.01 35
+test_570_A test_570_B 0.01 29
+test_571_A test_571_B 0.01 27
+test_572_A test_572_B 0.01 23
+test_573_A test_573_B 0.01 34
+test_574_A test_574_B 0.01 26
+test_575_A test_575_B 0.01 28
+test_576_A test_576_B 0.01 22
+test_577_A test_577_B 0.01 29
+test_578_A test_578_B 0.01 24
+test_579_A test_579_B 0.01 22
+test_580_A test_580_B 0.01 31
+test_581_A test_581_B 0.01 39
+test_582_A test_582_B 0.01 21
+test_583_A test_583_B 0.01 32
+test_584_A test_584_B 0.01 22
+test_585_A test_585_B 0.01 26
+test_586_A test_586_B 0.01 20
+test_587_A test_587_B 0.01 28
+test_588_A test_588_B 0.01 22
+test_589_A test_589_B 0.01 20
+test_590_A test_590_B 0.01 17
+test_591_A test_591_B 0.01 24
+test_592_A test_592_B 0.01 27.5
+test_593_A test_593_B 0.01 31
+test_594_A test_594_B 0.01 18
+test_595_A test_595_B 0.01 18
+test_596_A test_596_B 0.01 32
+test_597_A test_597_B 0.01 17
+test_598_A test_598_B 0.01 19
+test_599_A test_599_B 0.01 23
+test_600_A test_600_B 0.01 16
+test_601_A test_601_B 0.01 13
+test_602_A test_602_B 0.01 25
+test_603_A test_603_B 0.01 17
+test_604_A test_604_B 0.01 18
+test_605_A test_605_B 0.01 20
+test_606_A test_606_B 0.01 16
+test_607_A test_607_B 0.01 19
+test_608_A test_608_B 0.01 22
+test_609_A test_609_B 0.01 18
+test_610_A test_610_B 0.01 22
+test_611_A test_611_B 0.01 18
+test_612_A test_612_B 0.01 21
+test_613_A test_613_B 0.01 23
+test_614_A test_614_B 0.01 14
+test_615_A test_615_B 0.01 21
+test_616_A test_616_B 0.01 20
+test_617_A test_617_B 0.01 17
+test_618_A test_618_B 0.01 15
+test_619_A test_619_B 0.01 18
+test_620_A test_620_B 0.01 346.5
+test_621_A test_621_B 0.01 414
+test_622_A test_622_B 0.01 321
+test_623_A test_623_B 0.01 428
+test_624_A test_624_B 0.01 137.5
+test_625_A test_625_B 0.01 272
+test_626_A test_626_B 0.01 257
+test_627_A test_627_B 0.01 261
+test_628_A test_628_B 0.01 480.5
+test_629_A test_629_B 0.01 378
+test_630_A test_630_B 0.01 153.5
+test_631_A test_631_B 0.01 199
+test_632_A test_632_B 0.01 457
+test_633_A test_633_B 0.01 358.5
+test_634_A test_634_B 0.01 357
+test_635_A test_635_B 0.01 216
+test_636_A test_636_B 0.01 460.5
+test_637_A test_637_B 0.01 314
+test_638_A test_638_B 0.01 322
+test_639_A test_639_B 0.01 440.5
+test_640_A test_640_B 0.01 324
+test_641_A test_641_B 0.01 265
+test_642_A test_642_B 0.01 395.5
+test_643_A test_643_B 0.01 397
+test_644_A test_644_B 0.01 308
+test_645_A test_645_B 0.01 199
+test_646_A test_646_B 0.01 256.5
+test_647_A test_647_B 0.01 293
+test_648_A test_648_B 0.01 297
+test_649_A test_649_B 0.01 410.5
+test_650_A test_650_B 0.01 322
+test_651_A test_651_B 0.01 458
+test_652_A test_652_B 0.01 420.5
+test_653_A test_653_B 0.01 235
+test_654_A test_654_B 0.01 220
+test_655_A test_655_B 0.01 257
+test_656_A test_656_B 0.01 305
+test_657_A test_657_B 0.01 230.5
+test_658_A test_658_B 0.01 500
+test_659_A test_659_B 0.01 155
+test_660_A test_660_B 0.01 418
+test_661_A test_661_B 0.01 403.5
+test_662_A test_662_B 0.01 296
+test_663_A test_663_B 0.01 297.5
+test_664_A test_664_B 0.01 219
+test_665_A test_665_B 0.01 476.5
+test_666_A test_666_B 0.01 347
+test_667_A test_667_B 0.01 284
+test_668_A test_668_B 0.01 324.5
+test_669_A test_669_B 0.01 231
+test_670_A test_670_B 0.01 410
+test_671_A test_671_B 0.01 206
+test_672_A test_672_B 0.01 266
+test_673_A test_673_B 0.01 319.5
+test_674_A test_674_B 0.01 483
+test_675_A test_675_B 0.01 355.5
+test_676_A test_676_B 0.01 316.5
+test_677_A test_677_B 0.01 297
+test_678_A test_678_B 0.01 458
+test_679_A test_679_B 0.01 398.5
+test_680_A test_680_B 0.01 371.5
+test_681_A test_681_B 0.01 338
+test_682_A test_682_B 0.01 461
+test_683_A test_683_B 0.01 298.5
+test_684_A test_684_B 0.01 303.5
+test_685_A test_685_B 0.01 265
+test_686_A test_686_B 0.01 400.5
+test_687_A test_687_B 0.01 264
+test_688_A test_688_B 0.01 303
+test_689_A test_689_B 0.01 360
+test_690_A test_690_B 0.01 325
+test_691_A test_691_B 0.01 217
+test_692_A test_692_B 0.01 313
+test_693_A test_693_B 0.01 491
+test_694_A test_694_B 0.01 367.5
+test_695_A test_695_B 0.01 285
+test_696_A test_696_B 0.01 314
+test_697_A test_697_B 0.01 379
+test_698_A test_698_B 0.01 277.5
+test_699_A test_699_B 0.01 302
+test_700_A test_700_B 0.01 299
+test_701_A test_701_B 0.01 439.5
+test_702_A test_702_B 0.01 289
+test_703_A test_703_B 0.01 460.5
+test_704_A test_704_B 0.01 210
+test_705_A test_705_B 0.01 491
+test_706_A test_706_B 0.01 438.5
+test_707_A test_707_B 0.01 323
+test_708_A test_708_B 0.01 427
+test_709_A test_709_B 0.01 364
+test_710_A test_710_B 0.01 434
+test_711_A test_711_B 0.01 434
+test_712_A test_712_B 0.01 391
+test_713_A test_713_B 0.01 356
+test_714_A test_714_B 0.01 420
+test_715_A test_715_B 0.01 354
+test_716_A test_716_B 0.01 281
+test_717_A test_717_B 0.01 359.5
+test_718_A test_718_B 0.01 345
+test_719_A test_719_B 0.01 341.5
+test_720_A test_720_B 0.01 497.5
+test_721_A test_721_B 0.01 199
+test_722_A test_722_B 0.01 452
+test_723_A test_723_B 0.01 335.5
+test_724_A test_724_B 0.01 311
+test_725_A test_725_B 0.01 336
+test_726_A test_726_B 0.01 300
+test_727_A test_727_B 0.01 317
+test_728_A test_728_B 0.01 492
+test_729_A test_729_B 0.01 304
+test_730_A test_730_B 0.01 217
+test_731_A test_731_B 0.01 322
+test_732_A test_732_B 0.01 289
+test_733_A test_733_B 0.01 182
+test_734_A test_734_B 0.01 410.5
+test_735_A test_735_B 0.01 306
+test_736_A test_736_B 0.01 294
+test_737_A test_737_B 0.01 254
+test_738_A test_738_B 0.01 338.5
+test_739_A test_739_B 0.01 225
+test_740_A test_740_B 0.01 280
+test_741_A test_741_B 0.01 454
+test_742_A test_742_B 0.01 226
+test_743_A test_743_B 0.01 365
+test_744_A test_744_B 0.01 456
+test_745_A test_745_B 0.01 405
+test_746_A test_746_B 0.01 322
+test_747_A test_747_B 0.01 279
+test_748_A test_748_B 0.01 311.5
+test_749_A test_749_B 0.01 308
+test_750_A test_750_B 0.01 322
+test_751_A test_751_B 0.01 409
+test_752_A test_752_B 0.01 277
+test_753_A test_753_B 0.01 318
+test_754_A test_754_B 0.01 299.5
+test_755_A test_755_B 0.01 462.5
+test_756_A test_756_B 0.01 314
+test_757_A test_757_B 0.01 300
+test_758_A test_758_B 0.01 455
+test_759_A test_759_B 0.01 422.5
+test_760_A test_760_B 0.01 433.5
+test_761_A test_761_B 0.01 278
+test_762_A test_762_B 0.01 484.5
+test_763_A test_763_B 0.01 348
+test_764_A test_764_B 0.01 491
+test_765_A test_765_B 0.01 280
+test_766_A test_766_B 0.01 259
+test_767_A test_767_B 0.01 275.5
+test_768_A test_768_B 0.01 348
+test_769_A test_769_B 0.01 330
+test_770_A test_770_B 0.01 412
+test_771_A test_771_B 0.01 262
+test_772_A test_772_B 0.01 455
+test_773_A test_773_B 0.01 294
+test_774_A test_774_B 0.01 425
+test_775_A test_775_B 0.01 220.5
+test_776_A test_776_B 0.01 411.5
+test_777_A test_777_B 0.01 383
+test_778_A test_778_B 0.01 363
+test_779_A test_779_B 0.01 302
+test_780_A test_780_B 0.01 328
+test_781_A test_781_B 0.01 294
+test_782_A test_782_B 0.01 407.5
+test_783_A test_783_B 0.01 260.5
+test_784_A test_784_B 0.01 410
+test_785_A test_785_B 0.01 328
+test_786_A test_786_B 0.01 419.5
+test_787_A test_787_B 0.01 165
+test_788_A test_788_B 0.01 389
+test_789_A test_789_B 0.01 254
+test_790_A test_790_B 0.01 311
+test_791_A test_791_B 0.01 258
+test_792_A test_792_B 0.01 331
+test_793_A test_793_B 0.01 378
+test_794_A test_794_B 0.01 415
+test_795_A test_795_B 0.01 364
+test_796_A test_796_B 0.01 279
+test_797_A test_797_B 0.01 249
+test_798_A test_798_B 0.01 463
+test_799_A test_799_B 0.01 304
+test_800_A test_800_B 0.01 187
+test_801_A test_801_B 0.01 305.5
+test_802_A test_802_B 0.01 385
+test_803_A test_803_B 0.01 360.5
+test_804_A test_804_B 0.01 269
+test_805_A test_805_B 0.01 294
+test_806_A test_806_B 0.01 362
+test_807_A test_807_B 0.01 354
+test_808_A test_808_B 0.01 196
+test_809_A test_809_B 0.01 248
+test_810_A test_810_B 0.01 297.5
+test_811_A test_811_B 0.01 243
+test_812_A test_812_B 0.01 312
+test_813_A test_813_B 0.01 241
+test_814_A test_814_B 0.01 384
+test_815_A test_815_B 0.01 250
+test_816_A test_816_B 0.01 205
+test_817_A test_817_B 0.01 308
+test_818_A test_818_B 0.01 356
+test_819_A test_819_B 0.01 230
+test_820_A test_820_B 0.01 178
+test_821_A test_821_B 0.01 294
+test_822_A test_822_B 0.01 227
+test_823_A test_823_B 0.01 234
+test_824_A test_824_B 0.01 241
+test_825_A test_825_B 0.01 233
+test_826_A test_826_B 0.01 284
+test_827_A test_827_B 0.01 287
+test_828_A test_828_B 0.01 192
+test_829_A test_829_B 0.01 359
+test_830_A test_830_B 0.01 225
+test_831_A test_831_B 0.01 273
+test_832_A test_832_B 0.01 248
+test_833_A test_833_B 0.01 217
+test_834_A test_834_B 0.01 332
+test_835_A test_835_B 0.01 218
+test_836_A test_836_B 0.01 335
+test_837_A test_837_B 0.01 192
+test_838_A test_838_B 0.01 188
+test_839_A test_839_B 0.01 347
+test_840_A test_840_B 0.01 273
+test_841_A test_841_B 0.01 187
+test_842_A test_842_B 0.01 170
+test_843_A test_843_B 0.01 230
+test_844_A test_844_B 0.01 206.5
+test_845_A test_845_B 0.01 177
+test_846_A test_846_B 0.01 251
+test_847_A test_847_B 0.01 163
+test_848_A test_848_B 0.01 174
+test_849_A test_849_B 0.01 177
+test_850_A test_850_B 0.01 252
+test_851_A test_851_B 0.01 262
+test_852_A test_852_B 0.01 174
+test_853_A test_853_B 0.01 169
+test_854_A test_854_B 0.01 200
+test_855_A test_855_B 0.01 189
+test_856_A test_856_B 0.01 206.5
+test_857_A test_857_B 0.01 260
+test_858_A test_858_B 0.01 191
+test_859_A test_859_B 0.01 216
+test_860_A test_860_B 0.01 181.5
+test_861_A test_861_B 0.01 219
+test_862_A test_862_B 0.01 143
+test_863_A test_863_B 0.01 173
+test_864_A test_864_B 0.01 134
+test_865_A test_865_B 0.01 159
+test_866_A test_866_B 0.01 205
+test_867_A test_867_B 0.01 178
+test_868_A test_868_B 0.01 189.5
+test_869_A test_869_B 0.01 145
+test_870_A test_870_B 0.01 179
+test_871_A test_871_B 0.01 167
+test_872_A test_872_B 0.01 149
+test_873_A test_873_B 0.01 149
+test_874_A test_874_B 0.01 187
+test_875_A test_875_B 0.01 193
+test_876_A test_876_B 0.01 165
+test_877_A test_877_B 0.01 190
+test_878_A test_878_B 0.01 242
+test_879_A test_879_B 0.01 187
diff --git a/bottleneck/tests/data/ws_tests/test_100_A b/bottleneck/tests/data/ws_tests/test_100_A
new file mode 100644
index 0000000..8d126f0
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_100_A
@@ -0,0 +1,100 @@
+7.50638 7.78005
+0.991758 2.12178
+5.18481 6.61702
+6.14703 7.08581
+4.09936 4.83024
+3.79915 4.51283
+3.17645 3.75321
+0.61305 0.998622
+0.445643 1.13781
+6.38205 6.53669
+5.96392 6.44093
+7.21047 7.26005
+0.6703 1.26593
+0.529933 1.7027
+7.92495 8.83023
+2.1382 2.71695
+3.79209 4.5197
+5.23354 5.82214
+-0.395097 2.18831
+3.22028 3.88648
+5.56262 5.79949
+8.39623 9.37185
+2.7452 3.84539
+9.5022 10.2414
+1.01374 1.40504
+3.2029 3.89559
+7.61236 8.28485
+6.4371 6.909
+4.45616 5.35067
+1.57802 1.77895
+6.5991 7.76339
+6.66729 6.71714
+6.11898 6.57121
+2.60663 4.36396
+-0.259613 1.17683
+7.72857 9.48862
+4.68398 5.51521
+4.87447 5.4233
+6.86301 6.88244
+4.17814 4.25886
+8.70558 9.72902
+4.40873 4.57389
+6.1824 7.05049
+7.97557 8.79739
+8.52591 8.6985
+5.15336 5.27796
+9.70144 9.77031
+0.561778 1.39045
+9.32553 10.2456
+7.01495 7.74521
+6.83355 7.28255
+1.96721 3.01504
+5.78411 7.59464
+5.64012 6.10721
+3.7249 5.17086
+4.33297 5.91657
+7.11793 7.2545
+5.109 6.76878
+3.02787 3.04077
+0.999365 2.05566
+8.81392 8.9086
+6.20106 6.78943
+6.7987 7.05794
+0.438805 0.449602
+8.71793 9.79853
+-0.150282 0.51997
+5.72257 5.93156
+5.71098 6.09535
+9.0378 9.45942
+0.534987 0.872885
+7.72276 8.57754
+9.26069 9.40289
+4.148 4.80519
+1.04579 3.18109
+0.259767 0.93215
+0.250608 0.511569
+4.88108 5.62239
+4.6731 5.3348
+7.84979 7.93545
+0.912521 1.48142
+4.82553 5.38108
+6.02179 7.61665
+3.85848 6.39418
+5.10754 6.02118
+1.71956 1.86238
+6.47336 6.74034
+-0.0371018 0.212738
+3.97259 4.15465
+2.17413 3.20188
+4.49098 6.09812
+6.62445 7.84196
+6.57541 7.432
+6.81052 9.6653
+3.67502 4.69734
+3.92378 4.14743
+5.93127 6.46154
+0.63424 0.705454
+7.60129 9.23263
+4.23064 4.74575
+0.397705 1.24458
diff --git a/bottleneck/tests/data/ws_tests/test_100_A.pd.dipha b/bottleneck/tests/data/ws_tests/test_100_A.pd.dipha
new file mode 100644
index 0000000..e94f5fe
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_100_A.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_100_B b/bottleneck/tests/data/ws_tests/test_100_B
new file mode 100644
index 0000000..852799d
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_100_B
@@ -0,0 +1,100 @@
+5.8232 6.36308
+2.16066 2.48668
+2.38754 4.91418
+4.77403 5.43982
+0.291412 1.11147
+3.77337 5.2686
+8.31344 9.05384
+0.734064 1.14844
+7.57606 7.8521
+3.16719 3.86953
+2.55072 2.64932
+9.51707 9.6071
+0.304643 2.41784
+2.79925 3.28234
+5.32901 7.7576
+5.19903 6.30449
+1.87819 2.99454
+8.92272 9.67105
+4.62414 5.05592
+4.0079 4.64148
+2.26369 3.44573
+2.69335 3.13426
+1.90706 2.42652
+2.68113 2.79133
+1.41065 1.56018
+6.55282 7.18725
+5.72986 6.37151
+7.26968 8.22623
+3.32643 3.73606
+3.77325 4.63115
+1.05457 1.83651
+8.6815 8.85251
+3.91285 4.17139
+0.380936 0.842109
+7.33227 7.69334
+8.45635 8.923
+4.1769 5.08373
+0.501374 2.23328
+-0.161782 1.28908
+3.44716 3.4662
+3.15394 4.30243
+8.71416 9.3781
+6.3034 8.62893
+6.53824 7.04611
+0.6386 1.35269
+0.862088 0.960371
+5.12963 5.20203
+1.58695 2.0452
+6.57698 6.63228
+3.87747 4.45669
+1.51273 3.25669
+-0.0992804 0.667302
+4.7489 4.80059
+0.0280559 1.90471
+6.7462 8.27612
+0.915652 1.30007
+2.79556 3.77404
+9.87989 10.0722
+9.39105 9.84229
+7.57235 9.37122
+5.09426 6.44266
+6.3994 6.72037
+5.73441 6.99341
+6.9079 7.88049
+4.2003 4.41933
+-1.72447 2.25877
+9.04907 9.64323
+4.40473 5.3593
+9.31201 9.96079
+7.28343 8.74163
+3.0172 6.23779
+8.08422 8.56069
+6.83038 6.99863
+2.32038 3.1289
+7.42302 8.26286
+6.66905 7.18496
+0.730748 1.61335
+4.00564 5.73993
+2.81231 3.67489
+2.33178 2.37845
+9.03302 9.68681
+0.567816 0.755485
+7.89783 8.7621
+0.177662 0.332833
+-0.181569 1.36821
+6.22158 6.55787
+4.67115 5.16995
+0.806432 0.820738
+7.69636 7.87402
+4.40933 4.54995
+9.1329 9.15037
+8.87416 9.04329
+1.14349 1.8993
+3.29756 4.7172
+6.67873 8.31364
+6.91238 7.1654
+0.483084 1.55006
+2.66058 3.86294
+5.93347 6.06085
+7.40514 9.05071
diff --git a/bottleneck/tests/data/ws_tests/test_100_B.pd.dipha b/bottleneck/tests/data/ws_tests/test_100_B.pd.dipha
new file mode 100644
index 0000000..25d6734
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_100_B.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_200_A b/bottleneck/tests/data/ws_tests/test_200_A
new file mode 100644
index 0000000..164b71d
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_200_A
@@ -0,0 +1,200 @@
+0.471299 1.89241
+2.82136 3.97846
+8.81923 9.20678
+1.42474 1.65425
+8.36963 9.16097
+-0.236476 0.692489
+7.57182 8.06148
+2.89878 3.21958
+7.1285 7.51707
+5.75496 7.09461
+6.00081 6.10914
+9.60869 9.64676
+7.42889 8.97174
+7.26061 8.55944
+2.41226 2.5146
+8.5616 9.44847
+7.4946 8.86962
+5.42244 6.98028
+9.62386 9.96039
+7.70591 9.92849
+1.34119 3.2048
+3.92169 5.15228
+8.82955 9.60318
+7.94213 9.39997
+2.6716 4.02057
+0.375206 0.497663
+1.94572 3.65599
+1.03366 1.46356
+8.91855 10.1838
+7.11087 8.64425
+2.63266 2.78706
+8.93611 10.2943
+8.51999 9.28356
+1.31436 3.13725
+1.92871 4.00178
+8.30503 8.45555
+2.58739 2.82076
+3.20419 5.29453
+7.4015 8.13225
+9.07991 9.74729
+0.822366 0.938371
+2.90508 4.29367
+4.32385 5.4787
+3.63054 4.6918
+8.52962 9.87004
+1.16994 2.39465
+2.61903 3.33772
+4.15505 4.52942
+8.7068 9.66579
+8.10373 9.31351
+0.7954 1.23001
+7.82253 8.69505
+4.59616 5.91996
+1.02032 1.93931
+6.98421 8.46017
+8.42263 11.3447
+2.63444 3.7158
+7.49059 9.1137
+-0.122109 1.41074
+8.29578 8.81161
+6.24793 6.32368
+4.07212 4.39695
+5.32453 7.457
+8.3892 9.82048
+4.35981 4.78063
+5.49932 6.08321
+1.0107 1.53369
+2.48759 2.94139
+4.24977 5.52034
+1.93104 3.35207
+-0.733247 1.22412
+-0.354283 2.36812
+6.34728 6.44213
+5.98172 7.8753
+5.47963 6.82986
+6.01986 6.6588
+4.62793 5.22134
+7.73923 8.29761
+8.85565 9.51494
+5.55307 6.15804
+6.30963 7.17248
+9.4775 10.2636
+7.45333 7.74006
+1.79317 2.33273
+7.73056 8.44999
+3.94172 5.02778
+8.36177 9.85172
+5.91765 8.12935
+7.95436 8.97583
+5.06238 5.37907
+4.56153 4.97175
+9.47572 9.65038
+9.54745 9.922
+7.82271 8.66299
+4.19056 4.75156
+4.15657 5.72352
+0.213845 0.312444
+2.30944 2.6806
+2.42391 3.41888
+6.00512 6.88274
+6.64546 7.61145
+-0.204229 2.78228
+-0.417104 0.667252
+8.18696 8.67785
+9.27818 9.67924
+-0.0174685 0.21355
+5.91137 6.39606
+9.49268 10.1457
+2.11362 4.36526
+6.51084 7.82167
+6.07066 6.44843
+-0.653518 1.08588
+7.46736 7.87137
+5.26045 7.92188
+6.4171 6.8133
+6.73709 7.70383
+3.46451 4.23679
+0.122365 0.809853
+7.98627 8.0505
+1.71192 2.63047
+1.20624 2.12087
+4.6812 5.51566
+2.62672 2.67648
+4.203 5.1052
+5.26482 6.5186
+3.68166 3.74701
+2.72011 3.98338
+3.41652 3.71477
+2.26211 2.90374
+0.930209 1.43211
+1.98603 3.36662
+4.55838 5.9933
+5.66292 6.59838
+3.12432 3.87457
+6.54384 8.38959
+0.205059 0.331022
+8.70617 9.34121
+7.02182 7.38679
+2.36908 2.84197
+9.13221 9.76563
+7.50113 9.49245
+8.15671 8.45093
+1.9517 2.20923
+3.23368 3.43695
+2.97273 4.10133
+7.36338 8.96733
+4.77525 5.18347
+9.47774 10.3537
+1.75218 1.97051
+5.42544 6.18939
+9.75801 10.0151
+6.31285 6.38327
+8.43389 8.721
+7.6108 7.81113
+8.72029 10.3153
+5.18655 7.1101
+7.96243 8.43151
+0.798103 0.860125
+1.1289 2.77549
+5.91084 6.03085
+4.95884 5.46913
+5.88125 6.49667
+7.9394 8.9545
+5.07492 5.55063
+5.92251 6.08548
+3.88602 5.41487
+1.40122 2.15276
+8.74244 8.83223
+4.75577 6.60338
+0.921272 1.44873
+3.77361 3.90348
+8.8999 9.8518
+3.11077 4.85674
+8.56185 10.6345
+8.76335 9.00169
+6.8734 8.60197
+4.54408 4.93892
+5.57849 6.31727
+7.95161 8.30843
+1.55798 2.4957
+3.86082 3.97131
+6.45433 7.17065
+0.96021 2.32897
+6.84576 6.89531
+8.59095 8.70199
+3.57754 4.26457
+5.27979 5.74385
+2.06602 2.90525
+3.0856 4.18179
+2.76214 3.9982
+2.11943 5.4285
+3.1197 3.24389
+0.495798 1.23632
+3.18253 3.99433
+7.02072 8.37949
+2.77905 3.42643
+1.57093 2.30655
+7.10979 7.14006
+6.20994 6.72092
+8.15136 8.33899
diff --git a/bottleneck/tests/data/ws_tests/test_200_B b/bottleneck/tests/data/ws_tests/test_200_B
new file mode 100644
index 0000000..761943d
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_200_B
@@ -0,0 +1,200 @@
+1.17434 1.46837
+2.58198 4.16589
+0.234041 0.968658
+1.52703 1.59579
+6.7103 7.44033
+3.19227 4.41539
+5.42556 5.57369
+3.45417 4.86089
+3.82256 4.1092
+7.82551 7.90784
+3.9384 4.71796
+5.60335 5.9054
+7.96663 9.8987
+6.30305 6.64853
+7.33246 10.5316
+0.623312 1.09008
+2.63041 2.64616
+5.36028 6.28956
+4.64202 5.91858
+7.55219 7.96304
+7.73736 9.18221
+1.67114 1.84851
+5.07514 5.12159
+7.03732 7.05228
+7.5006 7.59212
+0.244947 1.55875
+0.0170454 1.10485
+1.95394 3.53669
+5.66015 6.01949
+5.88211 7.64639
+7.46698 9.27085
+6.37429 7.10154
+4.54535 4.81932
+8.21203 9.35896
+4.89933 6.20802
+3.68683 4.17831
+0.477467 0.828394
+6.17871 6.77834
+9.77523 9.92676
+0.854808 2.38709
+7.93326 8.3553
+2.10917 2.27771
+4.07045 4.72793
+8.2016 8.8011
+2.9205 3.95746
+2.89806 4.39725
+5.5654 5.78669
+9.5219 9.98543
+7.08591 7.19588
+8.35359 9.57893
+9.81348 10.0345
+8.5994 9.71835
+5.43903 7.25234
+1.82768 2.92724
+4.44952 6.79754
+5.66747 7.34386
+5.88153 6.39253
+3.34008 4.22032
+2.46068 2.76051
+0.370778 2.61681
+6.02508 6.26809
+4.32654 4.93262
+7.41536 7.99616
+8.84229 9.87911
+3.8551 5.84353
+1.56832 2.34694
+6.96099 7.42028
+8.15753 8.72014
+9.23141 10.3815
+7.4484 7.80228
+0.473671 0.874895
+3.15689 3.50687
+3.58122 4.09945
+3.55022 3.74767
+4.42708 5.80211
+4.40956 4.68699
+3.80576 4.61856
+7.29965 8.28614
+7.40582 8.15308
+1.69789 1.77669
+1.66419 3.44308
+0.473997 0.872506
+7.83959 8.52898
+6.22416 6.36949
+-0.187159 0.871822
+0.232336 0.585965
+9.29905 9.44357
+1.4459 2.40589
+2.83008 3.19758
+1.15291 2.12112
+2.58686 3.33896
+6.79362 7.88068
+0.228178 1.48318
+5.60001 6.20258
+4.97803 7.10992
+1.70429 1.962
+2.72659 3.13886
+9.22714 9.25889
+3.84694 3.88778
+-0.282077 1.48155
+9.28756 9.58517
+4.34069 5.59751
+8.63909 8.76839
+8.86236 10.7642
+6.77597 8.41888
+7.30621 8.64164
+0.685607 1.22755
+2.91514 3.22638
+2.72098 3.66837
+8.17528 8.32638
+5.19632 5.7506
+7.34177 8.70639
+5.74082 6.35524
+5.95975 6.69284
+9.40187 10.4488
+2.92761 3.36735
+0.399531 3.13082
+4.83399 4.92635
+7.74539 8.56852
+1.76322 3.5086
+6.54479 6.72963
+7.64362 8.12404
+1.35542 1.45313
+0.214385 0.718085
+1.7006 3.21962
+5.91009 6.47862
+2.21093 2.34636
+5.96919 6.79365
+6.59951 8.22203
+1.54571 1.59397
+3.27012 3.79128
+0.32455 0.622995
+1.73926 2.78017
+9.81035 9.84077
+7.38441 7.85171
+8.90372 9.34186
+7.26323 8.41174
+5.7363 5.97348
+8.25473 10.1281
+2.3981 2.52096
+8.53783 9.63442
+8.51755 9.2735
+6.48614 6.773
+3.40182 3.65137
+2.1353 3.04852
+2.95397 3.73285
+6.98063 7.4963
+4.50189 5.26384
+0.21416 1.49363
+0.632196 1.36307
+6.57833 6.60481
+8.0634 9.33903
+2.79759 2.94462
+4.43747 4.58861
+6.48733 6.86569
+2.28008 3.47037
+6.87452 7.77431
+-0.156821 2.71557
+0.72595 1.78862
+1.97586 2.38196
+8.61839 9.1468
+4.55496 5.68986
+0.26923 1.15728
+9.63757 9.7236
+1.39497 1.96698
+4.8643 5.04172
+6.64675 7.66435
+2.56256 2.6015
+-0.381989 0.611211
+0.676336 1.26896
+8.95304 9.03243
+5.62058 6.07997
+3.36522 4.04276
+8.64868 10.5024
+4.75813 5.19834
+1.96608 2.05864
+9.01449 9.10397
+3.72786 4.51921
+5.6938 6.96584
+1.73499 2.9314
+2.73099 3.41409
+8.77171 9.07665
+4.63865 4.67649
+8.6698 9.30782
+-0.168259 2.09581
+9.29672 9.56
+0.372544 2.60567
+0.450487 1.32919
+6.95341 7.6399
+3.4403 5.24993
+5.53469 6.97831
+-0.79664 1.21306
+5.68831 6.14413
+8.85601 8.95444
+3.83309 5.211
+5.51573 6.5114
+3.64009 3.99648
+4.40759 4.99283
+1.85198 2.6457
+2.72645 3.74803
diff --git a/bottleneck/tests/data/ws_tests/test_5000_A b/bottleneck/tests/data/ws_tests/test_5000_A
new file mode 100644
index 0000000..094c6e0
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_5000_A
@@ -0,0 +1,5000 @@
+0.471299 1.89241
+2.82136 3.97846
+8.81923 9.20678
+1.42474 1.65425
+8.36963 9.16097
+-0.236476 0.692489
+7.57182 8.06148
+2.89878 3.21958
+7.1285 7.51707
+5.75496 7.09461
+6.00081 6.10914
+9.60869 9.64676
+7.42889 8.97174
+7.26061 8.55944
+2.41226 2.5146
+8.5616 9.44847
+7.4946 8.86962
+5.42244 6.98028
+9.62386 9.96039
+7.70591 9.92849
+1.34119 3.2048
+3.92169 5.15228
+8.82955 9.60318
+7.94213 9.39997
+2.6716 4.02057
+0.375206 0.497663
+1.94572 3.65599
+1.03366 1.46356
+8.91855 10.1838
+7.11087 8.64425
+2.63266 2.78706
+8.93611 10.2943
+8.51999 9.28356
+1.31436 3.13725
+1.92871 4.00178
+8.30503 8.45555
+2.58739 2.82076
+3.20419 5.29453
+7.4015 8.13225
+9.07991 9.74729
+0.822366 0.938371
+2.90508 4.29367
+4.32385 5.4787
+3.63054 4.6918
+8.52962 9.87004
+1.16994 2.39465
+2.61903 3.33772
+4.15505 4.52942
+8.7068 9.66579
+8.10373 9.31351
+0.7954 1.23001
+7.82253 8.69505
+4.59616 5.91996
+1.02032 1.93931
+6.98421 8.46017
+8.42263 11.3447
+2.63444 3.7158
+7.49059 9.1137
+-0.122109 1.41074
+8.29578 8.81161
+6.24793 6.32368
+4.07212 4.39695
+5.32453 7.457
+8.3892 9.82048
+4.35981 4.78063
+5.49932 6.08321
+1.0107 1.53369
+2.48759 2.94139
+4.24977 5.52034
+1.93104 3.35207
+-0.733247 1.22412
+-0.354283 2.36812
+6.34728 6.44213
+5.98172 7.8753
+5.47963 6.82986
+6.01986 6.6588
+4.62793 5.22134
+7.73923 8.29761
+8.85565 9.51494
+5.55307 6.15804
+6.30963 7.17248
+9.4775 10.2636
+7.45333 7.74006
+1.79317 2.33273
+7.73056 8.44999
+3.94172 5.02778
+8.36177 9.85172
+5.91765 8.12935
+7.95436 8.97583
+5.06238 5.37907
+4.56153 4.97175
+9.47572 9.65038
+9.54745 9.922
+7.82271 8.66299
+4.19056 4.75156
+4.15657 5.72352
+0.213845 0.312444
+2.30944 2.6806
+2.42391 3.41888
+6.00512 6.88274
+6.64546 7.61145
+-0.204229 2.78228
+-0.417104 0.667252
+8.18696 8.67785
+9.27818 9.67924
+-0.0174685 0.21355
+5.91137 6.39606
+9.49268 10.1457
+2.11362 4.36526
+6.51084 7.82167
+6.07066 6.44843
+-0.653518 1.08588
+7.46736 7.87137
+5.26045 7.92188
+6.4171 6.8133
+6.73709 7.70383
+3.46451 4.23679
+0.122365 0.809853
+7.98627 8.0505
+1.71192 2.63047
+1.20624 2.12087
+4.6812 5.51566
+2.62672 2.67648
+4.203 5.1052
+5.26482 6.5186
+3.68166 3.74701
+2.72011 3.98338
+3.41652 3.71477
+2.26211 2.90374
+0.930209 1.43211
+1.98603 3.36662
+4.55838 5.9933
+5.66292 6.59838
+3.12432 3.87457
+6.54384 8.38959
+0.205059 0.331022
+8.70617 9.34121
+7.02182 7.38679
+2.36908 2.84197
+9.13221 9.76563
+7.50113 9.49245
+8.15671 8.45093
+1.9517 2.20923
+3.23368 3.43695
+2.97273 4.10133
+7.36338 8.96733
+4.77525 5.18347
+9.47774 10.3537
+1.75218 1.97051
+5.42544 6.18939
+9.75801 10.0151
+6.31285 6.38327
+8.43389 8.721
+7.6108 7.81113
+8.72029 10.3153
+5.18655 7.1101
+7.96243 8.43151
+0.798103 0.860125
+1.1289 2.77549
+5.91084 6.03085
+4.95884 5.46913
+5.88125 6.49667
+7.9394 8.9545
+5.07492 5.55063
+5.92251 6.08548
+3.88602 5.41487
+1.40122 2.15276
+8.74244 8.83223
+4.75577 6.60338
+0.921272 1.44873
+3.77361 3.90348
+8.8999 9.8518
+3.11077 4.85674
+8.56185 10.6345
+8.76335 9.00169
+6.8734 8.60197
+4.54408 4.93892
+5.57849 6.31727
+7.95161 8.30843
+1.55798 2.4957
+3.86082 3.97131
+6.45433 7.17065
+0.96021 2.32897
+6.84576 6.89531
+8.59095 8.70199
+3.57754 4.26457
+5.27979 5.74385
+2.06602 2.90525
+3.0856 4.18179
+2.76214 3.9982
+2.11943 5.4285
+3.1197 3.24389
+0.495798 1.23632
+3.18253 3.99433
+7.02072 8.37949
+2.77905 3.42643
+1.57093 2.30655
+7.10979 7.14006
+6.20994 6.72092
+8.15136 8.33899
+0.903753 1.57921
+0.380744 1.88053
+1.3164 1.79885
+0.199366 0.576639
+5.53683 6.49433
+8.8705 9.14396
+3.1401 3.98761
+4.82675 6.69396
+7.28593 8.08916
+8.11312 9.92914
+3.25737 3.42109
+2.58413 4.57223
+2.65202 2.77196
+-0.31616 1.51568
+4.1621 5.29563
+4.49155 5.21037
+7.28481 7.31722
+9.70568 10.0406
+2.39057 2.85874
+2.30626 3.16244
+1.15896 2.09616
+5.91343 7.33024
+-0.172181 0.177363
+5.08934 6.10928
+7.15508 7.55315
+4.43036 4.68093
+6.00772 6.49566
+7.9247 8.43809
+1.57028 2.52328
+3.45458 4.43692
+3.18257 4.83824
+1.48243 1.91225
+2.59025 2.99596
+6.93059 8.34359
+4.53752 7.51216
+6.42857 6.51513
+5.5663 6.13877
+7.54367 7.56485
+9.01229 9.19913
+2.84158 3.23347
+0.42959 0.620618
+8.77033 9.33787
+8.06103 8.30989
+6.48425 7.83668
+4.66949 6.00205
+4.46683 4.66247
+8.96738 9.07714
+0.463093 0.514808
+7.72986 9.44537
+6.31391 6.8289
+0.883295 1.70946
+3.73278 3.98015
+6.73453 6.92514
+3.58434 4.43262
+0.236286 1.4601
+2.00505 2.38684
+3.845 4.20708
+1.18852 3.04911
+0.766784 1.00641
+7.38781 8.11216
+8.9396 9.27589
+0.369822 1.53322
+8.76527 9.23987
+0.663408 0.803445
+9.69209 10.1455
+9.73379 10.234
+3.47602 4.89968
+4.12754 5.45249
+7.31984 8.57369
+0.989101 1.47678
+5.57662 5.83292
+4.99092 6.85044
+4.35272 4.3683
+0.0517815 1.92227
+7.2694 7.80634
+1.35565 1.42783
+8.5638 8.91707
+1.74557 2.74123
+2.18226 2.19664
+-0.901334 1.32691
+0.866613 1.03788
+5.30895 6.31774
+7.70178 8.5675
+4.06894 4.16071
+2.59697 3.53162
+4.30201 5.34212
+4.08762 4.19091
+-0.516192 0.848397
+9.85911 10.1066
+0.472991 1.40069
+6.26012 7.0054
+0.707801 2.15445
+1.73825 1.87193
+0.206301 0.831746
+7.77872 7.92715
+4.94477 5.60361
+3.86216 5.16839
+1.35166 1.54482
+2.91721 3.56193
+4.57242 4.75913
+7.09303 8.29678
+8.18431 8.92151
+6.80303 10.87
+1.29208 1.72027
+1.22224 1.31693
+5.26756 6.26459
+2.55221 3.94397
+6.58902 6.78354
+7.85917 8.89791
+6.59279 7.63115
+4.45787 7.26828
+3.48759 5.33991
+2.13838 3.86589
+1.53368 3.57313
+1.41722 3.19336
+3.48388 4.11958
+1.53756 2.98451
+7.29083 8.22109
+1.2713 2.16915
+6.94685 7.31029
+6.2494 7.04676
+3.00376 3.02028
+1.25232 1.43301
+1.50413 2.25
+2.89098 4.77198
+4.50766 5.89294
+5.5403 6.07893
+-0.101858 0.409209
+3.87963 6.1053
+-0.19564 1.46589
+-0.342077 0.694623
+6.63875 7.42223
+7.89982 9.05857
+4.91121 5.48031
+5.90743 8.35815
+7.13881 8.21597
+4.11493 5.08147
+3.59673 3.77176
+8.08236 8.3237
+1.35842 1.48934
+5.42963 5.85906
+4.60778 4.9734
+-0.607198 0.91225
+5.40263 5.7017
+5.08624 5.63236
+7.34529 9.02233
+7.30013 8.12907
+6.56106 6.75585
+6.82576 7.25434
+2.96037 3.56454
+3.60283 4.09137
+6.35408 6.71888
+-0.688103 0.84579
+8.45128 8.69771
+6.31749 7.3294
+5.82223 6.04761
+1.72983 2.38205
+6.94974 7.76985
+9.681 10.0141
+8.65394 9.2456
+2.52904 3.39548
+6.66609 7.35785
+4.18963 4.5473
+3.58643 3.80513
+2.88796 3.82413
+0.992066 1.1477
+4.57942 5.15419
+3.02826 4.32268
+5.91565 6.82087
+4.13694 5.13393
+6.28717 6.53257
+1.3149 2.36944
+0.488974 0.981461
+4.32763 4.98272
+-0.420836 0.63619
+7.13406 7.31362
+0.367782 1.91138
+6.14763 6.16713
+0.837933 1.92794
+9.3781 10.0609
+3.22887 5.44584
+5.91554 6.65974
+5.68608 6.02435
+7.99715 8.55953
+5.37106 5.38574
+0.254544 0.374268
+0.184701 0.917061
+9.38005 9.54042
+6.86741 7.35628
+0.87398 1.69093
+7.75845 8.53773
+0.370425 1.35335
+0.699837 0.810893
+3.73223 4.32089
+3.81804 3.85752
+4.85936 5.10097
+2.70381 3.10519
+3.82523 5.27699
+9.13422 10.3317
+4.62775 4.77988
+7.91139 7.95504
+2.72614 4.79958
+0.863357 1.88643
+4.14155 5.02327
+2.49683 4.11585
+1.06741 1.11516
+6.20979 8.38443
+0.936362 2.46703
+6.58231 7.85063
+1.89469 2.31422
+8.70668 9.14006
+5.76486 6.1122
+3.15778 3.76679
+0.248282 2.19881
+1.25317 1.92694
+7.81837 9.53067
+-0.582906 0.818904
+8.34194 8.37845
+4.4913 5.10164
+3.86376 5.5453
+6.94054 7.68699
+2.07462 2.5811
+0.518698 2.1529
+3.51773 4.60946
+8.39915 8.98446
+1.63685 2.19755
+6.60737 9.05917
+2.06667 3.23994
+3.18822 3.31219
+2.44332 3.22088
+4.755 4.87118
+4.34245 4.91565
+4.64562 4.8104
+2.73282 3.35646
+9.48057 9.86441
+0.640899 1.03356
+0.789475 0.925731
+1.4247 1.58347
+1.47747 2.25408
+8.8612 9.81597
+8.44147 10.6885
+9.07046 10.0877
+0.350125 1.15765
+4.45375 5.73964
+4.06526 4.26457
+7.50776 8.23491
+1.55452 1.63786
+2.8399 4.52559
+1.34319 1.47951
+5.21572 5.65702
+5.85695 6.75574
+8.21826 10.657
+-0.0479956 1.79162
+1.72905 1.78113
+3.35685 4.03797
+3.7123 5.82296
+8.56751 10.2992
+4.07987 4.25273
+5.8347 6.07253
+3.25283 3.99065
+9.31995 10.3647
+0.649025 1.14496
+1.06966 2.04182
+7.59831 7.85826
+3.35263 3.84374
+4.91371 5.10148
+8.0875 9.23421
+3.00484 5.14282
+8.60448 9.09442
+5.61429 6.24037
+3.4729 4.17907
+7.18702 7.26274
+0.729966 0.928899
+2.27264 2.81241
+2.67248 3.91661
+3.98443 4.64406
+5.50463 6.92435
+-0.257961 0.905736
+5.71363 6.67387
+4.12643 4.66467
+3.97623 4.64917
+9.71227 9.8243
+8.66674 8.97634
+7.94673 8.73904
+7.45228 8.14466
+3.78405 4.81189
+4.05505 5.00011
+2.84957 3.15451
+6.93785 7.58172
+1.85006 1.96814
+6.82256 7.00166
+2.42727 2.68161
+8.06129 8.76308
+1.53758 3.67482
+2.5057 4.18495
+7.09618 7.79664
+1.12843 1.46228
+1.61447 2.2668
+5.58639 5.70776
+8.15398 8.34959
+2.49733 2.57643
+5.18817 5.32462
+5.62963 5.86377
+1.95215 2.26641
+7.22129 7.23255
+5.99833 6.18639
+6.20875 7.13868
+6.814 7.6597
+7.41314 9.49798
+5.48819 6.31634
+4.81318 5.08156
+9.15434 9.42787
+4.83201 5.43295
+1.44477 2.6455
+8.8907 10.4727
+3.19487 3.21255
+1.47291 3.13113
+4.14796 5.10058
+5.85016 8.41212
+7.58183 8.53659
+9.5978 10.2877
+1.5954 2.58394
+2.65561 4.0975
+-0.157024 0.16627
+7.04379 7.75368
+2.39896 2.7728
+2.42376 3.58085
+0.158653 0.857045
+7.82101 9.01833
+6.80499 7.35261
+6.62833 6.66255
+4.90229 5.45681
+8.50205 8.69236
+2.01845 2.06924
+8.2503 9.04222
+4.58265 5.52758
+8.6176 9.74887
+1.28468 1.77019
+5.40424 6.20705
+0.943905 1.98023
+4.2702 4.41287
+3.89454 4.4814
+0.585132 1.56351
+9.45354 10.5374
+3.7501 5.07553
+7.53248 8.14004
+4.60026 4.78921
+1.61073 4.22368
+6.22591 7.40966
+0.57866 1.0522
+5.877 6.55882
+3.54573 3.7731
+7.64294 7.66103
+8.2399 9.14032
+0.307808 0.571367
+7.89791 9.25734
+5.2852 5.84332
+0.45713 2.42223
+7.73426 8.48158
+8.0058 9.46405
+8.03189 8.41868
+1.54624 1.98914
+7.24167 7.27699
+8.61226 8.83199
+5.38365 6.52599
+0.827018 1.51428
+7.19285 7.48372
+-0.0969552 2.16007
+4.08084 6.32563
+9.16026 10.2604
+0.206147 0.717435
+4.00643 4.8093
+2.16139 3.14759
+1.73359 3.13485
+9.1103 9.36052
+7.05621 7.43901
+4.83509 6.07581
+5.67164 7.89488
+7.93353 8.18454
+2.59566 3.1842
+3.62521 4.95121
+3.0297 3.18649
+1.08515 2.69289
+3.77063 5.7789
+0.106035 1.27409
+0.601099 2.13481
+6.98837 7.58833
+9.22955 9.79149
+1.6398 1.78726
+2.30423 3.34814
+2.3912 2.81842
+4.71724 6.16966
+5.13553 5.5016
+5.34117 5.45075
+9.32776 10.0676
+4.54244 5.29058
+4.01337 5.73188
+8.17427 8.39652
+1.96122 2.6921
+0.594267 1.00176
+-0.136973 0.977133
+6.41362 6.78056
+1.68388 2.39891
+9.50795 10.2315
+-0.262703 1.15557
+8.72229 9.683
+5.41821 5.67519
+4.93514 7.15867
+4.07046 4.26702
+-0.00866106 0.252353
+8.65877 10.1527
+2.10958 3.40353
+2.94947 3.43201
+6.32014 7.06279
+2.55034 2.89646
+3.87777 5.68044
+2.05325 3.00968
+5.11855 6.55784
+8.99618 9.22608
+3.36303 3.84902
+2.6234 3.70832
+7.35189 8.30856
+6.43777 7.28495
+5.33954 5.48055
+0.15999 0.391114
+3.4492 5.07088
+2.38503 2.42742
+3.88912 4.93246
+2.76303 4.54991
+6.56261 7.60381
+3.64198 3.72471
+1.70542 1.78806
+9.71115 9.88315
+0.471586 1.82377
+9.27611 10.5725
+0.486889 0.851587
+4.39234 5.10637
+9.54209 9.8955
+6.99602 7.42461
+2.98797 3.74623
+5.89424 6.4498
+9.63845 9.86333
+4.39828 5.18646
+2.30118 3.5758
+8.68128 9.56011
+9.00505 10.4304
+-0.22184 0.233296
+6.48492 7.60283
+1.54156 2.60693
+4.06808 6.39369
+5.52361 6.26241
+-0.698727 0.745524
+2.30742 2.41924
+0.655833 1.65752
+6.94733 7.81866
+7.83136 9.10651
+6.45284 7.1931
+6.09683 6.66159
+9.03299 9.4163
+1.86392 3.26189
+0.54863 2.07194
+0.364026 1.38376
+0.706954 1.0736
+-0.111015 0.584367
+1.54265 2.1413
+0.501172 0.57928
+2.09411 2.28902
+1.89894 4.09104
+8.72895 8.87045
+5.27709 5.72545
+0.164581 1.64188
+8.39203 8.73608
+8.21523 8.45002
+9.62006 10.1665
+4.79076 6.26442
+3.44189 3.68669
+8.93789 9.38343
+7.07036 7.64194
+8.34396 9.56445
+8.29992 8.64954
+5.82566 7.83287
+2.43008 3.4476
+1.81121 2.12203
+4.36108 4.3842
+6.28756 6.95939
+3.8698 5.79519
+0.644581 0.699162
+9.71982 10.2422
+4.86545 5.00544
+8.3808 9.29356
+1.34495 1.40972
+1.03641 2.01838
+8.55609 9.99958
+1.40813 3.46097
+3.20928 4.08838
+8.24345 9.11587
+1.27604 2.03462
+8.28298 8.46252
+2.20644 3.19585
+1.91396 2.30108
+4.2553 5.66006
+7.34925 8.38275
+6.28319 7.22199
+8.42171 9.62596
+1.12059 1.18262
+1.37555 1.84196
+4.39663 4.93639
+9.28044 9.58437
+5.47407 6.88593
+8.36529 8.49813
+9.40208 10.5922
+-0.451389 1.92404
+2.89431 3.19453
+6.51433 8.02158
+5.52163 6.06786
+7.63525 9.86457
+4.13898 5.05845
+0.136662 0.503748
+6.13492 6.74997
+8.37416 9.18971
+8.64164 8.82663
+0.941173 1.16158
+6.9073 8.26916
+8.37278 8.44326
+8.8951 9.20427
+8.40149 9.17577
+3.60361 4.57183
+8.67263 10.1127
+5.89716 6.45412
+1.97285 2.35593
+7.22973 8.13467
+9.55645 9.92529
+0.261578 0.836274
+9.04414 9.45485
+6.18043 6.54229
+8.88579 9.54087
+1.82613 2.93849
+5.7599 5.96366
+5.23105 5.5541
+0.425229 1.44436
+0.32065 2.60892
+7.83655 9.48786
+2.3168 3.45972
+2.35466 3.23342
+8.24494 8.27258
+7.32678 7.74264
+8.37275 10.0741
+4.17337 4.98348
+-0.162009 0.724431
+9.49757 9.76377
+8.69435 9.08089
+4.13841 4.7514
+7.26358 7.55514
+6.91912 6.93
+6.7883 7.18296
+-0.614315 1.1857
+6.05907 7.33557
+4.86704 4.87705
+8.50012 9.14836
+1.83683 3.09895
+6.16389 8.39248
+3.03556 4.41004
+4.72416 5.05782
+1.98183 3.19183
+2.77103 5.71501
+4.90002 4.9817
+0.269258 0.725628
+5.59551 7.05038
+2.95416 3.09633
+2.17662 3.18385
+6.67536 7.56762
+7.31678 7.39321
+3.84158 3.85359
+4.38203 5.10149
+0.816784 1.09918
+0.70131 0.739502
+0.276631 2.32633
+9.15839 9.49433
+0.721295 1.97673
+2.63875 2.75437
+5.00344 5.5645
+2.24555 2.81234
+7.74465 9.07646
+2.35244 4.90632
+0.812093 0.954419
+3.97904 5.2071
+4.19177 4.83646
+0.853012 1.331
+2.64112 3.25613
+0.0894716 1.61954
+3.39617 3.40859
+1.56906 2.28518
+2.37258 4.36515
+1.60997 1.7561
+5.15275 5.33281
+6.47824 7.47529
+2.51145 3.29949
+2.71094 2.77785
+8.84653 9.48398
+1.3246 1.66664
+7.43718 7.5546
+3.68985 4.24649
+4.50553 4.51669
+4.15617 4.54887
+8.55319 10.2136
+2.1448 3.55805
+4.64594 4.71505
+1.71763 1.99977
+4.98066 5.46709
+7.7779 8.36497
+-0.0604997 0.301294
+5.11873 7.32867
+4.94567 5.5986
+5.32645 6.26835
+2.5768 3.13511
+3.31604 3.87555
+1.60834 2.68762
+3.30552 3.85211
+4.26741 4.98636
+0.820475 1.18854
+7.91501 10.7203
+5.17391 5.30351
+4.00452 5.75141
+2.37722 3.4602
+2.2373 2.94837
+1.62462 3.48264
+7.98507 9.2566
+5.32504 5.56388
+0.760614 0.7802
+0.855659 1.01522
+3.11231 4.43223
+5.62821 6.21564
+4.96845 5.35921
+8.10559 9.11106
+1.02533 1.13103
+6.99976 7.0788
+1.87628 2.58801
+1.11023 2.24655
+5.23343 5.45086
+0.95875 2.25343
+7.45917 8.23614
+2.72245 3.04663
+8.66816 8.70698
+5.55734 7.12262
+1.01935 1.88271
+0.804417 1.76187
+7.82703 8.78426
+4.77321 6.15199
+2.91503 3.69352
+0.776735 1.08883
+5.19981 5.46442
+9.06483 10.4008
+7.72082 8.26398
+2.9854 3.26573
+0.584028 2.60443
+0.700994 1.10379
+5.47612 5.94502
+-0.318442 0.986786
+5.0704 5.08055
+3.83732 4.4826
+5.60843 6.59005
+8.81432 9.7851
+6.28792 6.65284
+1.16812 2.27701
+7.15234 9.66795
+9.02188 9.15339
+1.76112 2.04839
+7.49419 7.6204
+5.1765 5.497
+1.45855 1.94969
+1.35003 1.55822
+2.50453 2.86815
+7.10451 8.51352
+3.87727 4.1124
+1.84876 2.79351
+3.01661 4.05396
+-0.16814 0.366484
+-0.538895 0.608786
+7.59933 9.00744
+0.938648 2.38471
+5.76934 6.16572
+8.20416 8.62505
+8.64542 8.7264
+2.75784 2.7828
+0.794451 1.97817
+9.21331 10.5156
+8.46671 8.80572
+3.94814 5.16845
+6.73654 6.97397
+4.05301 4.93008
+6.37833 6.77985
+7.21161 8.15994
+3.74993 4.61029
+-0.127938 1.09853
+2.82957 4.28816
+6.50564 6.59445
+8.37926 8.48332
+0.757443 1.74585
+0.232438 0.972293
+6.99187 8.7098
+7.20368 8.44301
+4.4801 6.07501
+4.34015 6.1495
+2.19394 3.22334
+7.29817 8.41021
+1.16627 2.68901
+4.62423 5.08039
+0.955655 2.22882
+1.45862 3.07065
+1.69815 2.56291
+4.01179 4.36587
+7.135 7.75829
+6.6823 7.27765
+5.44745 5.67195
+4.94594 5.42067
+0.267772 0.301939
+0.676432 1.6296
+1.37335 1.91645
+1.89051 2.38631
+4.84386 6.30539
+8.95613 10.944
+2.18119 2.41821
+5.74901 6.16952
+7.5431 7.88071
+9.05278 9.8128
+0.201334 1.65323
+2.82787 3.82083
+3.07073 3.08475
+8.99671 10.1766
+5.43261 6.12137
+4.83693 4.86848
+6.31804 7.21544
+2.34491 3.2562
+6.05941 6.53725
+-0.483381 1.17347
+5.53777 5.72651
+3.28875 3.47472
+3.94609 4.9418
+7.45585 8.6871
+1.50066 2.57215
+8.10112 8.67954
+6.24737 6.42635
+0.64413 1.05759
+7.1741 8.21476
+0.502722 1.77462
+0.783663 1.74174
+9.52704 9.9109
+-0.473873 2.01013
+7.07946 7.11474
+0.857335 1.6501
+4.00225 4.84453
+5.40598 6.30573
+8.18802 8.30067
+9.00412 10.9588
+9.8362 10.1517
+7.62735 8.37572
+3.41477 4.63099
+2.51254 2.81559
+6.36702 6.56061
+5.11842 5.35515
+5.21873 5.73296
+5.73528 7.77276
+3.64993 4.66826
+7.12664 8.46553
+8.7257 9.16851
+1.27615 2.20376
+7.46188 8.20752
+2.64939 2.66373
+4.94147 6.0509
+6.3805 7.48841
+6.25197 7.12327
+0.0885331 1.2682
+4.97356 6.58488
+4.11917 4.27267
+9.08793 9.70385
+0.897277 1.31702
+6.87538 8.25544
+1.55565 1.59492
+2.62483 3.54274
+1.49631 2.92263
+9.45305 9.97728
+6.24087 6.4577
+3.94636 5.13669
+-0.000956745 1.08235
+1.46134 1.83767
+9.18517 10.6601
+-0.740186 1.81269
+5.81977 6.15818
+7.0529 7.99421
+6.17753 7.49749
+8.63091 9.04205
+9.65219 10.1558
+3.12839 4.99211
+2.97262 4.07384
+4.28605 4.33171
+4.15906 5.6805
+1.35165 1.50732
+0.524207 2.12307
+5.32468 7.01472
+3.16982 4.87893
+6.88786 8.34191
+3.81703 5.22335
+3.86772 4.37359
+8.19386 10.0705
+1.73155 3.16695
+4.31685 4.62261
+9.40618 9.89612
+4.41215 5.19659
+2.35595 2.63543
+7.88481 8.14203
+7.17062 10.3534
+9.41379 10.389
+7.99867 9.01239
+3.31382 4.04915
+5.39222 6.07657
+8.5187 8.65976
+9.30132 10.6131
+7.17351 7.93596
+4.80134 6.72724
+3.59756 4.65182
+1.08248 1.17479
+1.03124 1.06871
+6.43154 6.95098
+-0.102199 0.59801
+4.94795 5.18081
+6.39126 7.30258
+1.52738 2.04271
+1.80373 2.33093
+2.72251 3.01677
+0.296722 1.10844
+6.39104 6.51567
+8.70965 8.78714
+2.07858 4.41695
+1.91027 2.9718
+1.42944 2.01864
+1.96347 2.73397
+4.0701 4.22456
+4.02859 4.05107
+7.10977 7.98092
+8.21148 9.54287
+6.59231 7.65109
+0.144191 0.830665
+2.0192 2.23704
+8.03482 8.39591
+8.90473 9.98543
+2.18284 2.70166
+3.05569 3.54238
+8.35319 9.39539
+2.00803 2.42866
+2.35282 3.13763
+2.20155 2.79377
+1.76531 2.94892
+7.52749 7.72567
+3.02266 3.24778
+4.01741 4.22521
+9.75263 9.91571
+6.45502 6.67838
+2.24912 3.47262
+1.84372 2.26517
+4.09559 5.71188
+1.43811 2.33732
+3.89171 4.16905
+3.01506 3.9725
+0.0273168 1.51766
+5.04118 5.80507
+3.08517 4.17316
+8.81637 8.8332
+8.74055 9.50143
+2.36904 2.69008
+6.39733 6.44221
+8.53272 9.51114
+9.48423 9.55002
+8.65645 9.04872
+6.66352 7.48009
+5.64389 7.88656
+5.75301 6.6759
+3.28645 4.22757
+4.99482 5.82988
+3.00004 4.0273
+1.45249 1.56662
+4.96263 5.32195
+7.91351 8.1437
+1.02034 1.56249
+0.71376 1.73319
+0.709968 1.44651
+9.01414 9.54799
+4.02116 4.68005
+7.10903 7.27075
+7.21322 8.71031
+1.6644 2.27186
+3.71304 4.68764
+9.66257 10.1452
+5.34477 5.46136
+9.27722 10.583
+3.82328 4.83316
+4.77019 5.07928
+9.07112 9.23836
+6.99091 7.25634
+2.11871 2.3054
+7.88242 7.98572
+0.570809 0.714073
+8.51532 9.49151
+0.329247 2.48897
+4.78202 5.36476
+1.47969 2.78867
+6.75011 7.36769
+2.31162 2.39533
+3.50434 4.48026
+5.84603 6.28861
+7.5337 7.62538
+1.09955 2.85741
+6.09915 7.20381
+0.933825 2.37925
+0.576363 2.0182
+3.12126 3.22507
+2.85313 3.02656
+3.25724 3.92077
+5.48575 6.58011
+1.02824 1.65415
+8.68703 9.06219
+3.28389 3.86349
+5.80264 6.12775
+7.11846 7.47444
+1.29638 3.38601
+6.37908 7.05986
+-0.592438 0.854361
+0.39233 1.17768
+2.1497 3.94423
+2.42336 2.43441
+6.94806 8.30626
+0.79865 1.4173
+1.41455 1.43684
+0.240074 1.16712
+4.18593 5.9929
+6.161 6.564
+0.726091 1.90706
+0.375606 0.694866
+4.09349 4.26452
+2.01652 2.68038
+8.99301 9.90549
+8.93909 9.17673
+1.10427 2.01247
+9.12668 9.15282
+1.08098 1.55374
+0.377836 0.414809
+7.28611 8.86318
+8.3542 8.53251
+3.86353 4.12875
+6.7631 7.40068
+4.61679 4.78182
+2.12935 3.45492
+3.68233 4.0457
+6.68131 8.22111
+8.79197 8.80474
+1.8915 2.26287
+0.387586 3.073
+6.46798 7.57381
+7.79742 9.34526
+-1.21538 1.67303
+2.07845 2.66028
+3.14148 4.46647
+1.66789 2.73375
+8.49821 10.0574
+8.42537 8.89906
+0.618349 2.72887
+6.8229 7.54501
+6.99343 7.35322
+7.34223 8.68781
+3.18834 3.98274
+8.86908 10.2535
+3.39839 3.76171
+0.188168 0.392276
+1.68187 3.53401
+6.50423 6.71714
+7.61191 8.89715
+1.68463 2.09275
+5.94627 7.6003
+2.15865 3.24126
+7.93639 8.53826
+2.99626 3.43273
+7.71028 8.41172
+3.19472 4.60878
+8.36123 8.92549
+8.92975 9.02783
+2.87187 3.49672
+6.76949 7.71139
+8.09121 9.31151
+6.84199 7.44009
+0.730655 0.800873
+7.5208 7.54109
+6.75992 7.55017
+6.09818 6.17399
+0.639209 1.27283
+3.01917 3.22327
+1.69181 2.60614
+9.49245 9.5842
+-0.418034 1.08035
+5.77705 6.4705
+6.79362 8.51993
+9.73155 9.81609
+3.71503 3.92022
+6.18589 6.77634
+3.94124 4.23942
+7.59911 8.05275
+3.68865 5.10948
+7.63926 8.63019
+-0.049855 0.0844425
+-0.41188 0.807786
+1.35962 1.81039
+5.40579 6.15098
+1.38594 2.0059
+6.93444 8.71958
+7.01229 9.38008
+-0.0974976 0.962679
+4.74131 6.59152
+1.02343 1.59245
+1.55629 1.9128
+6.28353 8.38021
+5.66349 5.79644
+1.72629 2.28563
+1.64539 2.82654
+0.359466 1.05106
+4.37569 4.82703
+5.87657 6.37853
+1.46316 1.65333
+7.44494 7.5985
+1.16846 1.98579
+4.43371 4.93234
+2.31838 2.47777
+7.52687 8.44423
+6.08056 7.42253
+9.16144 9.94783
+4.74382 4.95616
+0.248344 1.05335
+6.12345 7.43941
+9.45647 9.99799
+3.77124 4.75199
+3.31315 3.44873
+-0.0909828 1.51271
+7.03234 8.02546
+8.11403 9.11461
+6.734 7.34799
+1.08903 1.18319
+2.72871 4.31607
+6.53688 7.52754
+1.07868 1.27792
+6.28409 6.56795
+4.89866 5.79458
+9.06994 9.1221
+2.54989 3.14338
+3.69971 5.71717
+3.7113 4.55076
+8.91864 9.64522
+8.75634 8.82359
+9.02242 9.03869
+3.59945 4.20169
+4.98557 5.07401
+4.81526 5.74009
+7.264 8.63749
+2.79579 4.43389
+2.87204 4.66432
+2.32487 3.72127
+3.99704 4.72567
+8.17229 9.0158
+-0.72926 0.823658
+2.52355 3.32725
+5.3446 6.63868
+4.48935 7.37833
+3.08173 3.0968
+2.41585 3.23026
+9.23187 10.5413
+5.50099 5.51888
+1.29634 1.88846
+-0.0113225 1.41526
+6.34508 7.53417
+0.383019 2.25144
+5.0649 5.40222
+3.08221 3.76296
+9.29111 10.6833
+2.19714 2.94735
+8.75711 9.48583
+8.61564 8.69349
+1.9362 3.96191
+3.7962 4.44382
+7.78501 9.03843
+5.79649 7.29675
+6.03048 7.4316
+1.31105 4.36446
+6.5882 7.03622
+4.88148 7.12474
+6.62305 6.90973
+2.27488 2.73731
+8.42703 9.28888
+7.72928 8.53989
+7.27021 8.63879
+0.992908 1.92001
+-0.282737 0.511292
+7.88963 8.03117
+6.93371 8.26148
+-0.0346633 0.403617
+8.7827 8.82558
+5.16876 5.59742
+8.61275 8.73843
+5.70578 6.02783
+9.08706 9.35903
+9.32728 9.83021
+9.20058 10.2497
+6.79824 7.3024
+7.17979 7.51783
+0.918555 2.67878
+7.9662 8.63241
+8.85903 10.3145
+9.34614 10.1964
+9.05027 9.79872
+8.28959 8.45837
+1.32518 2.04557
+8.72848 9.16742
+5.92126 6.77277
+8.31504 8.78631
+1.02487 1.70172
+4.45204 4.72842
+8.20636 10.4724
+5.86211 6.25457
+6.15754 7.71303
+8.37832 8.82577
+4.25233 4.59417
+9.41451 9.95324
+9.372 10.4461
+1.8346 2.7144
+8.00681 8.14717
+7.03997 7.06753
+7.16892 7.70102
+7.01781 7.46799
+1.78526 1.7969
+1.63304 2.2011
+8.59718 8.61083
+9.43498 10.3636
+4.98718 5.32487
+3.65451 4.89601
+8.82368 9.11333
+-0.104862 0.598773
+4.97756 5.62342
+1.99876 3.24686
+2.32242 4.01096
+4.04914 4.77892
+3.81545 4.32583
+3.30153 3.46783
+3.14287 4.04718
+8.65711 8.76768
+9.09385 10.6898
+4.82771 5.64405
+5.98783 6.36785
+7.93397 9.6543
+4.89726 5.65486
+5.08717 5.22314
+6.59377 7.23748
+3.58289 3.98597
+0.177884 0.397629
+5.30856 5.79257
+2.53943 3.98007
+6.51217 6.59644
+0.196888 1.99904
+3.8709 4.1901
+2.37646 2.50997
+7.03837 8.13287
+6.8674 6.89535
+0.576964 2.08851
+0.902928 2.86981
+8.59261 9.20279
+5.96621 7.49899
+0.617602 1.83267
+2.29189 2.6361
+4.34207 4.61026
+6.19963 6.76443
+1.15955 1.44068
+5.25852 6.33905
+6.37306 7.53103
+9.13334 10.039
+8.67743 9.93959
+5.62973 6.04375
+8.32286 8.77042
+3.28772 6.1722
+4.97902 5.47249
+3.37765 5.07238
+4.58025 4.84341
+2.76807 3.18817
+4.27581 4.43023
+6.92572 7.68461
+0.279247 1.0561
+1.10903 2.61106
+6.71708 6.73132
+2.66415 3.75702
+8.0513 9.80334
+4.82466 6.04232
+2.59971 2.85768
+9.04689 9.73945
+3.48338 5.16622
+7.90925 8.92774
+7.30264 8.06247
+7.59087 8.26476
+0.150315 0.423068
+8.62726 9.74636
+9.01983 9.71707
+6.84007 7.40541
+8.87829 9.48342
+2.69214 3.71481
+0.580036 0.77289
+9.474 9.83397
+5.80151 6.08527
+3.63837 5.27137
+8.5848 8.65779
+7.88338 8.13276
+3.27992 4.20963
+6.21244 7.28079
+-0.348924 1.38478
+5.26688 5.93787
+3.78941 5.01009
+6.41929 8.38529
+1.41724 1.67733
+0.212821 1.58246
+0.0697189 0.160497
+9.57839 10.2377
+9.03332 9.70645
+4.94572 5.15163
+3.16999 4.536
+5.77494 6.68359
+5.89258 6.11852
+7.72257 8.21668
+8.42501 8.44905
+8.7196 8.86465
+4.392 5.1076
+1.88249 2.54422
+1.38092 1.60326
+5.04142 6.37374
+4.31795 5.91152
+1.79399 2.09314
+6.65405 8.32262
+1.36356 1.58538
+5.45456 6.55824
+4.95807 6.22848
+8.72077 10.2825
+0.745968 2.01546
+6.85041 7.11076
+4.82028 5.34442
+5.77673 8.01294
+8.58582 9.33714
+8.49884 9.21533
+9.05574 9.4096
+3.19932 3.27024
+9.50227 9.96685
+0.771636 1.0617
+9.00621 9.36397
+-0.097167 1.39463
+7.79622 8.43537
+8.05228 10.1504
+2.21685 4.17072
+1.82476 2.45381
+4.34408 4.56578
+9.27538 9.54701
+6.80153 7.44115
+7.38884 7.84448
+7.17526 8.00165
+5.85812 7.67326
+5.25545 6.30791
+5.68518 5.94055
+3.77685 4.1545
+0.530928 0.737248
+3.9772 4.59563
+8.96322 9.45618
+7.98322 8.44165
+3.42929 4.22329
+3.66445 4.7583
+-0.183652 0.434842
+3.16492 3.95726
+6.87407 7.89944
+5.08921 5.7745
+2.85466 3.04505
+7.12685 7.41248
+0.715419 0.876676
+3.47441 5.21753
+9.13594 9.87799
+5.52459 6.35691
+5.12544 6.12935
+2.44296 2.91543
+2.75148 4.19886
+1.43478 4.3919
+6.6352 7.07768
+4.72283 5.11506
+6.36434 7.69268
+2.32643 2.75289
+5.46566 6.22854
+6.37995 6.76989
+1.52564 3.55871
+1.05807 2.19393
+1.95374 4.08727
+8.11273 8.12767
+2.85955 4.71355
+4.89009 6.88516
+2.06859 2.25512
+7.50556 8.77923
+4.43353 5.11915
+5.16308 5.9695
+1.12072 1.69277
+3.96494 4.38143
+7.06931 7.89524
+0.514522 1.51265
+6.56389 7.01146
+1.51362 1.8541
+4.90339 5.51209
+2.11422 3.15457
+2.50094 3.92557
+8.24319 8.62826
+-0.0843505 0.710377
+6.35956 7.89457
+-0.790954 1.2964
+4.02253 5.19193
+2.7425 3.46763
+9.41469 10.1367
+1.57636 2.25105
+3.18647 3.38738
+8.36644 9.66791
+0.180846 0.461221
+7.07675 7.71881
+0.265366 1.19275
+5.43007 6.4854
+9.13912 9.23294
+9.52905 10.4029
+1.18712 2.66227
+5.22714 5.62601
+1.87413 2.8716
+5.71882 6.16374
+5.38169 6.13948
+-0.196005 0.236738
+5.36803 6.4395
+8.27713 8.71262
+8.82031 8.8598
+-0.53845 0.564783
+1.80716 1.94173
+5.67905 7.47291
+2.37779 3.64893
+0.574727 0.766424
+4.60701 4.86591
+3.17989 4.37738
+1.36777 3.15112
+1.48092 3.06573
+3.37009 4.06028
+4.17179 6.2073
+6.47953 6.88994
+5.74431 6.5253
+4.88827 5.49049
+5.44148 5.59239
+1.66153 2.63132
+7.69387 7.82267
+5.20911 5.48488
+-0.103218 0.497402
+7.18003 7.33324
+6.54305 8.81732
+0.278108 1.27452
+2.38323 2.94772
+1.2461 2.03246
+5.47052 5.75781
+7.31505 7.35895
+2.22248 4.23589
+0.0305319 0.430773
+8.32043 10.1222
+6.11732 7.09764
+5.08797 5.74991
+6.62491 7.34164
+5.55795 5.66083
+3.27549 4.13145
+1.0113 3.24631
+0.0717186 0.519738
+7.82905 9.30839
+9.90251 9.98691
+0.841457 0.952276
+-0.133927 0.510174
+1.14614 2.82218
+2.59767 4.19742
+3.41095 3.95265
+3.38951 3.75838
+8.86766 9.19437
+9.27927 10.261
+2.33249 2.79402
+5.69681 5.93469
+4.02502 5.38732
+0.797157 1.22845
+7.23558 7.8651
+1.1253 1.99184
+8.58296 8.64267
+-0.400141 0.74698
+3.46677 3.50526
+6.03252 6.64842
+5.8493 6.68938
+3.53209 3.84014
+7.22078 8.98106
+6.21943 7.69944
+0.887198 2.07323
+3.36591 4.57442
+4.30143 6.41179
+4.07556 4.54276
+8.77552 10.0615
+6.7247 7.04044
+9.05494 10.1126
+7.46604 7.80632
+3.38601 3.8043
+5.60475 7.02788
+9.09811 9.4654
+9.33447 9.80012
+8.66499 10.1002
+3.87007 3.88281
+2.87624 3.11359
+5.92385 6.80801
+4.49711 5.01863
+8.84524 9.36225
+6.40944 6.82093
+2.90915 3.68288
+3.96801 4.82534
+5.51744 5.84233
+3.2959 3.44409
+0.18526 0.207322
+5.49717 5.72648
+6.9522 7.1952
+0.769572 1.79343
+5.95522 6.03918
+6.54327 7.7475
+2.13516 3.83957
+-0.388892 0.775076
+1.30128 2.29414
+9.76761 10.1604
+7.38731 8.66002
+7.09229 7.43495
+9.1379 9.52432
+6.75942 7.88717
+7.42824 8.82063
+6.93078 8.19884
+2.307 2.93836
+8.38254 8.84691
+3.90159 5.37938
+0.0413204 0.112203
+0.638217 1.53943
+0.88678 2.49435
+1.99104 2.60847
+6.61595 7.65064
+2.37641 4.71719
+7.94945 9.21404
+5.44594 7.13646
+5.45737 6.12335
+7.39207 8.02885
+5.51588 7.39341
+8.1581 10.0632
+0.197869 1.44516
+-0.0161139 0.73487
+4.24155 4.7304
+0.00374564 1.26481
+8.1878 8.20011
+-0.115544 1.74771
+0.912347 2.52922
+2.72234 4.83268
+6.45577 7.07776
+9.74201 10.1772
+7.11008 8.72914
+4.41921 4.8673
+7.97673 8.36658
+0.438659 0.647061
+4.35086 5.44482
+8.22919 9.34379
+3.53242 5.65576
+1.126 2.32177
+5.95118 6.51364
+3.10519 3.9447
+1.28889 2.26267
+7.04255 7.67791
+3.12614 3.17626
+8.09968 8.49162
+6.07924 7.219
+5.99554 6.52549
+9.14378 9.5773
+5.82872 6.53112
+9.3361 10.1704
+4.3751 6.51675
+3.288 3.98328
+4.56342 4.80185
+7.16574 7.43901
+7.7638 8.47758
+7.31514 7.78499
+7.98942 9.50252
+4.31211 4.70724
+2.9094 3.33304
+0.108736 0.668815
+8.08409 9.11098
+-0.0053985 0.589992
+1.31926 2.72153
+2.28664 2.38813
+7.95237 8.26388
+-0.0283047 0.452099
+7.50295 8.71708
+7.72356 8.63468
+3.48953 3.89579
+7.73814 8.73456
+4.54487 5.45817
+6.45109 7.00312
+3.99915 5.41716
+6.81436 8.5682
+6.86726 7.55999
+2.67863 3.7053
+2.6837 3.39567
+2.84347 2.91724
+5.79383 5.80493
+2.41217 3.0619
+8.78163 9.0998
+1.43456 2.50854
+6.73393 8.53005
+3.02563 3.56456
+3.34628 4.2934
+2.44985 2.92819
+1.38262 2.89341
+4.56337 5.75702
+0.275735 1.16604
+1.39763 2.8108
+9.69128 9.90361
+8.54868 9.66756
+3.01838 3.72831
+8.34017 10.5262
+1.82721 3.0476
+5.9732 6.83307
+2.77874 4.25603
+1.71987 3.1227
+6.33773 7.89103
+1.31982 2.82992
+4.21601 4.9627
+6.68166 6.72653
+0.87708 1.06828
+1.03483 1.26625
+2.996 4.03087
+1.54718 1.57452
+2.33087 2.38226
+2.29464 3.36496
+2.03064 3.41867
+5.8456 6.10406
+7.54614 8.2874
+1.42938 2.89154
+2.65935 3.53883
+3.98845 4.42049
+6.85632 7.15487
+8.12038 9.34993
+0.873558 1.32129
+6.61595 8.00766
+9.49147 9.81947
+-0.0225601 0.328769
+-0.481519 1.37204
+6.31457 7.45251
+4.59738 5.81395
+4.83304 5.63008
+1.95746 2.78657
+2.97889 3.74408
+9.08327 10.702
+3.58219 4.93634
+7.87068 9.77851
+0.330978 1.36031
+4.78145 5.36918
+4.94672 5.56644
+7.66806 8.08613
+4.78512 6.35461
+5.17367 5.74386
+8.65884 9.97088
+9.22053 9.60447
+6.15061 6.58817
+0.0875971 0.541643
+6.45597 7.92002
+0.636824 1.05267
+5.31677 6.12838
+6.51127 6.6731
+0.459551 1.69382
+5.75106 6.41377
+3.68438 4.67415
+9.36302 9.78281
+5.46195 7.99215
+2.55471 2.59231
+-0.0640245 1.33755
+9.36027 10.6198
+2.67955 2.77882
+3.51443 4.10619
+6.83904 7.23692
+2.59553 2.81418
+7.74628 8.95169
+3.86464 3.90067
+3.32377 3.992
+1.43737 2.52191
+3.83927 3.99402
+5.24426 5.35179
+0.833857 1.05277
+8.4062 8.51964
+9.62299 9.66254
+3.55427 5.19048
+1.7003 2.62107
+6.8059 7.49246
+-0.761104 0.773528
+1.37137 1.95048
+2.1222 2.59387
+0.633505 2.04796
+0.605156 1.04336
+7.22842 8.3365
+4.28716 5.28921
+8.14286 9.52015
+7.62467 9.18603
+1.11029 1.81278
+5.05654 5.13597
+0.862653 0.97827
+7.24766 7.92167
+8.80103 8.91467
+3.05841 4.82292
+1.28204 1.55969
+1.58886 2.57874
+0.0537678 1.28837
+8.09303 9.71678
+8.37599 8.85705
+3.18107 4.01971
+6.67019 7.75848
+6.29836 8.21603
+0.86271 1.30358
+3.86126 6.49694
+5.84446 6.24913
+0.475025 0.598151
+6.3477 7.08327
+3.60161 4.51824
+7.13317 8.13858
+4.89052 6.23701
+5.69441 5.99027
+7.18735 8.34853
+9.30182 9.34894
+6.06589 6.15141
+8.05917 8.89642
+5.6136 7.14058
+0.838337 0.959487
+0.56421 2.00841
+6.46876 6.63629
+2.4434 3.92184
+7.97216 9.45372
+8.17926 8.66756
+1.86522 2.01888
+0.983342 1.89079
+2.07322 2.09765
+3.52974 4.73717
+3.24973 4.88691
+5.47789 5.95384
+4.11218 4.57076
+6.61174 7.47165
+8.09302 8.36193
+1.67911 1.69022
+4.436 6.17515
+5.6544 5.74951
+1.50354 1.76043
+4.41433 4.83589
+1.82528 3.53979
+3.98749 4.65527
+6.42503 7.5787
+8.69554 10.1767
+8.39215 8.56999
+8.71646 9.66209
+1.59091 3.39622
+6.12574 6.94955
+7.92527 8.25049
+9.19858 9.49137
+2.73382 2.97747
+4.56558 5.94738
+8.33983 8.58548
+9.00798 9.01838
+4.93268 5.28383
+3.15356 3.58606
+8.28171 8.79351
+1.47358 1.9581
+0.891797 2.05345
+1.56032 2.38159
+2.5152 3.80485
+8.0963 9.88138
+1.1262 1.89279
+7.99336 8.2352
+5.25067 5.41251
+4.57532 5.20101
+1.87911 4.59415
+4.25142 4.70467
+8.18782 8.76989
+9.20478 9.3612
+7.70898 9.7752
+0.655865 0.958924
+4.8883 5.77477
+3.03279 3.47456
+1.01979 1.41661
+8.94219 10.6987
+2.49348 4.58195
+2.44003 3.29005
+3.4725 3.55572
+9.3917 9.95851
+7.08658 7.47686
+3.56413 4.44089
+-0.47868 1.11453
+6.82615 8.00596
+3.49451 3.74705
+8.13286 8.47976
+7.01732 8.82556
+1.19064 1.48887
+5.28851 6.88637
+8.83175 9.49879
+0.939903 1.17024
+7.49124 9.01906
+2.9285 4.23224
+5.68296 6.86273
+8.53897 8.77886
+2.9107 5.01232
+0.748655 1.10265
+4.77258 5.12626
+3.995 4.75289
+2.71467 4.26926
+6.21665 7.16233
+4.53883 5.75731
+4.37153 4.76125
+7.47635 8.75777
+4.82013 6.4699
+9.36015 9.58451
+4.43054 5.86752
+2.10934 2.34705
+3.00306 3.06539
+7.81957 8.44081
+1.97221 3.06916
+0.153393 0.503956
+5.05611 5.27536
+5.73277 5.89001
+3.64807 4.85582
+6.13416 6.1528
+3.85511 4.14045
+0.411725 1.36529
+2.26932 2.5447
+3.51164 4.93266
+2.50955 4.34201
+8.74663 9.39268
+6.2229 6.39303
+4.38059 4.91592
+7.29109 8.62318
+6.31801 6.99532
+9.75036 10.0514
+1.69019 2.41527
+4.20462 5.27729
+6.32944 6.94729
+3.5736 5.21496
+4.48316 4.61828
+1.76915 2.43263
+2.42026 4.09159
+2.08762 2.43074
+5.48161 6.02473
+5.51826 7.47042
+2.78026 3.1552
+7.89469 9.49867
+3.09084 4.54697
+7.20417 7.42408
+5.36528 5.74851
+1.86239 2.41988
+1.55994 2.85743
+4.40182 4.6638
+7.91619 9.01242
+3.08119 3.74714
+1.54108 2.08538
+3.61461 3.64631
+8.76851 9.66257
+-0.645571 1.3366
+-0.707083 1.21005
+7.19571 8.23405
+5.42865 5.89329
+2.12897 2.59222
+0.603102 0.930391
+3.75025 4.63181
+6.14867 6.4526
+7.30947 7.51461
+7.83183 8.79802
+6.06658 8.53246
+1.67895 2.50063
+1.14179 2.04478
+8.59583 8.90112
+-0.918885 1.30717
+0.182607 0.613593
+3.3335 3.77196
+0.783053 2.4368
+6.49331 7.60104
+2.85101 3.28637
+7.42273 7.66905
+3.96433 5.02573
+8.26262 8.40749
+9.24451 9.32783
+4.89036 7.07214
+6.45431 6.96815
+5.20701 6.58747
+7.40142 7.98615
+4.19768 4.9831
+3.32546 3.88811
+-0.471996 0.967855
+9.36172 9.63532
+1.96831 3.00632
+7.537 9.72671
+4.67746 4.81135
+3.10782 4.93642
+4.94809 6.54855
+4.16763 5.25628
+9.04992 10.316
+0.668935 0.680886
+4.02935 4.84503
+5.32499 5.76636
+5.32267 7.15457
+5.18886 5.23491
+4.37053 5.36801
+2.39955 2.74657
+8.19764 8.86645
+4.24706 5.69703
+1.87851 2.36988
+0.886553 1.05064
+7.27428 7.90224
+9.08417 9.44879
+3.11534 4.02019
+6.3284 7.39925
+4.96029 5.59076
+2.58248 3.11741
+7.76513 8.13505
+4.93613 6.51523
+0.565355 1.70512
+2.12366 3.0319
+5.32422 6.84146
+-0.135396 1.08591
+3.7901 4.86303
+4.49677 5.41847
+0.615748 0.834712
+0.64784 1.81859
+6.65505 7.13894
+-1.12744 1.61017
+0.550814 1.24316
+6.66639 6.89866
+6.19271 8.17468
+3.09382 3.78684
+4.41221 4.95889
+7.96091 8.48824
+8.32129 10.2917
+2.13168 2.19835
+1.4635 2.38989
+5.78102 6.42215
+1.70153 3.20616
+5.35068 5.71016
+4.27702 4.37203
+5.13888 6.04764
+4.79644 5.37927
+6.75314 7.66368
+6.04484 6.84064
+4.34947 4.45643
+9.08755 10.396
+0.88804 2.17441
+6.86788 7.88301
+7.94296 8.61664
+8.02387 8.79591
+1.79024 2.40559
+5.50404 6.01044
+7.76772 8.1932
+1.174 1.23693
+6.20571 6.9224
+4.20863 4.48702
+4.16743 4.39075
+-0.11965 0.120778
+7.01234 7.52619
+5.91415 6.46151
+5.28713 5.72354
+6.26981 6.31237
+0.643056 1.43864
+1.62562 1.99875
+0.544992 0.721386
+6.92522 7.09165
+-0.107048 1.12273
+0.644674 0.91244
+8.56904 9.01883
+2.23079 2.56598
+9.79034 10.1123
+8.13788 8.4131
+1.86753 1.95236
+2.97577 3.33272
+8.57454 10.0193
+1.20043 1.53408
+3.43515 3.86571
+5.79075 6.41293
+1.71558 2.52845
+2.39907 3.46652
+9.08289 9.91182
+0.859644 1.07475
+5.30144 5.42157
+-0.441497 0.890794
+3.55044 4.14918
+-0.340115 1.19239
+6.5534 6.76908
+0.836514 2.09196
+8.15747 8.96484
+4.80087 5.14227
+7.72071 8.88223
+5.11901 5.65559
+4.44996 4.63562
+-0.328404 1.3002
+0.90759 1.34556
+5.94839 6.35058
+1.76504 1.78344
+1.32585 2.08994
+7.18641 8.20945
+0.62657 1.06025
+6.28086 6.40975
+5.05525 5.16143
+5.82694 8.07685
+6.23677 7.55394
+-0.226265 0.661443
+1.42599 2.36325
+9.04445 9.92971
+-0.169286 0.185741
+8.34636 10.9042
+9.52494 10.0475
+8.39989 10.1377
+3.89956 4.70428
+3.98673 4.97185
+5.43008 5.67936
+7.76475 7.98591
+4.46895 4.73188
+0.584662 1.54474
+2.12622 2.79994
+1.40578 2.2461
+1.45171 2.02105
+2.05665 3.04611
+2.29818 2.68118
+1.77344 2.98698
+4.92092 5.55302
+7.18758 8.37525
+8.83407 10.0565
+2.91182 4.71932
+6.47293 6.74664
+2.49238 3.69749
+0.487234 0.541003
+4.703 4.92744
+9.8867 9.94918
+1.7713 1.9792
+5.68316 6.90242
+5.62485 6.70656
+7.24837 9.60197
+7.71147 7.76519
+5.22324 5.30661
+9.11258 9.28071
+8.2827 8.90115
+8.90865 9.42138
+7.47233 8.72308
+4.89712 5.65153
+4.12392 4.20239
+5.65325 6.55887
+8.65945 9.05845
+7.9165 8.36489
+1.4952 2.43991
+5.49665 5.80793
+1.67206 2.55302
+0.943544 1.58521
+0.47 0.860959
+6.47638 7.43101
+4.38434 5.97278
+8.12782 9.10574
+5.78143 6.6539
+9.23616 9.40513
+1.6845 2.00736
+6.56955 7.37847
+7.42993 9.04718
+-0.179632 0.450904
+8.65819 9.07724
+7.86567 8.80824
+1.85428 2.7755
+2.29222 2.65374
+4.03614 4.51729
+6.9326 7.07635
+5.50807 6.498
+6.17637 7.26432
+8.7688 9.16308
+7.65 8.88604
+3.74495 4.29991
+8.5671 10.5661
+7.41964 8.21083
+8.04302 9.78783
+0.269663 0.317601
+8.29804 9.40991
+3.90673 4.22298
+8.82384 10.9441
+7.27081 8.19548
+1.30184 1.98993
+8.13028 8.92385
+7.21224 7.35137
+5.02122 5.69666
+0.817219 0.974073
+-0.128067 0.589359
+2.12137 2.74019
+5.24657 5.44714
+1.55805 3.10332
+9.91031 10.0748
+7.13941 7.9143
+-0.183908 0.934079
+3.987 4.11053
+3.26678 3.67608
+9.75921 10.1121
+0.755391 1.06346
+7.28479 7.49982
+1.37522 3.80623
+0.944351 1.46531
+9.49278 10.2372
+8.28946 8.67597
+9.43537 9.58003
+7.73357 8.756
+2.64043 2.8687
+4.70448 6.99929
+3.82199 3.89343
+3.43825 4.10908
+4.42362 5.69086
+8.08536 8.60142
+8.43208 9.31272
+7.5889 8.39208
+7.90112 7.9734
+6.10381 6.80568
+8.76283 8.80151
+1.46728 2.53288
+1.68884 2.47102
+7.63343 8.29838
+9.18852 9.5558
+0.977174 1.4792
+4.7577 5.74873
+4.66433 6.37375
+-0.0952277 0.378184
+5.30929 6.07469
+4.98811 5.16146
+3.0744 5.59799
+0.944909 1.25222
+1.38561 2.51277
+3.77811 4.23459
+2.11604 3.32458
+0.920929 1.17187
+5.23496 6.34905
+6.9953 7.65745
+4.81803 4.89553
+4.69301 5.36777
+-0.208926 2.6111
+7.97334 9.83269
+-0.396673 0.779988
+5.91367 6.47682
+6.27249 6.83533
+5.58931 6.89679
+2.03394 2.67025
+-0.197752 0.383167
+4.69751 7.695
+4.5989 6.07875
+3.7285 4.27396
+7.9807 8.27693
+-0.00248985 1.30934
+2.68016 3.916
+0.881558 1.14567
+4.77066 5.05302
+0.552268 0.919467
+2.46862 2.65199
+1.4009 2.51701
+-0.171185 1.28252
+9.27842 9.90243
+3.51778 3.57728
+6.10071 6.92163
+9.05387 10.0894
+5.52995 5.89082
+8.40216 9.0272
+9.02911 10.1602
+4.85818 7.38829
+1.6762 2.32334
+6.45416 8.62337
+5.44592 6.0245
+3.45876 3.94274
+9.07144 9.16725
+6.51885 7.6363
+7.92593 9.01986
+0.270702 1.57395
+6.11245 6.70173
+1.37658 2.19068
+2.42668 3.43827
+7.98226 8.43306
+3.72269 4.74654
+8.16252 8.58873
+8.81456 9.5363
+-0.338386 0.864811
+1.90693 2.25796
+3.5305 4.17475
+6.07997 7.67393
+0.53347 1.68815
+7.31182 8.44458
+7.77462 8.33613
+3.79975 4.15552
+9.08822 9.9771
+-0.101698 1.05442
+8.44869 9.95724
+-0.0318759 0.532673
+8.09238 9.51356
+5.51514 6.60799
+8.66528 10.3297
+8.25556 9.97893
+-0.220428 0.247563
+0.00453913 0.540444
+1.53599 1.61735
+3.77213 5.06896
+2.65332 2.75864
+6.05811 6.43112
+0.302534 0.803651
+0.393766 1.11611
+9.31035 9.62387
+0.568281 1.7765
+-0.721118 1.27387
+1.83573 2.62578
+1.39953 1.91158
+6.51883 8.52813
+2.60154 2.95054
+6.58322 9.37818
+5.61178 5.67661
+9.56511 10.2767
+9.09174 10.0697
+2.55846 3.39943
+8.38146 9.06138
+7.97019 8.18074
+6.1426 6.42787
+1.15876 1.55463
+2.93483 2.96376
+7.23883 7.29158
+9.64606 10.0674
+4.89825 6.70366
+7.35635 7.96328
+2.2702 2.36797
+-0.0464389 0.395244
+1.14883 2.10411
+4.7309 5.10593
+6.07946 7.37741
+5.50202 6.28822
+3.66574 3.96271
+1.9944 2.3862
+7.58159 7.59275
+1.98712 3.30587
+2.10317 2.89161
+9.66889 9.97287
+1.57327 2.15421
+8.14125 8.30983
+3.77185 4.12658
+8.51624 9.51485
+9.25211 9.722
+2.06312 3.0453
+9.34954 9.91254
+7.31475 8.89322
+7.85044 9.20242
+0.226243 1.28465
+0.0260868 0.575177
+9.40743 10.1655
+4.04324 5.05341
+1.02626 1.48332
+3.33074 3.72025
+9.2005 9.61387
+6.68317 7.14109
+6.82083 8.6312
+4.34816 4.50329
+-0.48874 0.975608
+4.26651 5.68526
+4.89731 5.57569
+2.68984 3.5661
+0.499714 1.01055
+9.01902 9.36142
+3.22067 4.59054
+0.65132 0.860512
+1.6791 2.36642
+8.28222 8.7579
+2.84349 3.24134
+5.64949 6.09512
+3.44026 4.43245
+2.60889 2.6248
+-0.00849234 0.984046
+7.5745 8.65675
+2.07464 2.6488
+2.59747 2.65772
+6.36828 7.42208
+3.83342 4.50127
+5.41167 5.7011
+6.53606 7.53796
+8.21975 9.56176
+1.90113 3.08684
+7.74402 7.82057
+4.26515 5.11327
+5.42743 5.59215
+8.69709 10.0912
+2.87019 3.94798
+9.27013 9.54627
+9.30568 10.2136
+9.02985 9.62917
+3.7589 4.59642
+6.59359 6.86939
+3.26574 4.83488
+5.14545 7.70086
+7.43163 8.05103
+5.72972 5.74457
+0.490113 1.31151
+7.018 7.42627
+6.22976 6.27589
+9.07732 9.30419
+4.3917 4.42663
+8.50298 10.3728
+6.18671 7.53619
+3.51053 4.097
+2.17172 3.56595
+6.08046 6.23691
+9.07361 10.9129
+3.95757 4.11333
+-0.136516 0.78995
+1.34923 3.47002
+0.0562579 0.686502
+9.10943 10.2731
+5.80174 6.16971
+7.86011 7.87649
+5.34384 5.51645
+6.32167 6.76387
+7.70566 8.28038
+-0.319903 0.867682
+-0.372564 0.570014
+8.83696 10.8439
+7.78947 9.38211
+9.25815 10.1092
+5.59721 5.67148
+0.234719 2.42489
+1.06314 2.87416
+1.75391 2.69799
+5.4536 6.66068
+1.35696 1.87102
+2.17418 3.1459
+7.61817 7.98287
+2.92194 3.18393
+7.68243 7.83261
+9.33163 10.5531
+1.14227 2.50228
+5.47911 5.70857
+9.88123 10.0758
+8.81249 8.83145
+6.02747 6.43183
+4.81158 5.79178
+6.65666 7.5047
+4.89085 5.56569
+0.935564 1.71547
+-0.0452879 1.16222
+4.03524 4.6206
+5.88518 6.02658
+2.06227 2.9581
+0.207246 2.2404
+2.81757 3.70318
+0.704257 1.98403
+2.38486 3.30039
+3.57073 4.78358
+1.53721 3.00546
+8.37852 8.39527
+1.54619 1.59789
+1.00447 1.40778
+5.31977 6.43861
+3.82175 3.83209
+3.37738 4.44002
+5.46644 5.97254
+3.88191 5.00688
+4.88046 5.39031
+4.15092 4.93679
+1.75182 2.07399
+1.16434 1.76541
+3.37032 4.29676
+3.1685 3.98533
+1.28787 1.59775
+5.86338 6.17993
+3.8645 4.25757
+1.83947 2.48092
+0.184795 0.586724
+3.13752 3.76447
+2.14264 3.03248
+5.78182 5.9029
+2.47969 3.8088
+2.59206 3.08362
+-0.354871 1.03627
+7.94041 8.05947
+9.48014 9.93817
+0.992727 1.48877
+6.1525 7.51387
+5.00071 6.15665
+7.42074 8.27606
+9.6539 9.83042
+1.08984 1.46387
+5.46282 6.95907
+4.74506 5.13968
+0.357565 1.91464
+9.07652 9.65474
+0.201095 0.646211
+7.04306 7.69131
+1.17728 1.2237
+5.92183 6.29165
+-0.41356 0.491524
+8.38339 10.4509
+8.08648 8.11344
+3.32474 3.39522
+5.762 5.83732
+2.26778 2.55548
+4.86127 5.92868
+3.75949 5.16608
+4.83431 5.88632
+2.65122 3.31344
+9.30295 9.38948
+6.03391 6.32749
+5.12035 5.59414
+5.68785 5.979
+7.89553 9.15202
+2.54445 2.74715
+2.36337 2.49709
+4.71661 6.12198
+3.72447 4.68735
+1.0541 1.53187
+3.45178 4.80929
+7.90773 8.26212
+8.1816 9.18627
+0.322569 0.871041
+7.24823 7.32699
+1.7003 2.78087
+9.70927 10.2515
+3.75922 4.01081
+1.06949 1.40253
+1.21774 1.4734
+6.02123 6.32973
+2.76396 3.09484
+2.80358 3.00026
+5.25666 6.31369
+4.71714 5.30669
+4.37906 4.50557
+7.40824 7.44969
+7.89081 9.18263
+8.8136 10.3074
+9.1757 9.37261
+7.1938 8.51137
+0.580081 2.32678
+2.02497 2.95434
+6.01446 6.78851
+8.54365 9.21454
+3.03567 3.27089
+0.650657 1.5716
+5.05518 6.36521
+1.64301 2.76399
+4.15989 4.34183
+3.72791 3.98156
+3.91372 4.06182
+3.04507 3.88871
+3.82596 4.25694
+3.36492 5.00402
+6.50019 8.17974
+3.54621 3.81009
+0.546921 2.09811
+5.1789 5.9826
+4.98983 6.31221
+2.47557 2.63878
+4.64568 4.81101
+9.1462 9.21888
+7.37417 7.5276
+2.21604 2.50113
+8.29804 10.2722
+5.1282 6.06353
+8.58281 10.1589
+6.47084 7.04085
+6.27806 6.72674
+7.11554 7.85687
+6.01085 6.02773
+5.46694 7.52872
+9.51078 9.85387
+3.36627 4.06552
+2.96126 5.12635
+3.09314 3.40691
+5.05456 6.62548
+7.56469 8.97053
+1.33727 2.87482
+5.6572 6.28169
+0.120924 0.296475
+7.09139 7.41322
+2.10076 3.28507
+8.74998 10.1094
+7.45072 9.50796
+7.75294 8.59218
+0.740374 2.44897
+7.63001 8.91562
+4.30743 4.81716
+6.40813 7.29159
+6.30213 7.35987
+6.44392 7.32584
+8.41155 9.4466
+-0.377892 0.689618
+5.88857 6.70983
+6.67779 7.70668
+4.831 5.17464
+2.62342 3.82764
+8.57453 9.29283
+7.32648 7.96725
+9.32937 9.9726
+7.30774 7.65754
+3.97456 4.59876
+5.73092 7.20962
+1.958 2.10551
+3.2115 3.81482
+5.76497 7.42425
+2.77219 3.29692
+4.95297 5.14843
+5.96367 6.3619
+2.49872 4.61736
+8.21817 8.23425
+2.13615 2.61877
+7.84121 9.55011
+8.63416 10.2773
+5.61084 6.32053
+4.86002 5.79944
+9.07858 10.688
+5.95829 6.42504
+3.3289 4.17849
+3.27989 4.91625
+8.28046 9.23021
+2.18691 2.6072
+1.3962 1.75013
+2.13627 3.73117
+2.11128 2.57303
+7.22357 7.50136
+7.43862 8.03136
+2.80578 3.02886
+0.176906 0.761142
+5.99314 6.6075
+1.90398 3.3925
+5.48264 6.73579
+7.18447 7.49811
+3.24434 5.05219
+5.53263 6.04178
+1.71172 2.45682
+0.297266 0.481632
+2.62582 3.36142
+0.243865 1.49321
+8.86142 10.169
+3.93193 4.39404
+4.98182 5.15675
+7.99209 9.73159
+8.18033 9.45596
+4.25235 4.41546
+1.59603 2.15581
+6.47724 8.69649
+5.24138 7.93131
+3.4267 3.49003
+0.0439912 0.316407
+1.99983 3.87206
+-0.103124 0.568771
+4.62451 4.80117
+2.89065 4.16315
+5.82817 7.43232
+6.89255 7.82189
+5.71037 6.81241
+4.34551 5.24905
+7.33931 7.3741
+-0.855192 1.27129
+8.94842 9.10813
+9.19877 9.68412
+6.42658 7.77968
+-0.0669636 0.430107
+6.40366 7.40701
+8.91175 9.24059
+3.21388 4.21676
+3.38557 3.79509
+4.24411 4.97032
+7.259 7.34896
+2.55995 3.18361
+8.77438 10.5503
+8.18685 9.79378
+2.78397 4.4563
+8.6891 9.38337
+6.51749 7.59374
+2.52346 3.46101
+8.40526 9.35647
+5.26942 6.33572
+4.15094 5.00668
+0.471666 1.53842
+7.63441 7.96745
+2.39974 3.7814
+2.71989 3.02994
+8.12085 8.33493
+6.19474 6.84381
+6.6133 8.31417
+5.1758 6.94983
+8.66241 8.79095
+6.10878 8.22083
+8.81883 9.08031
+8.28969 8.45176
+7.19851 8.37836
+1.5722 1.6836
+4.57814 6.95063
+7.66128 8.10631
+0.742483 3.08515
+1.15026 1.98074
+3.90133 4.12003
+7.61145 7.73433
+8.32187 10.2933
+0.407205 1.08089
+1.26545 2.60796
+2.70646 3.92753
+-0.196551 1.83536
+-0.413063 1.23838
+0.264484 0.556192
+6.30158 6.96097
+-0.66246 0.809062
+9.34243 10.3521
+8.70093 8.79679
+0.745195 1.92911
+9.12892 9.68193
+7.98533 8.30538
+6.23671 7.04296
+6.5603 6.95483
+7.08133 7.10563
+2.15769 2.41541
+8.24752 8.73978
+5.27693 5.61904
+0.317419 1.48404
+3.48029 5.46979
+7.38901 8.56554
+1.06587 1.62384
+5.54926 6.04924
+4.46577 6.48749
+5.349 6.15584
+8.04249 8.17359
+3.37651 3.56179
+3.64706 5.57403
+4.49844 5.26404
+3.93361 4.92128
+5.82184 6.29881
+0.984273 1.70318
+1.12773 1.80726
+3.11675 3.17451
+5.07913 5.46291
+0.615591 1.81465
+1.08948 2.77847
+7.97412 8.07365
+5.05207 5.82497
+0.0407709 0.558817
+6.11142 6.48205
+3.4461 3.57315
+8.6547 8.80553
+8.18965 9.64194
+5.55564 7.9703
+4.01776 4.16989
+2.4668 2.82018
+0.911925 2.56662
+4.68814 5.03614
+7.4899 8.49036
+8.40912 9.14001
+2.32725 3.16377
+0.0723972 1.42049
+6.6441 6.6953
+3.65586 4.38222
+6.35844 6.57833
+4.44435 5.73077
+1.81779 2.57257
+4.17692 4.59722
+8.54682 9.38058
+1.61135 1.81629
+3.91926 5.00536
+9.78302 9.85143
+1.25632 3.10345
+5.53191 6.08174
+-0.231868 0.676811
+1.03054 2.58105
+0.0402172 0.690608
+0.974571 1.25234
+5.22227 5.92302
+8.05843 10.1439
+8.48938 8.50755
+0.0965782 1.24008
+6.53821 7.47765
+0.189991 0.475204
+8.48963 8.54995
+9.68363 10.0534
+1.49381 2.71302
+6.75552 7.41283
+7.91075 9.15302
+0.520922 1.40928
+1.17957 2.11221
+4.00122 4.40686
+7.32467 7.9273
+6.39126 7.90248
+6.50534 8.19308
+7.19888 7.22234
+-0.136797 0.731889
+0.870318 1.25614
+2.07126 2.28297
+6.10995 7.60408
+3.02174 3.90102
+-0.657541 1.57517
+0.993121 2.66255
+7.27232 7.50832
+2.16079 3.75428
+9.27397 9.75098
+8.36865 8.5545
+4.56641 4.97607
+3.60746 4.34616
+6.31304 7.70611
+2.91442 3.7602
+4.85814 6.70407
+4.45876 5.67661
+8.06749 8.82229
+2.02826 3.59873
+1.92922 2.50088
+2.63867 3.48117
+2.17665 2.54826
+8.62674 9.10675
+0.96648 1.47671
+8.86336 9.53978
+5.52747 5.80829
+0.77099 3.06106
+2.2307 2.53877
+6.29165 6.63018
+4.44717 5.04651
+3.80894 4.63054
+7.47519 7.87072
+0.933668 1.9949
+-0.712945 1.21558
+7.30206 8.38376
+5.80281 7.00022
+7.96578 8.6558
+0.24063 0.706466
+4.41893 4.58472
+4.0132 4.92768
+5.29626 6.09397
+3.43602 4.00728
+0.780945 1.66499
+8.83861 9.15168
+9.06411 9.75544
+3.45618 3.62529
+9.51413 10.0148
+0.842106 1.75695
+1.06485 1.44192
+6.89987 8.05314
+7.89154 8.73313
+8.71675 9.79526
+2.40574 2.58062
+8.55952 8.78132
+5.61716 6.06282
+3.71059 3.77929
+2.50187 2.99137
+6.92852 7.23184
+7.00442 7.93869
+8.82232 8.8756
+4.10389 4.53702
+7.6907 7.77577
+9.31554 10.2674
+8.51082 8.70339
+4.83332 6.70311
+4.6904 5.42892
+4.71407 5.67695
+4.12047 4.44089
+7.51845 8.26858
+1.31781 1.9397
+6.26854 8.02093
+6.92072 7.77774
+0.438156 2.18909
+0.898035 1.72074
+3.81121 3.8643
+1.01676 1.34308
+9.28445 9.42801
+2.43133 4.43516
+4.33664 5.9904
+2.19178 2.37244
+1.5457 1.79785
+2.23781 2.6481
+6.8365 6.87073
+0.82568 2.74775
+9.59404 9.89262
+8.48394 9.15107
+6.16085 6.42224
+3.5667 5.97689
+4.16931 7.41638
+6.95636 7.0982
+6.87987 7.09233
+3.12619 3.14821
+7.76636 7.98459
+4.60371 5.59136
+3.92189 4.88302
+6.90694 8.19858
+3.85132 5.19015
+8.05045 8.32483
+4.8338 6.05032
+1.93576 3.18873
+2.4182 3.55039
+5.56905 5.8172
+4.18436 6.01283
+3.04944 3.85936
+7.83585 8.95233
+1.76281 3.0558
+3.44143 3.6317
+8.69887 9.40371
+5.67867 5.73236
+0.859809 1.76578
+6.92284 7.13601
+8.27495 9.13414
+5.44385 6.42599
+-0.941603 1.8215
+7.88161 8.79447
+0.965018 1.17732
+5.56442 5.79546
+8.79032 10.9909
+5.28632 5.79175
+4.80998 6.07002
+8.4021 9.81107
+3.16415 5.08682
+-0.212163 1.2052
+5.683 5.83625
+0.738527 1.31842
+2.03835 2.52756
+7.4543 8.91243
+-0.568869 1.44659
+3.58855 4.42371
+6.33058 7.18779
+-0.645579 1.94313
+2.18149 2.24157
+3.80281 4.67323
+5.14628 5.97452
+2.55239 3.45685
+3.56586 6.23355
+6.74752 7.19693
+8.99006 10.5533
+0.259833 0.99882
+8.9005 9.75401
+7.28058 8.41075
+4.57803 5.70104
+9.82823 9.90251
+6.94375 7.42033
+7.8878 8.81951
+5.01137 5.52693
+2.25503 2.28817
+6.65772 7.11107
+0.647512 2.04416
+4.34796 4.5706
+4.5395 4.91529
+2.65423 3.49531
+7.97384 8.78377
+5.53873 5.76806
+9.78641 10.1351
+6.01664 6.44407
+3.47406 3.75187
+4.59421 4.81804
+1.20641 2.00488
+2.48904 2.80768
+5.77372 6.10692
+2.49363 3.24499
+1.8483 2.62965
+2.28556 3.22209
+3.17819 4.51426
+3.5548 4.23276
+3.25239 3.57895
+0.613317 2.44862
+3.82234 4.78976
+4.72809 6.46528
+9.54107 10.4426
+9.20052 10.1921
+8.24152 9.89817
+5.17594 6.19462
+7.83364 8.17082
+5.67992 6.36464
+8.9943 10.1426
+2.20598 3.0081
+3.38199 5.16464
+0.599928 1.35804
+0.841211 1.60761
+5.29338 5.89919
+1.11061 2.29219
+3.41512 3.95907
+7.9375 10.0203
+8.73852 9.66917
+9.95092 10.0162
+4.02544 4.30219
+4.1461 5.37827
+1.08089 1.59196
+7.87513 8.21121
+7.85673 8.0973
+0.96237 1.56519
+2.45532 2.61678
+6.1829 6.23637
+0.135135 0.613518
+3.18324 3.78587
+5.64796 7.20194
+0.861169 1.71661
+9.66005 10.1169
+0.880774 1.12452
+1.29389 1.57658
+5.60299 5.89759
+5.53642 7.07306
+0.540268 1.31836
+6.60244 7.98105
+4.21877 4.57159
+3.15367 4.75356
+7.81055 8.40378
+8.00942 8.10861
+5.78071 6.35646
+3.15993 4.99293
+2.36526 2.78444
+8.1361 8.76071
+1.40066 2.96474
+-0.17906 1.05877
+5.94933 6.6808
+3.43187 4.05553
+3.02912 4.68942
+2.1506 2.29413
+2.3516 2.38305
+2.87496 3.0851
+6.71294 8.99858
+3.76177 5.52545
+1.58417 2.57063
+2.74646 4.27445
+5.48407 6.60696
+-0.133321 0.716559
+3.53886 3.58196
+2.28729 2.40198
+-0.209646 1.21263
+6.62795 7.32318
+0.714781 0.880466
+2.96831 4.05932
+6.00935 6.38896
+5.39798 6.11983
+8.47679 9.70468
+1.4339 1.74845
+2.35223 4.75732
+4.31357 4.9642
+5.26493 7.70538
+7.91888 8.94851
+6.51439 7.69469
+7.69015 7.85411
+3.94274 5.15373
+6.25852 7.32402
+2.73567 3.43236
+7.09564 8.42242
+2.55932 4.29066
+1.79489 1.84559
+8.86427 9.35669
+7.23854 8.27062
+7.8488 7.98307
+0.710888 2.22424
+0.0413624 1.10578
+1.54302 1.97696
+1.64924 3.01081
+8.15535 10.2397
+0.305662 1.63835
+8.20375 9.03123
+1.66617 2.08748
+4.01691 4.88505
+3.32856 4.10709
+5.15342 5.44616
+5.80751 7.38872
+0.485341 1.07648
+3.98267 4.20211
+6.96867 9.37655
+9.48055 9.85181
+8.39277 9.50424
+2.47589 2.79873
+3.48046 5.37417
+4.98279 6.01686
+1.29845 2.31199
+-0.204348 2.50289
+0.23488 1.00378
+6.26899 7.14823
+4.62903 5.49672
+0.199052 0.822066
+6.97297 7.69083
+4.23783 4.65198
+0.530497 0.839143
+6.61355 8.22831
+-0.0103941 2.16307
+0.148601 1.20044
+0.314438 0.67632
+3.43415 4.06208
+1.95498 3.25728
+4.23094 4.84942
+9.5493 10.0057
+2.64964 3.52073
+8.21388 9.1622
+-0.112496 0.47622
+7.97551 8.19546
+2.16155 2.6289
+0.38442 1.46032
+3.85675 3.91557
+1.00605 1.42016
+2.4853 3.53086
+-0.0765625 0.504366
+8.11302 8.46334
+7.18135 7.80218
+6.46466 8.12336
+3.75968 5.33954
+9.08789 9.73677
+6.47459 7.49454
+0.90148 1.47681
+3.44733 3.54163
+7.32968 7.909
+1.30055 2.75407
+8.78735 8.92461
+8.21764 8.59414
+0.888162 1.08404
+5.65195 6.26421
+6.23881 7.33284
+8.69731 9.88088
+3.55695 5.36909
+6.49248 7.02755
+2.31407 3.01952
+5.7803 6.1286
+6.30415 8.01577
+7.73864 8.27496
+0.741078 1.69184
+4.94671 5.68254
+3.28226 5.02894
+1.97446 2.60413
+3.26555 5.54754
+2.56179 3.41897
+3.20058 3.32486
+6.96915 7.69055
+6.89302 7.39856
+1.9659 2.61404
+1.31107 1.36867
+6.23573 6.33677
+0.17616 0.517772
+8.55548 8.79155
+9.61632 10.2651
+2.20331 2.34017
+6.93195 7.42939
+1.25398 2.23119
+1.06577 1.41048
+5.99156 7.09818
+3.34821 4.1271
+4.61618 6.90956
+2.30853 3.52875
+0.0518063 0.113732
+5.38513 6.09734
+1.73468 2.64838
+7.24679 7.63999
+4.18175 5.06728
+7.09602 7.13414
+9.06191 9.11605
+6.2309 7.67675
+3.96576 4.63237
+-0.552645 1.37948
+5.76964 6.89903
+4.9272 7.5832
+4.59003 6.49719
+4.12281 6.9664
+5.12256 5.58387
+1.78859 2.76954
+4.36808 5.05712
+8.41165 9.54483
+8.11513 8.43405
+8.42016 9.52715
+8.50598 9.34564
+1.80028 1.83558
+8.08502 8.43726
+6.96667 8.12021
+5.4726 6.26772
+7.1141 9.29989
+7.83324 8.1744
+8.74368 9.16491
+2.5515 3.01706
+5.92375 6.44495
+7.45628 8.41582
+9.04829 9.71503
+4.58856 4.75356
+7.26064 7.32462
+1.81695 2.40529
+6.88067 7.95052
+1.91408 2.02663
+1.32005 1.45025
+7.47733 8.42004
+4.99403 5.85297
+0.95744 2.28875
+-0.089503 0.536888
+1.09978 2.48865
+1.9959 3.098
+0.376116 0.448329
+3.98908 6.49684
+9.10178 9.51012
+5.41394 7.31529
+6.60708 7.59071
+4.38466 5.76203
+1.84355 2.60304
+0.658705 0.933522
+6.98725 7.05509
+5.60064 6.98804
+1.0603 1.1521
+4.06192 4.46156
+0.351018 1.00807
+9.17113 10.2192
+6.71641 6.74659
+8.85392 10.5272
+4.50816 5.22908
+1.13934 2.43196
+3.3746 3.57576
+7.62137 9.3234
+6.93482 7.16058
+5.66506 6.44324
+5.13364 5.86068
+1.97257 2.03803
+2.69746 2.73067
+0.989591 1.38342
+4.18819 4.69676
+4.31608 5.12265
+2.79556 4.87763
+3.55387 5.34421
+-0.112466 0.585639
+2.43156 2.70221
+5.88314 7.08322
+-0.450332 1.29858
+1.22202 2.46588
+6.74433 7.32925
+5.14596 5.37435
+6.76754 7.41799
+1.48762 2.45958
+4.57241 5.3382
+4.17465 5.02296
+6.48856 7.5576
+0.383566 0.823394
+8.50875 9.08734
+1.79393 2.24548
+5.06812 6.49508
+3.55364 3.61502
+5.58973 6.58885
+0.631097 2.10041
+0.323995 0.941782
+8.8798 10.1036
+6.37114 6.88202
+6.9393 7.83288
+3.09503 3.41759
+3.65269 3.70305
+5.61676 5.8924
+1.90199 2.38446
+4.23683 5.35609
+9.18649 9.88878
+8.28736 8.37734
+3.04805 5.03593
+8.02926 8.38975
+3.58161 4.01331
+3.20923 3.48207
+6.85118 8.78281
+5.06518 7.49843
+1.57456 3.05552
+3.0154 4.23782
+2.83557 3.24854
+1.29358 1.89328
+1.42911 2.72661
+3.17067 3.96651
+0.353554 1.48472
+3.46227 4.25611
+6.17639 7.24657
+5.60878 7.13562
+4.11129 5.52476
+9.17596 9.4123
+3.08339 3.65766
+4.083 4.63013
+0.628465 1.92141
+7.81989 8.39386
+3.35589 3.87531
+5.35974 5.41743
+4.48321 4.64376
+0.888177 1.37343
+8.49061 8.50063
+5.09078 6.01801
+9.65314 9.99342
+1.60502 3.0115
+1.37928 2.77642
+6.60322 8.94046
+6.74573 7.45157
+-0.291156 0.325249
+6.1518 6.66827
+5.38199 6.46959
+3.50128 5.22692
+1.31774 1.70159
+0.550546 1.48845
+7.51187 7.85496
+4.2014 5.23193
+3.88255 3.97209
+2.60555 2.84958
+5.15706 6.00036
+2.99284 3.27867
+0.395077 0.768383
+3.30863 3.60594
+0.0325231 0.379208
+6.55183 7.33346
+1.44554 2.95846
+0.245421 1.29751
+3.98808 5.41226
+5.90242 6.266
+4.11097 5.02597
+0.134753 0.929866
+0.609287 1.16311
+0.231832 1.06825
+6.22093 7.05584
+9.18429 9.80637
+0.544139 1.30185
+1.69143 2.90306
+6.75109 8.67893
+5.49641 6.76104
+8.91712 10.0271
+7.09126 8.12404
+8.82958 10.2847
+0.569249 0.69421
+3.59288 5.8053
+9.25068 9.4226
+8.51607 9.26259
+5.00906 5.17068
+1.83467 2.99102
+7.32006 7.64842
+0.405532 0.603773
+6.41882 6.60495
+0.721592 1.44375
+2.78393 4.46732
+7.14806 7.16117
+5.12868 5.27918
+2.74138 3.1737
+2.95394 4.26547
+7.82827 8.21028
+9.06982 10.7279
+0.108376 0.290131
+6.34574 6.97141
+4.39022 5.50801
+7.98339 8.79674
+3.80026 4.71831
+5.43594 5.66916
+1.6743 2.61476
+4.29763 5.47402
+7.95714 8.69311
+3.4152 3.7387
+8.01715 8.8941
+6.53723 7.44437
+-0.0222108 1.04503
+4.96242 6.01648
+1.70885 1.75511
+7.62434 8.53526
+6.82863 7.39782
+8.19967 9.22283
+1.99719 2.11323
+-0.0124079 0.240201
+4.48577 4.87935
+2.586 4.41666
+6.37848 6.67092
+4.39606 5.67983
+9.39761 10.1095
+7.10866 7.15796
+3.91993 4.52129
+5.10552 5.36997
+7.08963 8.32694
+9.12669 9.58509
+9.26894 10.1974
+0.737413 1.26523
+2.77833 5.28516
+3.19039 4.36857
+4.32954 5.45614
+4.98069 5.49295
+7.54745 8.76142
+5.70425 7.05749
+-0.250513 0.36578
+4.76997 5.89607
+2.03075 2.32111
+6.54141 6.55896
+4.19799 4.45091
+8.7796 9.11915
+5.75014 6.05646
+5.36885 5.42775
+-0.00433056 0.865304
+3.65169 5.4751
+0.23625 0.872926
+0.0386337 0.792214
+4.40245 4.56789
+6.44567 7.42162
+5.51394 5.98005
+3.50146 3.83147
+8.47573 9.85647
+7.91378 8.47044
+9.44297 9.90241
+5.962 6.68782
+4.49034 4.86927
+2.17774 3.47061
+8.80614 9.26595
+7.92096 8.13838
+7.80209 7.93317
+7.78915 8.29735
+6.98111 7.162
+0.491059 1.14901
+8.97965 9.38792
+3.30207 3.53207
+3.17127 4.43581
+3.97564 4.43746
+6.79008 7.17877
+5.61669 7.51263
+4.0853 5.38748
+4.42181 6.32041
+8.08599 8.9095
+2.46938 2.55499
+1.20692 2.06351
+1.98995 2.35216
+8.17116 9.17158
+7.53414 8.37086
+3.7744 4.46197
+3.29464 4.38
+7.33246 7.81959
+4.89572 6.2831
+-0.152496 1.56427
+0.636242 0.938556
+5.62066 6.06096
+9.42994 10.473
+8.95446 9.46311
+0.277891 2.80311
+6.92968 7.29845
+2.75677 3.02975
+2.2859 2.51308
+2.96683 3.03857
+6.44584 6.49518
+8.33607 8.60407
+7.20303 7.7616
+7.07205 7.46849
+2.35677 2.7904
+5.86404 6.12906
+2.42371 4.62735
+3.27237 4.11016
+0.0668578 0.644021
+6.77371 7.45187
+3.66596 5.21874
+0.718034 0.755944
+6.06162 7.05
+6.91473 7.09753
+5.0749 6.08914
+0.759874 1.11978
+8.54591 9.64997
+3.97266 4.70679
+1.51133 3.17164
+7.21772 7.69877
+8.00719 8.37052
+0.284003 0.38001
+4.08842 4.16227
+5.04461 5.79973
+4.60604 5.31979
+2.2461 2.28157
+6.25631 7.69766
+9.12404 9.67586
+7.73134 8.98923
+1.0513 1.46408
+9.17225 9.42567
+3.66795 4.29168
+8.84403 9.28497
+9.93613 9.94729
+3.16615 5.09374
+-0.149675 1.43397
+2.30855 2.48392
+0.843172 0.951801
+8.32945 8.8506
+8.97012 9.94697
+2.8559 2.92359
+-0.321715 0.89173
+7.48565 7.71775
+1.44301 1.47795
+6.6649 6.76187
+9.10721 9.93599
+1.82207 3.03935
+3.61893 4.5306
+2.53746 3.81243
+0.424528 1.29026
+9.51874 9.68841
+7.94954 8.14396
+7.49282 7.52655
+3.04604 3.69656
+9.45461 9.47212
+7.69209 8.16412
+0.607135 1.16564
+0.150291 0.450632
+3.28914 4.01085
+5.45597 6.02921
+8.16157 8.36605
+9.76573 10.2325
+0.151994 1.07074
+1.3748 1.68548
+2.29854 2.63593
+7.92162 8.68895
+1.28795 1.61949
+7.85469 8.26683
+4.32268 6.33174
+6.13964 6.3596
+1.25714 1.88002
+2.05006 2.28294
+8.31864 8.34151
+9.0613 10.0715
+-0.041568 0.25139
+6.79984 6.81686
+5.10674 5.70583
+5.92937 7.01652
+7.57649 8.05834
+0.937157 2.25362
+7.48567 7.59746
+2.33403 2.88942
+7.3805 7.73421
+5.586 5.75327
+0.828854 2.12988
+8.22741 8.59954
+9.69214 10.1207
+6.55359 7.08114
+1.85342 2.634
+6.08756 7.28893
+6.34993 6.93474
+8.93548 10.1463
+5.49445 5.8338
+1.47951 2.14646
+2.62089 2.75888
+2.35352 3.10539
+4.98774 5.28931
+4.92239 5.40697
+7.52674 8.78948
+4.52451 4.83819
+5.45854 5.75838
+5.51553 6.3901
+4.82905 6.44407
+6.20655 6.4483
+5.68116 7.06109
+7.97301 9.15827
+8.8854 9.91623
+9.60198 10.2449
+1.93322 2.67684
+0.441852 1.87646
+5.19981 5.71385
+2.54799 2.5809
+4.34591 5.02655
+7.54678 8.75202
+6.1496 7.19033
+1.13658 1.30756
+1.38724 2.08252
+2.13624 2.30419
+8.49196 9.41369
+-0.21387 0.685093
+2.47875 4.19982
+3.69093 4.00543
+5.70643 6.50331
+7.07443 8.83588
+6.85756 7.68937
+1.69241 1.83242
+0.140565 0.502156
+2.15007 3.23784
+4.97403 5.69757
+5.08315 6.25554
+3.45026 4.01942
+3.37482 4.73009
+7.4154 8.34013
+6.95399 7.59768
+8.07995 9.86199
+8.43993 8.88645
+7.66844 8.12742
+-0.0200687 0.435846
+4.47984 5.9416
+7.66804 10.0801
+4.14578 5.98717
+0.256533 0.89254
+6.43216 7.4474
+3.60295 4.79419
+3.90129 4.29812
+5.30606 5.58674
+9.11552 9.79229
+5.60702 5.85299
+2.39514 2.64865
+4.51164 4.60227
+6.31154 6.77441
+3.12239 3.13505
+7.50962 7.89478
+3.90928 4.88831
+9.64625 10.0629
+5.9465 6.02877
+2.08554 2.10477
+0.087547 0.34748
+2.34295 2.53703
+6.846 7.3043
+1.37869 2.11446
+4.03371 4.26278
+5.38623 6.40917
+4.75848 6.25417
+6.03478 6.15991
+-0.585543 1.2091
+2.52824 3.57712
+3.95687 5.40914
+4.42955 4.71909
+2.9328 3.98848
+5.40471 6.97056
+7.64789 9.30279
+6.19595 7.07492
+8.27328 9.41596
+8.29855 9.13665
+2.54035 3.10488
+8.25038 8.87903
+5.66599 5.88701
+7.40067 8.71195
+6.63762 6.67694
+-0.0163105 1.72666
+4.77743 6.60356
+0.567991 1.14977
+5.96841 6.42987
+3.02266 4.58424
+6.72121 7.35492
+7.51477 8.65223
+8.55055 8.81014
+5.59759 5.82816
+0.218944 1.82542
+1.03197 2.36652
+7.84302 9.1594
+2.11542 4.7332
+6.37618 6.92981
+1.34963 1.59353
+0.516281 1.08859
+-0.0151152 0.0624718
+6.45603 7.23063
+4.76865 5.46588
+7.5893 8.42021
+1.04534 1.99034
+2.62638 3.04997
+5.00254 5.98512
+7.7588 9.44547
+6.82186 7.34321
+8.7629 9.82272
+-0.309554 0.54858
+4.19843 4.92981
+5.62327 6.80846
+6.40599 7.6073
+6.1547 6.53898
+3.93941 4.44985
+3.28342 3.72778
+7.17256 7.23035
+2.31269 3.05437
+7.99132 8.20926
+7.19338 8.08381
+7.29139 7.96441
+4.25818 4.4208
+0.802894 0.81938
+0.990115 1.04066
+0.443898 0.490936
+3.44459 3.95977
+9.07812 10.3145
+7.86709 8.26338
+-0.230114 0.390748
+7.50905 8.49199
+-0.715424 1.97535
+2.92248 3.12903
+5.44209 6.62431
+0.991914 1.99037
+5.92275 6.7724
+9.10818 9.2797
+4.46434 4.83462
+4.21122 5.48353
+1.8721 3.40764
+7.04713 7.60526
+3.76581 4.76317
+7.00667 7.36475
+6.87244 7.39431
+7.6349 8.46695
+-0.0728922 0.351194
+5.02925 5.6834
+1.45779 2.83702
+0.339175 1.46574
+6.40414 6.9165
+6.30401 6.91007
+5.6392 5.78172
+5.63288 6.44639
+7.45285 8.89031
+4.09741 4.57929
+8.76728 9.06448
+1.62324 1.84552
+5.72509 6.54553
+8.65273 10.3652
+7.3362 7.8953
+8.96224 10.3113
+0.217316 1.7827
+1.28523 2.90127
+8.78746 9.11602
+8.6075 9.9606
+-0.647788 0.779976
+4.9702 5.47602
+4.15553 4.57497
+1.08174 2.80993
+4.01011 4.8145
+6.79603 7.2317
+4.3711 4.43566
+9.65087 9.79922
+8.19407 9.21784
+3.04008 4.94094
+6.0883 7.23919
+6.88708 6.97172
+0.438073 2.00665
+8.53083 8.83004
+4.22258 4.65233
+6.72856 7.61085
+3.17591 3.18978
+5.07955 5.6938
+2.09043 2.55351
+3.28085 4.43556
+7.29225 8.03925
+7.78034 7.82608
+6.59677 7.67719
+5.56032 6.38139
+8.72663 8.82535
+2.96505 3.11983
+1.67192 2.11727
+7.85386 8.49025
+6.30965 6.72799
+8.53082 9.3801
+2.8976 3.39972
+8.90427 9.44661
+-0.0665785 0.410254
+4.58099 5.81135
+1.88015 2.21838
+3.38693 4.10149
+7.46378 7.68246
+8.80985 9.72212
+6.54877 7.25642
+7.18249 7.71509
+7.41978 8.64805
+1.00839 1.78626
+0.39421 0.526751
+7.13516 7.28317
+7.28011 7.80573
+1.90158 2.49032
+1.66181 4.17994
+8.81106 9.21133
+9.46151 10.5007
+0.52585 0.575082
+7.66495 8.64072
+7.72794 8.50991
+4.92409 6.23879
+2.28769 3.21774
+3.62671 4.40932
+5.77688 7.31314
+8.94253 10.0664
+0.416618 0.635111
+1.81377 2.41356
+7.91755 8.83363
+1.62715 1.82626
+8.22065 9.51656
+0.020228 0.724724
+8.81119 9.95764
+8.66509 9.61079
+5.28201 5.32152
+3.95724 4.22138
+7.09339 7.77685
+9.63428 10.1514
+3.69117 3.779
+3.82195 4.76757
+5.75824 6.62265
+3.69984 4.75163
+3.58259 4.8788
+8.32635 8.85873
+5.81959 7.32506
+8.11265 9.14304
+2.20118 3.32511
+7.79582 8.52691
+6.5891 7.13584
+0.385393 0.440656
+1.13414 1.9951
+1.76482 2.69977
+4.76194 5.82757
+6.33633 7.5348
+4.7663 5.65083
+1.98298 3.01285
+0.956973 2.38629
+5.60955 7.65827
+9.11064 9.14351
+2.99933 3.37975
+3.36304 4.57437
+3.89886 4.50733
+8.73838 9.3514
+9.11824 9.66042
+1.47961 2.93909
+0.615297 1.13217
+1.70646 2.32478
+4.35168 4.99362
+0.986601 1.18332
+4.01551 4.92342
+7.68944 9.86838
+4.47611 4.85316
+0.051839 0.86288
+3.59624 5.5628
+7.08729 8.90374
+9.53464 9.9196
+4.69871 5.74189
+8.43146 10.6889
+3.23774 3.77777
+9.35399 9.62741
+1.15259 2.69451
+6.6368 7.33773
+5.26395 6.09857
+6.87415 7.21717
+-0.925645 1.06118
+8.49641 8.67659
+2.31486 3.25354
+2.51057 2.58303
+0.921997 1.48762
+6.29777 6.74738
+4.03945 4.27305
+7.1668 7.3471
+8.44572 8.80343
+7.16937 7.84526
+8.89008 9.4332
+7.01815 7.66319
+-0.420804 0.982878
+1.59755 1.64672
+0.700814 0.72579
+6.3138 7.37379
+8.49276 9.93522
+-0.795656 0.819657
+0.772253 1.05926
+0.917593 1.3917
+3.30076 4.12274
+-0.0237176 0.260552
+6.82385 7.49119
+6.98638 7.52012
+8.24915 9.08397
+4.17486 4.25908
+3.08435 4.64404
+8.17114 9.91412
+8.95923 9.3751
+0.596707 1.89462
+0.982917 1.40236
+6.79552 7.36657
+8.2599 9.69551
+8.85126 10.4342
+7.98967 9.14514
+0.766355 1.63286
+7.76211 7.99247
+5.23163 5.89338
+4.4707 5.50457
+9.257 9.27862
+2.11049 2.59654
+1.65501 2.06238
+0.551768 2.10873
+0.0285582 0.194421
+3.66153 3.85615
+5.07097 5.55806
+5.29145 5.80735
+2.03499 3.0863
+0.73171 2.29494
+2.63023 3.6417
+6.17478 6.25997
+5.79646 6.46363
+9.10633 10.5516
+7.23415 7.84823
+6.49951 7.1506
+9.94647 10.0242
+7.91236 8.09097
+7.8127 7.97662
+3.34238 3.42907
+8.50796 9.8311
+8.75792 8.98028
+9.34125 10.4441
+2.84413 3.71602
+1.49884 2.35652
+7.52317 9.18955
+9.5587 10.3525
+4.85436 6.1181
+5.91369 6.12194
+6.88463 8.34471
+1.51952 2.99156
+4.29022 5.12674
+8.0229 8.41246
+2.44841 3.04779
+7.59975 7.91485
+2.74491 3.62575
+0.0169968 0.240919
+5.85351 6.29039
+4.99825 5.93439
+2.153 3.35304
+1.19032 1.41763
+6.13337 7.80615
+7.05013 7.89364
+8.38056 9.92
+6.35525 6.64521
+3.93342 5.15885
+2.87656 3.47116
+3.56176 4.41159
+6.72084 7.9171
+8.03801 9.12442
+1.03329 2.56255
+7.64542 8.61709
+2.85627 2.89437
+8.8303 9.79838
+1.08032 2.34573
+7.51366 8.39169
+9.09685 10.3677
+6.753 7.41904
+-0.217662 1.42059
+6.72492 7.97553
+7.99325 8.8976
+0.765372 1.10894
+4.37958 6.04671
+8.72027 9.58928
+6.00234 7.29277
+8.43912 9.25356
+2.98816 3.17389
+0.4292 0.552167
+1.69827 2.80318
+5.99904 7.09981
+4.68367 5.87791
+-0.203208 1.09587
+2.65367 3.28472
+3.87051 3.88111
+6.36178 7.18853
+-0.0815935 0.200848
+6.82255 7.18488
+4.99295 5.08405
+2.67155 3.08447
+5.82099 6.77145
+8.76434 9.01086
+5.94982 6.18665
+3.23369 3.71743
+0.934129 2.73456
+1.13233 1.24208
+8.21931 9.03906
+6.25425 6.69972
+0.971299 4.21205
+5.68426 6.45281
+2.85786 3.3955
+8.17715 8.88439
+2.72802 5.01235
+6.12811 6.53711
+5.22878 6.45864
+0.453655 0.922032
+0.466162 0.85262
+2.40916 2.64759
+5.63583 6.37476
+2.18434 3.14105
+0.912811 2.08432
+8.9464 10.1515
+6.77323 7.27133
+0.7167 1.60579
+5.89813 6.32997
+7.66593 8.4611
+6.54145 6.88337
+5.95421 6.21188
+1.10383 1.92226
+5.37168 5.65707
+1.51874 1.66339
+4.60748 5.00384
+8.97354 10.5394
+2.05022 3.20373
+8.17316 8.19283
+2.33792 2.72643
+8.81577 9.3704
+5.95738 6.59855
+5.69025 6.17335
+6.91889 7.88142
+2.17529 2.81528
+6.65046 7.19698
+7.10694 8.78046
+2.09613 2.47484
+1.92423 2.25333
+-0.0906039 0.861376
+6.61481 7.70609
+6.7448 6.84276
+3.43655 5.28405
+6.05404 6.48902
+3.24637 3.36149
+5.69528 5.77157
+5.12352 5.31024
+7.65858 8.80828
+3.69209 4.4851
+0.25765 1.29637
+3.1537 4.13191
+3.12328 3.83765
+2.99798 4.8748
+4.49566 4.67827
+3.50822 4.03987
+8.00334 8.34084
+8.61039 9.00704
+0.0332147 0.166124
+4.55193 5.36546
+4.20308 4.31589
+0.955466 1.20095
+-0.382972 1.47625
+0.803913 1.01916
+3.78333 4.0707
+6.58604 6.70173
+3.02066 3.82562
+1.16515 2.2816
+7.87242 8.24214
+4.057 4.60368
+2.84714 3.59726
+2.77804 3.69136
+-0.139996 1.36416
+4.50647 6.37579
+8.86647 10.1549
+9.24372 10.1442
+0.743107 1.84722
+6.18761 7.65841
+0.214887 0.443938
+8.8513 9.55063
+4.04856 5.79916
+6.69671 7.10025
+6.97477 7.79702
+4.82551 5.10538
+0.821772 2.85828
+9.3086 9.74805
+5.45623 6.66668
+7.64296 8.67451
+7.53052 8.31024
+7.45352 7.5063
+1.31412 1.4979
+7.81176 8.48083
+0.228964 1.73207
+5.52579 5.93103
+6.58544 8.48938
+2.75407 4.18746
+3.21396 3.96298
+1.13806 2.34106
+0.899331 2.87945
+5.69016 6.61624
+2.48172 2.58082
+0.676004 1.43405
+3.41766 3.9503
+0.104554 0.298373
+6.50673 8.21831
+6.00349 6.69385
+9.62453 10.3147
+4.09379 6.02911
+-1.12803 1.68823
+1.83324 3.43133
+8.30576 9.09288
+-0.363911 0.405218
+1.91686 3.34928
+6.98331 7.15885
+-0.31591 0.996789
+0.145813 0.35408
+5.32016 6.13679
+6.99664 7.48644
+-0.140875 0.821045
+9.0119 9.19742
+1.69616 1.72453
+4.38064 5.07542
+6.85898 7.55478
+3.9145 4.27935
+5.77592 6.16806
+1.45345 3.01301
+4.13024 5.59662
+8.14557 8.41669
+4.00075 4.829
+-0.283024 1.59436
+5.92468 7.17507
+6.84458 7.18356
+1.06987 1.42839
+8.618 8.66235
+0.432802 1.59512
+3.78058 4.36051
+1.6113 4.21135
+6.73475 7.01057
+6.74819 6.90498
+6.93146 8.54681
+9.02605 9.91613
+3.888 4.00526
+1.07958 2.27915
+4.78456 5.10764
+3.92952 4.89555
+9.09348 9.30304
+6.73107 7.21036
+7.42366 7.73225
+4.04079 4.72919
+1.21726 1.34683
+8.82903 9.73504
+0.577663 1.00786
+1.56822 2.08675
+4.84315 5.44994
+1.01008 1.16524
+5.99782 6.01535
+0.996739 1.75305
+4.76128 6.39012
+8.93563 9.51972
+-0.0698166 0.453543
+5.9084 6.95139
+0.535401 0.692258
+4.80729 5.48335
+3.42581 4.76147
+3.58715 4.43541
+7.50236 7.71227
+5.19742 5.87901
+1.79752 2.43097
+7.29762 7.57608
+5.65169 6.47762
+6.02249 7.93642
+0.840131 2.81176
+6.2646 6.96911
+7.46014 8.17136
+9.79049 9.94054
+4.61094 5.35819
+7.30902 7.41873
+1.21883 1.84621
+6.41743 6.57736
+1.53114 1.62859
+6.73237 7.47083
+6.05618 7.56831
+7.63374 8.16821
+5.20839 6.05382
+0.619043 1.44065
+2.38657 4.88786
+3.88289 5.18788
+4.42283 4.51106
+9.15575 9.22388
+3.18678 3.72243
+3.20638 3.65935
+4.2219 4.97961
+4.63725 6.90959
+2.57123 2.59101
+4.08581 4.37325
+6.53926 6.80412
+1.77475 3.89149
+9.22854 10.426
+2.67375 4.36551
+3.17194 4.0433
+1.10304 2.0348
+3.67233 4.04957
+3.23526 3.5012
+5.17684 6.47301
+4.4 4.67662
+4.15842 5.85903
+5.88496 6.61616
+7.26489 7.51279
+4.17402 6.6997
+-0.540216 0.54573
+4.36063 4.60442
+9.18146 9.96239
+0.977216 2.42032
+9.09143 9.61178
+5.06686 6.23076
+2.04772 2.92048
+1.4154 2.00707
+7.80442 9.54824
+4.55549 4.7148
+7.56964 8.80172
+1.35347 3.21648
+9.12751 10.0605
+1.81735 2.06061
+5.63798 8.0918
+6.79492 7.98002
+9.23053 10.1299
+1.74639 2.02724
+3.71825 4.09879
+2.4995 3.42493
+4.1255 5.66758
+4.75493 6.99687
+8.22481 8.72036
+6.13689 7.53026
+5.41315 5.66358
+4.21425 5.62743
+6.22936 6.44392
+2.02303 2.96414
+-0.0655462 0.130508
+6.1487 6.70994
+4.36674 6.24985
+7.51129 7.63176
+7.9729 8.98613
+3.92117 4.15596
+4.54398 5.43399
+6.34248 6.92305
+-0.550253 1.16167
+9.15142 9.53717
+8.99354 9.65952
+6.28988 7.90053
+3.36505 3.782
+8.80005 9.70553
+1.99947 2.18573
+1.15023 2.07069
+0.253723 1.32958
+2.0392 2.93977
+2.89024 3.00836
+8.16735 8.2049
+1.49508 2.95258
+6.19092 7.44552
+2.33328 3.06758
+6.44166 7.4649
+7.34749 7.79488
+7.5557 8.04141
+2.76812 5.13617
+7.97308 9.25668
+4.73539 5.22234
+7.53377 8.41651
+-0.355405 1.36499
+4.72111 4.73744
+-1.22753 1.84842
+5.5033 5.63808
+3.95421 4.19313
+6.24752 6.98229
+4.49694 5.07277
+3.70871 4.30093
+1.31984 1.50116
+7.16044 8.70868
+2.44587 3.34659
+6.08322 7.20376
+2.75012 2.82555
+0.0394442 0.863634
+3.90896 4.73696
+4.77494 5.04158
+8.41473 8.82932
+1.7049 2.71024
+9.01684 10.1044
+4.57959 5.01066
+3.2484 4.21875
+1.11596 2.88792
+3.53616 4.14001
+5.80672 5.82478
+5.85844 7.70293
+6.18239 6.30124
+2.22913 3.23412
+2.97521 3.08481
+2.2749 3.70611
+2.3457 3.86609
+2.71695 4.04473
+7.22863 7.40115
+1.80428 2.39815
+1.80781 2.33028
+2.78662 3.14936
+9.40717 9.94906
+6.54968 6.80773
+2.76862 3.24492
+1.96034 2.87404
+3.53295 3.54927
+5.36042 5.67073
+8.63339 8.93752
+0.932415 1.70402
+4.32923 4.55594
+9.3491 10.4969
+0.121416 1.15499
+-0.172998 1.36319
+2.02349 2.29887
+1.75352 2.35329
+0.502555 2.01665
+6.71754 6.80014
+3.35175 3.93337
+7.17133 7.9851
+8.51299 9.95771
+5.86103 6.36734
+1.44593 3.46008
+4.49699 4.60855
+2.29261 3.10053
+6.68713 8.19499
+5.43776 6.84387
+8.58591 9.02134
+5.24746 6.15595
+1.3847 2.5074
+6.62143 7.07775
+1.7101 2.077
+9.70898 10.2789
+6.67451 7.92058
+2.56858 3.60374
+1.61917 2.60482
+1.77902 2.16908
+4.76209 6.00461
+3.8894 3.98269
+7.0278 7.276
+5.4866 5.59417
+1.69306 2.92506
+2.45744 3.76592
+2.5689 2.80611
+5.98283 6.06154
+9.5267 9.9626
+9.55652 10.4128
+6.6111 6.64606
+3.38826 4.26111
+3.61887 3.73455
+4.14924 6.13796
+7.15863 7.28212
+5.78984 6.56662
+2.09304 2.2681
+4.39867 4.88557
+6.20907 6.81034
+4.63336 4.91476
+0.939805 2.43621
+1.56774 5.13599
+8.40908 9.82058
+2.06273 2.20306
+2.53524 5.01482
+2.9314 3.23661
+2.48535 3.47368
+0.366389 1.4699
+8.81131 9.01654
+2.05102 2.87972
+1.9699 2.22723
+6.18333 6.98224
+1.3425 2.4443
+0.767883 1.77423
+3.1538 3.43248
+0.891006 0.903458
+5.7136 5.8713
+0.437569 1.37539
+3.98533 5.01646
+8.65764 9.89518
+3.74889 3.98561
+7.74507 8.30657
+8.24671 8.43006
+6.88467 7.42036
+1.99426 2.03522
+1.90486 2.04181
+1.12911 1.71807
+9.25253 10.105
+1.92989 2.0346
+5.60044 6.25585
+9.16848 10.087
+6.67824 6.72257
+1.88522 2.80222
+0.242758 0.852689
+5.09249 7.71484
+5.54974 6.44414
+7.66767 8.72936
+3.48884 3.83156
+3.4697 5.14646
+8.48582 8.7692
+6.76259 7.06897
+7.83856 8.62005
+5.81853 6.76571
+2.04803 2.94439
+6.85396 7.22985
+6.52449 7.39764
+9.26838 9.34809
+4.64449 5.64975
+7.51845 7.80279
+-1.27268 1.65344
+0.686101 4.20373
+7.80552 8.37119
+7.20419 8.35284
+9.33962 9.87975
+4.31238 5.58683
+2.39198 3.84398
+1.29248 2.59269
+4.71612 6.195
+5.27332 6.52174
+7.71492 7.84702
+8.18064 8.72233
+1.55223 2.31294
+6.34374 7.31758
+6.48966 6.92611
+2.62268 3.09895
+4.09064 5.06197
+2.66367 4.12126
+1.53391 2.93092
+8.64516 8.70655
+9.20047 9.28957
+4.00474 4.11716
+8.5418 9.45901
+8.73386 9.73253
+9.22596 9.63179
+1.34204 2.7834
+8.4489 9.21027
+7.75158 8.51085
+5.98856 6.11212
+1.29906 2.08111
+9.24315 9.76291
+6.84345 6.91607
+5.88294 5.90545
+3.03022 3.39941
+3.22222 3.4089
+1.12791 1.65898
+6.70232 7.36336
+8.60042 8.82377
+1.26451 1.30362
+2.76682 2.92693
+1.54763 2.19582
+6.5865 7.24173
+4.15242 4.21742
+8.39615 8.78524
+1.67017 2.08717
+9.03012 9.97041
+2.31463 2.45877
+8.29872 8.51813
+1.66689 2.51919
+-0.807606 1.47794
+1.31452 1.94418
+0.0739222 0.512106
+4.23577 4.25889
+7.45273 7.97505
+3.34234 3.46608
+7.97304 9.14131
+1.9029 2.99946
+8.84087 9.79689
+4.92769 5.68685
+2.74004 3.04513
+0.889257 2.20448
+3.10574 3.9758
+3.91547 4.32303
+7.17475 8.07377
+5.92903 8.03738
+1.57974 1.65527
+3.76339 4.2285
+2.28263 2.7559
+9.53105 9.87477
+2.10154 3.2222
+4.23683 5.34347
+1.38769 2.48482
+5.39838 5.51872
+8.50975 10.1382
+8.04108 9.21474
+8.5252 9.67823
+8.893 10.7726
+7.1294 8.18211
+1.15642 1.73882
+0.436911 0.756698
+3.66142 3.71659
+6.37686 6.7
+8.88506 8.99896
+2.31891 3.79061
+2.61615 2.81909
+1.35216 1.39571
+3.04217 3.52564
+7.8409 9.34099
+0.470596 1.49157
+6.94014 7.18365
+8.05483 8.49979
+8.18511 8.25608
+7.03597 8.45251
+2.47411 2.65172
+0.112716 0.193057
+4.45039 5.10584
+4.53906 5.80013
+5.11702 5.27151
+1.24211 1.90757
+4.64114 4.72912
+1.77254 3.45037
+-0.1275 0.99675
+5.69637 7.67722
+2.21252 2.44032
+3.89623 4.40192
+2.79904 3.15569
+8.37911 9.42424
+5.27199 6.2026
+1.84791 3.75411
+0.522801 0.54806
+3.83644 4.64785
+6.65497 7.55638
+6.75104 6.98564
+2.34979 2.98049
+8.27176 8.60459
+5.07773 5.44064
+1.16934 1.98872
+4.2914 5.37557
+6.83462 7.95408
+3.91405 5.73229
+7.77473 8.53538
+9.23441 9.90185
+4.03659 5.2473
+5.99336 7.8004
+4.2432 5.89276
+6.39847 7.81276
+9.13909 10.4164
+1.12009 2.5649
+2.35157 3.18468
+4.46918 5.55572
+3.82512 5.53666
+7.18238 8.10193
+8.40911 9.23639
+8.99555 10.4192
+6.69547 8.87825
+4.79012 5.34858
+9.23615 10.0986
+-0.590587 1.14603
+2.74289 3.48244
+-0.248403 1.1591
+3.35663 3.7229
+7.37504 7.6481
+6.64796 7.64695
+0.778081 2.41212
+4.49242 4.7772
+8.01419 8.109
+6.6494 7.76619
+8.86331 10.1205
+0.817273 0.937855
+8.00019 8.21556
+6.19405 6.54794
+6.11798 7.30421
+3.40164 4.28921
+5.31927 6.21584
+2.79377 3.40938
+3.59494 3.90321
+7.79218 10.3132
+2.99546 3.86111
+1.71916 3.40283
+6.1768 6.81915
+7.59629 8.68568
+1.59724 2.348
+6.20151 6.5391
+6.30798 6.70478
+0.489786 1.51322
+1.28396 1.86775
+5.18031 5.43007
+6.61276 7.70565
+1.4909 2.11165
+4.56163 5.49277
+1.93598 4.35147
+3.65568 5.00224
+1.68028 2.00363
+7.82874 8.67399
+1.23053 2.87598
+-0.164275 0.194491
+2.58349 4.01302
+1.23279 2.02984
+0.599702 1.09257
+9.50965 9.80164
+2.33108 3.58037
+4.38659 4.62378
+2.65097 2.87349
+0.0537058 0.576502
+4.20415 5.15693
+5.41458 5.98382
+4.37747 5.10347
+2.62536 2.70073
+6.96845 8.15356
+6.91533 8.41638
+9.36431 9.58863
+6.13019 7.25915
+2.7818 3.4951
+9.44641 10.1301
+2.68817 4.19772
+5.65664 5.6814
+8.25308 10.498
+3.50374 3.64458
+1.47063 1.78567
+8.21901 8.98152
+3.99261 4.47339
+2.51395 3.38788
+4.66178 5.24959
+9.08415 10.3467
+5.92351 7.20447
+1.74145 2.35957
+7.62653 8.96797
+6.43542 7.68775
+5.49047 6.56355
+4.9225 6.22555
+0.257967 0.704837
+3.42488 3.52873
+8.67606 9.77824
+5.12981 6.37856
+5.97359 6.32151
+1.58517 2.28129
+0.530687 1.54545
+7.04056 8.15296
+1.8541 3.1902
+9.46286 10.0098
+3.17967 4.02237
+3.49966 3.80271
+6.24894 6.49618
+1.19944 1.59215
+5.30422 6.94823
+7.49137 7.78584
+7.02669 8.16282
+2.21673 3.36471
+7.66183 8.34763
+4.13876 4.87421
+3.0199 4.07124
+8.40439 8.82943
+-0.274649 0.429602
+6.11215 7.65609
+3.34781 5.03006
+1.28231 1.77258
+7.57256 8.59456
+5.36208 5.81735
+7.18511 8.96618
+8.86053 9.49567
+5.39097 5.93211
+6.59094 7.26553
+3.69159 4.01914
+8.73797 8.81611
+1.41144 1.82827
+7.83555 8.07567
+6.13821 8.44907
+5.83432 6.48744
+2.93596 4.66271
+7.03215 7.59658
+1.65252 2.45337
+2.91358 4.90129
+8.94415 9.14642
+5.21005 6.1166
+0.33225 1.17039
+7.40089 8.07586
+9.30427 9.40776
+2.34188 2.81124
+1.02811 3.3344
+6.28117 7.62089
+4.80105 7.10049
+8.90252 10.0057
+2.20932 2.33093
+8.20746 10.6268
+4.31887 5.23945
+9.258 9.8985
+3.80742 4.15057
+1.11313 1.23711
+9.53067 9.70165
+7.95467 8.67187
+9.66031 9.83223
+3.61385 4.09571
+0.623148 0.652817
+7.77809 8.62118
+0.86157 1.98606
+3.12528 3.75815
+1.9363 3.22621
+8.23521 8.99175
+8.95406 10.4487
+3.38526 3.90652
+0.34281 2.0226
+0.739384 0.793829
+3.55637 3.96384
+6.1562 7.28647
+5.30211 7.51385
+1.46275 1.78688
+-0.0144662 0.868488
+0.0740443 0.119828
+9.26206 9.83923
+0.743397 1.40754
+4.68823 6.62985
+8.8291 9.17373
+4.66711 5.09313
+4.023 4.44994
+5.68937 5.79194
+8.04835 8.06763
+6.94662 8.00075
+0.774686 1.13428
+0.381819 2.34757
+2.1235 2.63524
+5.42795 6.89998
+6.07662 6.29083
+6.47821 6.7872
+2.58305 2.6192
+-0.598336 1.23458
+4.29089 5.43332
+8.09914 8.28229
+5.05925 5.35258
+0.181705 0.444466
+3.27849 4.79932
+0.310314 1.43125
+1.13836 2.76825
+1.2529 4.09336
+0.198106 0.608625
+1.77442 2.23777
+6.29823 6.64574
+1.22125 1.37929
+1.77592 3.04011
+1.43999 2.90926
+4.20495 5.32396
+4.98874 5.33211
+8.36483 8.67875
+5.65373 7.14132
+2.8303 3.05037
+3.41509 3.54032
+7.21702 7.85857
+5.79848 5.8913
+4.52711 5.65511
+2.04663 2.66919
+5.76363 6.77903
+-0.153046 0.77878
+4.37474 4.49936
+6.86786 7.81999
+8.92084 9.16368
+7.5975 8.56954
+0.197493 1.07503
+3.99803 4.67019
+9.35123 9.60094
+1.46442 2.4256
+5.21501 5.79612
+8.80879 8.99085
+-0.109252 1.30631
+7.34965 7.87947
+7.08703 8.12723
+0.985946 2.14663
+0.48521 0.856118
+6.57719 6.70623
+8.71165 8.72286
+3.16883 4.8714
+-0.21189 0.412944
+3.6526 4.37121
+0.364649 1.3363
+9.27722 9.35135
+3.47517 3.8793
+5.67149 6.28631
+6.52789 6.61039
+9.36323 10.4189
+4.30743 6.18638
+7.93653 9.4877
+8.24024 8.41475
+2.75692 3.13935
+8.80223 9.1489
+3.42656 3.90557
+8.96598 9.3217
+1.99582 4.84803
+5.1178 5.8688
+4.47901 5.73433
+7.30397 7.85527
+0.18463 0.656832
+7.80806 8.41666
+8.50023 9.42628
+7.67563 8.64756
+9.46783 9.52169
+2.06797 3.3107
+5.08863 5.10167
+0.82146 1.39055
+7.5428 8.04736
+9.09407 10.8208
+9.15219 9.99706
+1.61637 3.46354
+5.3812 5.96247
+9.34115 9.73575
+6.49221 7.30031
+1.56337 3.39704
+8.463 8.60841
+-0.322779 0.658242
+8.50173 8.72125
+0.854851 1.83405
+7.81945 8.12841
+2.60724 3.19985
+5.03714 5.55331
+1.85041 3.36816
+7.26119 7.64364
+5.75223 5.99653
+4.00026 4.43863
+5.00939 6.03009
+6.22879 6.6638
+6.44231 7.18622
+1.66002 1.88587
+2.59781 2.84919
+4.96399 5.40545
+5.70327 6.95018
+6.97141 7.08346
+3.98535 4.6179
+5.96795 7.14997
+5.07581 5.8262
+4.65665 4.98851
+8.65646 8.70986
+3.04175 3.19155
+0.796073 1.0952
+8.24859 8.57828
+5.26952 6.34245
+7.94685 8.78542
+0.193963 0.968524
+6.61159 6.80186
+9.37533 9.79195
+8.94048 9.74959
+5.77272 6.48616
+6.0092 7.86718
+2.52621 2.58938
+8.91347 9.22421
+4.20466 5.45909
+4.82157 5.09167
+7.35464 7.36611
+5.12413 6.45063
+2.12404 2.81187
+8.88875 9.20752
+2.59731 3.20587
+1.54772 2.08968
+6.70449 7.08952
+-0.0967146 0.888521
+3.10207 4.34815
+1.20807 2.35497
+6.00753 6.08492
+3.21837 4.00446
+4.34095 6.0963
+4.24821 4.79576
+4.49523 6.6669
+1.49483 2.52552
+0.0411497 0.641526
+8.3854 9.20954
+8.12419 8.93702
+0.0201515 1.06914
+1.57617 3.44176
+1.4173 1.76847
+5.42261 6.51539
+6.6744 8.46109
+3.05234 3.59179
+6.49059 7.24618
+7.01989 7.69901
+2.34664 2.90601
+9.17324 9.86754
+5.50919 5.70258
+2.40486 4.6009
+3.74368 4.00093
+6.9211 7.33554
+7.41358 8.7413
+8.78284 9.62033
+2.96753 3.01602
+-0.200693 0.535532
+6.4383 6.45049
+8.28835 9.42148
+4.2379 5.35128
+4.68397 5.04593
+5.7185 7.03177
+5.37494 6.43977
+2.99518 4.08138
+7.28064 7.54638
+9.10622 10.4907
+1.23839 1.50915
+6.7823 9.24533
+8.45679 8.62427
+0.106718 0.69304
+2.84119 3.50375
+3.60466 4.51338
+8.04709 8.19023
+3.31632 3.48054
+5.9027 7.46331
+-0.621072 1.13003
+8.57167 8.69262
+0.301047 1.42246
+1.24229 2.44616
+0.962706 1.55754
+8.77327 9.55275
+1.77899 2.44335
+0.368575 1.84726
+9.05918 9.07832
+6.61723 7.68015
+8.59899 8.80383
+-0.133927 0.20271
+5.69266 5.74809
+0.68202 1.52342
+7.17359 7.91482
+5.74049 7.34297
+7.88371 7.9683
+1.58749 2.26543
+3.96728 4.45988
+5.4354 6.88336
+1.68706 1.6976
+6.56907 7.40696
+0.518151 0.724124
+8.99155 9.36995
+6.00506 7.91529
+5.26967 6.11536
+2.37416 2.50887
+8.47983 9.31509
+2.38155 2.54346
+8.08415 9.65214
+1.00693 3.19203
+1.6523 1.73553
+6.85283 6.9958
+4.11425 4.90193
+1.39597 1.58725
+5.05551 5.19458
+5.89969 6.11394
+5.9148 7.26824
+9.32271 9.93989
+1.62911 2.58215
+5.43399 6.14203
+3.11393 3.58792
+8.57619 9.3788
+2.23349 2.7884
+8.09022 8.54326
+9.7114 9.87076
+5.91086 6.10885
+7.35805 7.57276
+0.650002 0.879866
+3.24977 3.75531
+2.73948 3.41051
+3.08006 4.62772
+3.71868 4.31519
+4.13905 5.78577
+1.77297 3.02983
+5.85931 5.89333
+3.68972 3.93193
+1.43922 2.98425
+6.51534 8.33386
+6.6821 7.50874
+1.2541 2.11722
+5.40634 5.54411
+4.55502 4.60346
+4.32484 4.68497
+3.40711 4.31975
+9.20893 10.0853
+6.12594 6.9009
+0.12664 0.347193
+7.53378 8.82258
+7.79572 8.91645
+2.50098 3.39701
+4.17873 4.97732
+1.05822 2.47032
+3.1012 4.97736
+8.42126 8.74568
+7.83301 8.17843
+9.26618 10.584
+3.02667 3.7128
+8.30654 8.69242
+2.87173 3.43275
+6.59917 7.54843
+7.03447 8.20283
+5.75718 6.40637
+2.62899 4.1855
+-0.520148 0.902194
+5.1538 5.61763
+1.25625 2.33142
+4.16336 4.3384
+3.01296 3.41026
+3.16515 3.26305
+2.40944 3.21897
+6.80742 8.57141
+1.15125 1.54824
+8.72251 9.50878
+3.15703 4.04482
+0.470308 0.726093
+0.199979 0.878243
+7.8908 9.17915
+6.91793 7.16038
+4.64783 5.00217
+2.21237 3.03073
+1.5825 1.63362
+3.18806 5.20795
+5.92725 5.95595
+4.65027 5.09868
+6.42204 6.87201
+8.08637 9.40221
+4.95542 6.16185
+7.45987 7.57979
+8.826 9.13961
+4.42078 5.27977
+7.26216 8.97585
+2.26919 3.33512
+9.4077 9.81908
+0.722223 1.03378
+-0.0497795 1.19355
+8.22686 9.31082
+0.0733766 0.93037
+7.47883 7.9062
+5.28731 5.74181
+1.78496 3.61348
+0.690987 0.764344
+2.56442 3.54999
+4.27944 5.43124
+4.04412 5.35376
+0.663756 1.88268
+1.73567 1.78553
+8.07666 9.41842
+7.70138 8.42873
+9.27113 9.55873
+0.982413 2.5565
+0.994807 1.02007
+5.01226 5.31923
+8.87435 10.0597
+1.74836 3.22578
+0.151528 0.191719
+5.82608 6.06438
+1.17239 1.59955
+3.18515 4.11049
+1.92258 3.70604
+1.63692 1.8266
+1.83542 2.66228
+2.21954 3.11425
+3.97546 4.3928
+0.731374 2.05705
+5.44809 5.96359
+9.85934 10.0553
+8.42169 9.63654
+6.68148 8.43446
+2.00014 3.3485
+0.735924 1.73
+1.61833 3.05643
+7.87934 8.67316
+8.67441 10.0032
+0.794573 1.2493
+6.11926 6.41441
+5.2715 5.82597
+9.41854 9.46625
+3.46299 4.06742
+5.6487 5.79053
+1.46503 3.43496
+0.9957 1.53939
+2.4714 3.1301
+0.887049 1.6196
+3.04884 3.19662
+1.24337 2.05758
+7.61142 8.55766
+0.998279 1.64425
+4.74917 5.85236
+2.97632 3.94611
+4.11786 5.62709
+7.40498 7.62083
+1.47854 3.64736
+2.1176 2.64511
+4.55533 5.89436
+7.44618 9.79926
+-0.410242 0.737348
+5.719 6.30861
+8.33692 8.38222
+8.78122 9.98195
+3.75452 4.26866
+2.23771 2.44985
+6.72455 7.61362
+5.9797 6.58846
+6.72885 7.60315
+-0.710302 1.18332
+7.73287 9.383
+6.61213 7.67394
+4.12945 5.68527
+-0.300887 0.341615
+5.77978 6.41534
+8.34001 9.96874
+1.62323 1.8283
+1.71788 2.23905
+7.43484 8.0418
+3.47322 3.8047
+3.47311 3.51261
+7.82093 8.86377
+2.46973 2.99125
+7.91166 8.55065
+3.39807 3.43599
+8.94792 10.0437
+7.70859 8.32487
+5.86852 7.13103
+7.64996 9.19033
+6.66742 7.8092
+7.88241 8.58675
+9.42939 10.3479
diff --git a/bottleneck/tests/data/ws_tests/test_5000_B b/bottleneck/tests/data/ws_tests/test_5000_B
new file mode 100644
index 0000000..5f6e43c
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_5000_B
@@ -0,0 +1,5000 @@
+1.17434 1.46837
+2.58198 4.16589
+0.234041 0.968658
+1.52703 1.59579
+6.7103 7.44033
+3.19227 4.41539
+5.42556 5.57369
+3.45417 4.86089
+3.82256 4.1092
+7.82551 7.90784
+3.9384 4.71796
+5.60335 5.9054
+7.96663 9.8987
+6.30305 6.64853
+7.33246 10.5316
+0.623312 1.09008
+2.63041 2.64616
+5.36028 6.28956
+4.64202 5.91858
+7.55219 7.96304
+7.73736 9.18221
+1.67114 1.84851
+5.07514 5.12159
+7.03732 7.05228
+7.5006 7.59212
+0.244947 1.55875
+0.0170454 1.10485
+1.95394 3.53669
+5.66015 6.01949
+5.88211 7.64639
+7.46698 9.27085
+6.37429 7.10154
+4.54535 4.81932
+8.21203 9.35896
+4.89933 6.20802
+3.68683 4.17831
+0.477467 0.828394
+6.17871 6.77834
+9.77523 9.92676
+0.854808 2.38709
+7.93326 8.3553
+2.10917 2.27771
+4.07045 4.72793
+8.2016 8.8011
+2.9205 3.95746
+2.89806 4.39725
+5.5654 5.78669
+9.5219 9.98543
+7.08591 7.19588
+8.35359 9.57893
+9.81348 10.0345
+8.5994 9.71835
+5.43903 7.25234
+1.82768 2.92724
+4.44952 6.79754
+5.66747 7.34386
+5.88153 6.39253
+3.34008 4.22032
+2.46068 2.76051
+0.370778 2.61681
+6.02508 6.26809
+4.32654 4.93262
+7.41536 7.99616
+8.84229 9.87911
+3.8551 5.84353
+1.56832 2.34694
+6.96099 7.42028
+8.15753 8.72014
+9.23141 10.3815
+7.4484 7.80228
+0.473671 0.874895
+3.15689 3.50687
+3.58122 4.09945
+3.55022 3.74767
+4.42708 5.80211
+4.40956 4.68699
+3.80576 4.61856
+7.29965 8.28614
+7.40582 8.15308
+1.69789 1.77669
+1.66419 3.44308
+0.473997 0.872506
+7.83959 8.52898
+6.22416 6.36949
+-0.187159 0.871822
+0.232336 0.585965
+9.29905 9.44357
+1.4459 2.40589
+2.83008 3.19758
+1.15291 2.12112
+2.58686 3.33896
+6.79362 7.88068
+0.228178 1.48318
+5.60001 6.20258
+4.97803 7.10992
+1.70429 1.962
+2.72659 3.13886
+9.22714 9.25889
+3.84694 3.88778
+-0.282077 1.48155
+9.28756 9.58517
+4.34069 5.59751
+8.63909 8.76839
+8.86236 10.7642
+6.77597 8.41888
+7.30621 8.64164
+0.685607 1.22755
+2.91514 3.22638
+2.72098 3.66837
+8.17528 8.32638
+5.19632 5.7506
+7.34177 8.70639
+5.74082 6.35524
+5.95975 6.69284
+9.40187 10.4488
+2.92761 3.36735
+0.399531 3.13082
+4.83399 4.92635
+7.74539 8.56852
+1.76322 3.5086
+6.54479 6.72963
+7.64362 8.12404
+1.35542 1.45313
+0.214385 0.718085
+1.7006 3.21962
+5.91009 6.47862
+2.21093 2.34636
+5.96919 6.79365
+6.59951 8.22203
+1.54571 1.59397
+3.27012 3.79128
+0.32455 0.622995
+1.73926 2.78017
+9.81035 9.84077
+7.38441 7.85171
+8.90372 9.34186
+7.26323 8.41174
+5.7363 5.97348
+8.25473 10.1281
+2.3981 2.52096
+8.53783 9.63442
+8.51755 9.2735
+6.48614 6.773
+3.40182 3.65137
+2.1353 3.04852
+2.95397 3.73285
+6.98063 7.4963
+4.50189 5.26384
+0.21416 1.49363
+0.632196 1.36307
+6.57833 6.60481
+8.0634 9.33903
+2.79759 2.94462
+4.43747 4.58861
+6.48733 6.86569
+2.28008 3.47037
+6.87452 7.77431
+-0.156821 2.71557
+0.72595 1.78862
+1.97586 2.38196
+8.61839 9.1468
+4.55496 5.68986
+0.26923 1.15728
+9.63757 9.7236
+1.39497 1.96698
+4.8643 5.04172
+6.64675 7.66435
+2.56256 2.6015
+-0.381989 0.611211
+0.676336 1.26896
+8.95304 9.03243
+5.62058 6.07997
+3.36522 4.04276
+8.64868 10.5024
+4.75813 5.19834
+1.96608 2.05864
+9.01449 9.10397
+3.72786 4.51921
+5.6938 6.96584
+1.73499 2.9314
+2.73099 3.41409
+8.77171 9.07665
+4.63865 4.67649
+8.6698 9.30782
+-0.168259 2.09581
+9.29672 9.56
+0.372544 2.60567
+0.450487 1.32919
+6.95341 7.6399
+3.4403 5.24993
+5.53469 6.97831
+-0.79664 1.21306
+5.68831 6.14413
+8.85601 8.95444
+3.83309 5.211
+5.51573 6.5114
+3.64009 3.99648
+4.40759 4.99283
+1.85198 2.6457
+2.72645 3.74803
+2.04751 3.00998
+3.19365 3.9383
+8.09529 9.45596
+8.88173 9.5618
+0.609816 2.67806
+1.57288 2.60884
+1.68354 1.80124
+4.92058 5.9959
+1.48728 1.84885
+0.299669 0.413905
+9.02156 9.56731
+7.50854 8.49023
+0.667131 1.89987
+2.22472 2.58793
+5.84395 8.79426
+2.35839 2.66935
+3.43111 3.69982
+6.71023 7.36801
+6.75697 9.0991
+2.35352 2.85316
+6.73054 7.39006
+9.48673 10.1493
+6.71226 6.72805
+9.22083 9.71889
+8.36513 9.33921
+0.0652672 0.319993
+3.26467 4.60881
+7.62269 7.79878
+6.48608 6.69515
+6.21737 6.88645
+6.56094 6.9699
+1.61317 2.7167
+5.08621 6.29754
+2.24676 2.8076
+3.09943 3.93921
+9.74093 10.0968
+0.417699 1.6381
+9.2958 10.2973
+3.6663 4.1369
+0.0229943 0.448065
+9.2928 10.1833
+3.66334 4.22032
+0.812172 2.19952
+7.88025 8.71192
+8.69379 9.34922
+1.70691 2.95352
+8.28737 8.29985
+5.22491 5.354
+4.03526 4.14084
+6.49359 7.05924
+0.24853 1.44718
+7.86936 8.75135
+5.76 6.68919
+5.85437 6.14314
+5.86292 6.0516
+2.35692 2.91295
+0.0990674 1.29386
+2.9911 3.56188
+0.552671 0.638929
+5.80756 6.22761
+1.21067 1.77175
+4.51882 4.72936
+1.99969 2.89732
+3.65968 6.61987
+0.478582 1.33355
+0.259061 0.289813
+3.89264 5.02474
+0.349236 0.438003
+7.70442 8.1729
+7.90389 10.1876
+3.06898 3.15219
+4.77811 5.29095
+9.76561 9.89451
+4.14295 4.2489
+0.540224 2.28623
+9.60749 10.2284
+8.49555 9.00307
+7.89668 9.76886
+4.12631 4.70897
+7.87898 7.91814
+9.29858 9.52908
+9.24009 9.91544
+3.73498 4.70275
+5.44467 5.9274
+2.13453 4.85697
+2.29607 2.88771
+0.807842 1.82319
+0.319005 2.08473
+1.62 1.63649
+2.20431 3.23869
+2.00132 2.77136
+6.64752 6.71706
+8.12249 8.28379
+7.55541 7.7813
+3.51763 3.64484
+9.21075 10.2811
+2.24501 2.54426
+5.64566 6.46452
+6.72307 8.56698
+3.91728 4.60262
+4.02535 4.29548
+3.0499 3.53135
+1.30677 2.32194
+9.36908 9.90669
+3.92387 4.33848
+2.87312 3.08243
+4.49167 5.2749
+5.43143 6.74905
+6.94595 9.16539
+1.9784 2.00429
+9.42478 10.2226
+3.7185 3.96576
+9.37729 9.50574
+5.34283 6.89736
+4.95341 5.84626
+2.91654 4.28413
+8.26544 9.3076
+6.23114 7.20273
+1.02585 2.21446
+1.6718 2.29591
+2.28926 2.73452
+-0.648145 1.105
+1.44194 2.18562
+6.78584 8.37985
+2.00402 2.08248
+1.64076 2.04067
+0.0419044 0.455962
+5.51723 5.72098
+5.42117 6.81165
+5.70331 5.81707
+4.97889 5.60741
+3.38797 4.46846
+7.20995 7.66784
+3.45388 4.23386
+3.11057 4.35995
+3.29476 4.04676
+2.0519 2.94719
+5.37101 5.38271
+5.99383 6.64188
+7.48444 7.6377
+2.15043 3.05399
+1.54093 1.83799
+5.59223 5.87222
+5.8005 6.08042
+6.1208 7.22563
+1.2938 2.17454
+4.92405 5.0402
+6.91336 7.79688
+1.47978 1.99762
+9.00494 10.8315
+5.84805 6.15303
+4.95368 5.49096
+8.21704 8.31192
+0.715222 2.33517
+0.904183 2.54741
+3.42349 3.74906
+0.627978 2.37092
+8.41477 8.72651
+3.55373 5.58652
+4.12685 4.61533
+0.775274 1.41263
+4.78915 5.08639
+6.35791 8.15015
+2.88242 3.63509
+2.78526 3.07834
+0.39129 1.15933
+3.26615 4.74531
+8.78873 9.8888
+7.25612 7.45972
+4.97452 5.30012
+0.757255 1.35518
+1.29516 2.52446
+4.66838 4.96648
+-0.0720209 0.832726
+2.68276 3.21123
+8.44253 10.0311
+3.40809 4.70506
+1.09617 2.35452
+5.19302 6.73599
+1.25316 1.58101
+6.2056 7.10099
+7.7666 8.52777
+0.301239 1.37275
+0.522829 0.731575
+6.73869 6.96826
+2.41703 3.20567
+4.94617 6.22052
+5.41524 7.68272
+6.0408 6.29938
+0.0642067 0.600878
+6.32122 6.63505
+3.25427 4.70611
+5.88704 6.1678
+8.71533 9.08476
+6.25575 6.88392
+1.54462 1.56366
+3.95938 4.03326
+2.54671 3.66798
+8.48603 9.10156
+3.37369 4.65454
+5.25469 5.64636
+7.02624 7.36449
+8.17061 8.44321
+9.23147 10.1149
+1.45589 2.25886
+6.47702 8.25307
+7.69088 7.91753
+0.442832 0.616926
+8.35355 8.83222
+7.65142 9.58906
+4.04877 5.17345
+0.76012 1.8686
+6.54877 7.40058
+7.41774 7.65429
+8.69655 9.3325
+4.8302 6.25306
+1.77203 1.90284
+3.67485 4.94569
+6.60162 6.72031
+3.05924 3.35235
+0.0823162 1.3486
+8.42991 8.86331
+6.81596 6.83527
+-0.0174808 1.6745
+-0.758131 1.08928
+4.14423 5.46342
+9.26253 9.85714
+7.42749 8.58214
+4.88849 5.86936
+8.99339 9.38141
+8.85301 9.18285
+2.64303 3.45658
+7.1133 8.66473
+3.50745 3.8629
+7.81615 7.83244
+2.94991 3.8741
+7.91822 8.8362
+-0.0553088 1.19059
+7.35558 7.77948
+2.11257 2.20563
+8.57533 9.16338
+2.3515 3.13009
+4.13239 5.38696
+2.20763 2.93941
+7.2451 7.3211
+0.834388 1.57413
+4.47024 6.17855
+4.75947 6.80913
+2.99607 3.54732
+8.15998 8.80718
+8.94688 9.27971
+4.46335 4.9522
+5.30725 5.69786
+7.63989 7.86974
+6.69589 7.69565
+5.34018 6.08115
+8.59515 9.62264
+1.80557 3.22507
+8.62429 8.94242
+1.34532 1.95042
+8.60707 8.80741
+8.03275 9.40327
+4.30357 4.39095
+8.97954 10.7076
+2.18143 3.51825
+3.98695 5.62062
+2.48813 2.60622
+5.56957 6.43776
+5.18249 5.55459
+3.45373 3.64101
+-0.00345662 0.570597
+3.61127 4.69761
+9.37858 10.6205
+7.24635 8.19639
+4.70142 4.80735
+3.30055 5.14257
+0.860415 1.31635
+4.72924 5.46893
+7.47391 7.72644
+6.22287 6.57754
+0.181652 1.01366
+2.14494 2.80736
+2.16406 3.19383
+8.52991 9.22722
+8.74411 9.06935
+0.575831 1.02699
+2.47315 3.0331
+4.2872 4.59813
+5.82293 7.03604
+2.08982 2.25319
+7.3626 8.41994
+1.23867 3.10885
+7.397 7.78026
+6.78837 7.32977
+0.829368 1.56617
+9.23075 9.35172
+6.76562 7.23578
+0.42851 0.839401
+4.83626 5.5852
+0.150032 2.45322
+2.16811 2.47439
+5.60245 5.81188
+7.43707 7.46519
+0.167317 1.44642
+4.9732 7.58343
+8.67391 10.2957
+0.318592 0.639284
+3.365 4.25929
+7.83683 8.88895
+5.20557 5.30114
+0.940347 1.74022
+5.39149 7.13464
+1.10826 1.27913
+1.9147 2.31276
+0.935283 2.49181
+3.67898 4.33336
+5.10125 6.07734
+0.348807 0.839242
+0.310986 0.58381
+2.03594 2.43119
+5.49755 5.94215
+1.94885 3.34409
+9.66806 9.97883
+4.79099 5.45155
+4.81158 5.30001
+5.17667 5.90019
+9.64168 9.99177
+1.14899 1.22792
+0.466236 0.952985
+6.93679 7.72282
+2.97285 3.23931
+9.22517 9.24315
+7.25783 7.46414
+4.37304 4.51815
+4.01069 4.02979
+0.843132 1.80443
+4.78572 6.04237
+6.02471 6.38074
+4.99536 7.76852
+4.97442 5.17384
+0.731231 1.49497
+2.2797 2.90845
+9.13211 10.341
+4.19545 5.08597
+6.13127 7.09817
+2.65124 5.02208
+5.40235 7.12912
+6.86258 6.91991
+8.24317 8.55273
+7.6877 7.69875
+3.33922 3.53776
+0.089484 0.40755
+1.34909 1.68726
+8.43113 8.72899
+4.90038 5.55994
+0.308089 0.490555
+5.42628 7.1433
+2.11647 2.56987
+3.56934 4.1619
+8.35794 9.24416
+8.8645 9.69151
+5.10701 6.0036
+7.66385 7.8412
+2.89952 4.55221
+6.01533 6.38269
+-0.945182 1.07304
+1.79537 1.85576
+-0.0313338 0.501067
+8.85689 8.87522
+1.61143 1.7773
+9.53229 9.84943
+3.51669 3.81091
+-0.448016 1.10903
+3.16889 3.439
+4.30534 4.36372
+6.20158 8.09618
+2.20949 5.23616
+3.29459 4.17079
+3.90101 4.05611
+5.89688 6.85702
+0.734474 1.04471
+7.84341 8.02702
+8.69431 10.1086
+9.73194 9.92195
+7.63516 7.70631
+8.51416 9.33072
+-0.0712911 0.361001
+2.76979 3.22708
+5.34404 7.5165
+5.64429 5.79865
+0.0755012 0.363483
+5.05631 7.27153
+-0.60164 1.09659
+0.457228 0.876186
+4.27092 5.38033
+8.63891 9.04134
+6.29608 7.04242
+8.97795 9.93013
+5.00385 5.57737
+8.48068 9.44885
+7.35543 7.78492
+3.55698 4.01035
+-0.268117 0.649128
+0.633184 0.66254
+4.54216 4.81132
+6.15574 6.35276
+4.3663 6.36286
+1.45231 2.07039
+7.37031 7.9157
+5.30961 6.3506
+5.80757 5.81762
+4.91767 4.97519
+3.45667 3.60965
+1.7934 2.3807
+4.33289 5.41047
+1.16021 1.29979
+3.75172 4.53521
+3.10835 3.1275
+2.68167 3.00314
+4.10639 4.24094
+4.90776 5.74069
+7.30861 7.86666
+3.52822 3.70998
+5.22222 5.28033
+0.00866476 0.326377
+7.73247 8.61481
+4.25231 4.77499
+8.41148 8.54604
+2.95389 3.63497
+7.76126 9.69124
+6.41218 6.69682
+4.86285 6.44503
+1.84783 1.9065
+4.08788 4.11706
+9.17473 9.50133
+5.15091 5.78649
+1.27694 3.33579
+2.92648 3.37855
+9.37392 10.5123
+4.81878 6.34991
+8.38702 8.83716
+5.07771 6.33618
+1.47438 1.75588
+6.20935 7.11166
+1.08286 1.38
+1.40048 2.0157
+6.60355 7.26234
+5.28396 5.90003
+8.9525 9.59216
+-0.0305792 0.544664
+-0.571491 0.735471
+6.287 7.03679
+5.35225 5.4104
+0.095812 0.605976
+4.33523 4.4048
+6.13288 6.80949
+4.14654 5.5505
+-0.213214 0.260592
+7.56188 7.83088
+7.8132 8.65963
+8.02469 9.3254
+0.00641711 0.420562
+7.49269 8.15849
+9.26359 9.4366
+5.74008 7.86317
+8.62729 9.78825
+4.28946 6.20553
+3.19174 4.54991
+4.16992 4.25203
+2.46138 4.11583
+1.92971 2.16701
+3.43028 3.80842
+6.98297 7.28388
+7.51884 7.55947
+7.79102 9.44326
+0.416342 1.32311
+9.35398 9.85201
+8.72997 9.10384
+6.23398 6.88888
+7.46984 7.4875
+5.92603 6.66938
+1.77761 2.58697
+0.835966 2.06139
+9.63284 10.3565
+6.13677 6.42768
+0.151375 0.382404
+8.10315 8.13441
+5.52283 6.28113
+1.00873 2.44226
+2.5239 3.89871
+5.40599 6.72653
+3.43407 4.0068
+1.22444 1.26601
+7.04395 7.80599
+3.75987 3.77123
+6.43597 7.06249
+8.34435 8.87418
+8.25853 9.04009
+0.415321 2.32725
+0.639046 1.75525
+7.83226 8.12538
+9.55429 10.2734
+3.658 4.35867
+1.8588 3.93292
+7.38922 8.16823
+8.53626 9.23024
+0.848152 1.13412
+6.31667 7.2348
+3.81584 4.62621
+9.24748 10.7408
+2.75953 2.95288
+5.70188 6.62278
+4.22202 4.45368
+3.24616 3.88779
+1.05053 2.09846
+8.67718 9.52693
+2.14107 2.71959
+1.10518 2.69689
+5.01476 5.54139
+4.69244 5.20358
+8.88285 9.93012
+2.55228 2.77382
+6.72118 7.50057
+7.58999 8.71573
+1.83763 2.13481
+4.86135 5.27995
+4.39794 5.42117
+1.42512 2.98262
+4.80489 5.34701
+2.7993 5.13702
+7.52122 8.41729
+9.08613 9.37543
+1.1555 1.3935
+7.34071 8.0428
+8.33361 8.40349
+2.514 2.54741
+8.25732 8.41758
+1.65337 2.57964
+4.20527 5.06565
+0.723443 1.06987
+5.85836 6.64701
+7.908 8.07591
+5.01839 7.0105
+3.15908 5.10364
+4.3574 6.67192
+2.06662 2.46437
+7.5595 8.9108
+7.94919 9.20231
+4.11889 5.49714
+7.28151 7.51881
+1.30685 2.09479
+3.08479 4.47364
+4.50916 5.91511
+7.31605 7.63868
+3.14469 4.07035
+8.38431 8.87993
+7.42277 7.64967
+4.22472 4.26323
+8.49871 8.90746
+7.44431 8.09014
+8.35213 8.7504
+3.85634 4.37584
+9.12975 9.77042
+-0.326056 1.17374
+3.53802 4.06211
+6.81775 6.8467
+8.19106 8.64489
+4.20526 5.37727
+2.74081 3.72143
+0.49642 1.10775
+7.76606 8.00524
+4.79825 6.38926
+1.99478 3.20484
+4.69853 6.29508
+5.73058 7.18643
+8.11708 8.64257
+9.62375 9.84838
+5.95271 6.38989
+9.0193 9.93848
+3.91188 4.10834
+6.065 6.60546
+2.62354 3.60072
+8.53665 9.06824
+6.40691 7.44693
+1.62959 2.5825
+9.4128 9.87031
+6.24697 6.62684
+3.31136 3.45626
+4.80347 4.9935
+9.21711 9.53416
+-0.491547 1.72886
+4.75174 4.87217
+0.86329 1.53331
+2.4586 4.2578
+5.10301 6.2815
+5.08302 5.86788
+6.12434 6.78948
+9.68323 10.0973
+3.52576 4.40424
+4.9925 6.89084
+0.846638 1.80782
+1.09709 1.7685
+8.38592 9.03312
+9.56243 10.2682
+5.03592 6.6429
+7.8609 8.04599
+1.21404 1.31975
+7.47824 9.2063
+1.47849 2.68795
+1.2909 2.06381
+5.21288 5.54616
+6.27218 6.99345
+4.77622 5.08494
+3.30665 4.14735
+3.38947 3.55545
+7.71197 8.53162
+1.10565 1.50806
+0.7889 0.984689
+2.88598 3.33244
+5.70958 5.81232
+5.16567 6.24511
+6.91255 7.25784
+-0.401084 0.753156
+4.81138 6.20671
+1.67301 3.58501
+7.19478 8.25624
+1.24428 2.2523
+4.31631 5.33357
+0.589196 1.02017
+5.69207 6.97803
+2.3854 3.25501
+4.1362 4.91135
+8.9932 10.3184
+7.95871 8.45158
+4.03213 5.26347
+3.09506 4.06425
+-0.0310321 0.738171
+7.35733 7.61512
+2.48488 2.96253
+4.72098 5.69867
+5.5395 5.96914
+3.17854 4.283
+6.50012 7.33744
+1.93266 3.00941
+1.49319 2.71826
+9.0187 9.13099
+7.15259 7.40691
+8.71939 8.93257
+1.57203 3.11249
+0.933429 2.16903
+2.99663 3.71667
+2.06144 2.81311
+7.9072 8.2103
+0.490069 0.614737
+7.84111 9.70812
+1.15363 1.6421
+1.15475 1.43307
+8.2228 9.92116
+7.76825 8.40724
+6.15122 7.31322
+7.1427 7.49294
+2.30516 2.7019
+2.03336 4.03387
+8.3918 9.85707
+8.57214 9.59345
+3.8057 4.1119
+8.9223 9.38556
+9.32051 9.60504
+7.13349 7.69154
+1.71855 2.00425
+5.10333 6.0605
+-0.149137 0.80973
+0.466224 3.1698
+4.19165 4.29604
+1.64018 2.3161
+9.40397 9.89211
+5.21738 7.06323
+0.525526 1.0331
+8.06992 8.08704
+9.81539 10.0915
+9.33514 9.50521
+5.95494 6.54519
+9.21466 9.35909
+4.96603 5.18164
+3.89238 5.53056
+5.04546 6.32916
+8.63758 8.65805
+7.03226 7.57074
+0.32029 1.10893
+0.194176 0.992252
+8.79061 9.50848
+0.239137 0.300717
+7.7234 8.43747
+3.43679 4.28954
+8.31382 9.18928
+1.39612 1.67253
+6.95733 7.39846
+1.29129 2.12185
+7.93611 10.2305
+3.67764 4.17562
+1.38149 2.42407
+2.2847 2.48412
+9.28655 10.0661
+2.94115 3.21326
+7.04238 7.91536
+5.06012 5.61526
+8.95611 9.91736
+2.18524 3.44007
+1.0692 1.10987
+4.37019 5.18443
+5.82014 6.441
+1.68642 1.70458
+4.93783 4.9535
+9.42003 10.1196
+-0.356795 1.30987
+1.37778 2.80527
+9.54126 10.1758
+8.67413 10.5984
+0.914291 2.0697
+6.08696 7.09832
+2.82202 3.31103
+4.07818 5.50195
+2.85223 3.67449
+6.03006 7.10863
+8.84655 10.528
+5.08031 6.2001
+1.00272 2.74191
+0.169102 0.223253
+0.025089 1.26534
+-0.203339 0.64667
+0.899666 1.48885
+0.74235 1.49976
+6.28212 6.80412
+5.65159 5.93106
+2.1686 2.7445
+5.02936 5.43091
+8.07124 8.80499
+8.65696 8.95802
+7.68394 8.365
+8.65062 8.69146
+0.058248 1.19535
+5.74545 5.84057
+6.05244 6.52152
+9.3878 10.3328
+7.71379 8.88044
+3.32961 4.54105
+8.51987 8.62854
+4.10821 4.16902
+9.47639 9.78723
+4.72417 4.84793
+2.32867 2.94068
+9.52275 9.57815
+5.32867 6.96127
+4.32462 5.1508
+4.46919 6.45961
+8.62661 10.9533
+0.0244049 0.56156
+1.49207 1.73164
+7.03156 7.81168
+5.88587 5.89732
+8.43632 9.65085
+7.52612 8.06726
+4.82464 5.6193
+3.8062 3.90356
+2.42708 2.51646
+2.06458 2.45877
+0.427218 2.24283
+7.42616 8.11513
+0.617708 1.01833
+8.74218 9.03592
+-0.213346 0.599112
+9.05291 9.59124
+5.20365 5.54277
+2.85289 3.99509
+3.08468 4.58456
+0.136826 0.685254
+3.87191 3.99021
+0.970836 1.49673
+2.44355 2.53584
+8.88615 9.94545
+3.90591 4.52798
+1.52518 2.50658
+7.21268 9.07745
+0.767314 1.23833
+8.62975 9.42367
+6.71524 7.67686
+7.61205 8.48292
+5.312 5.65087
+4.75627 5.96261
+7.90674 8.0753
+7.37887 7.71478
+3.74483 5.52984
+2.7187 2.85544
+4.7902 5.62159
+2.89671 5.19815
+7.37268 8.72506
+7.11916 8.28301
+9.19814 9.75279
+1.2085 2.60113
+-0.632009 0.889734
+7.99858 8.39743
+6.48346 7.10822
+6.30616 7.06648
+5.56514 6.51183
+2.41505 3.56224
+6.83749 8.84447
+9.05111 9.46906
+7.77476 8.4091
+6.11378 6.31232
+4.42882 5.69917
+5.88107 8.052
+3.75437 4.08893
+2.70487 2.77664
+7.26028 9.77257
+1.44621 2.73267
+2.0384 2.60397
+2.95402 3.68949
+6.04766 6.4054
+0.716046 1.77698
+1.5084 1.72988
+2.58426 2.80376
+8.05255 8.59793
+6.06336 6.20709
+3.29813 4.31473
+2.53477 4.92554
+8.78711 9.88634
+9.26627 9.82082
+6.70683 6.81257
+8.25978 8.99788
+7.28054 7.64237
+5.14556 5.20711
+4.20431 5.87866
+8.96592 9.97597
+4.06216 4.41519
+8.49174 11.0491
+5.24547 6.03094
+4.65885 5.95835
+5.09606 6.34846
+6.30463 6.65933
+6.48022 9.56168
+1.38088 2.98143
+0.486911 1.16767
+8.16327 9.34821
+0.768885 0.782616
+4.51699 6.08086
+9.55086 9.70242
+2.86802 3.72489
+1.88496 2.18749
+4.31876 4.33726
+8.38871 9.45631
+8.80634 9.36198
+5.232 6.42399
+9.86919 10.0492
+3.61902 4.53086
+3.13118 4.42364
+2.69395 3.1816
+-0.303144 1.32309
+4.28871 4.36739
+3.8631 4.08745
+4.9291 4.98968
+7.14273 7.25505
+2.56623 2.59122
+6.01753 7.72265
+6.76051 7.53954
+6.76933 8.14741
+0.933137 1.83537
+7.9357 8.57904
+5.55847 5.59984
+4.25563 4.3345
+4.28087 5.21348
+8.88534 9.06554
+1.88575 2.94002
+5.26613 6.04562
+0.514249 1.45538
+0.130644 0.501645
+4.30564 4.86337
+1.57246 2.38451
+0.303814 1.77474
+4.22675 5.02783
+6.75381 6.78634
+5.64096 5.9725
+6.76159 6.98142
+2.35569 2.39119
+3.29794 4.95962
+6.55055 7.03366
+5.31474 5.69404
+9.01335 9.16988
+8.58306 9.37831
+7.06522 7.07778
+1.14695 1.74744
+3.15507 3.22865
+5.5925 7.14168
+2.14679 3.68767
+7.54789 9.71878
+1.5667 2.08742
+-0.604726 1.66718
+0.306012 0.54799
+2.61731 5.08257
+0.80957 1.74655
+8.22035 8.81637
+4.401 5.449
+8.89389 9.01988
+4.80574 4.9322
+2.19895 2.88565
+9.06688 10.8095
+1.23727 1.58699
+7.14836 7.92057
+4.65155 6.15149
+0.563061 2.16535
+7.66764 8.0341
+8.32324 8.42774
+4.54541 5.11069
+8.0237 8.09992
+7.26113 8.09404
+2.55196 3.20317
+8.1236 8.60951
+1.90437 3.23006
+0.888133 2.50365
+1.13618 1.69444
+2.60463 3.01696
+7.2311 7.73229
+5.06501 6.01487
+3.9893 4.10116
+1.45278 1.56937
+2.74601 3.80778
+9.40705 10.3843
+3.02533 3.52213
+8.7097 9.2268
+8.73145 10.5552
+2.56059 3.5742
+6.27328 7.57089
+3.23291 3.30811
+6.33804 7.20304
+7.63648 8.34564
+9.82053 9.93597
+3.14924 4.58629
+5.28253 6.33733
+1.99411 2.04104
+0.305593 0.420302
+5.39668 6.64188
+7.99992 9.37823
+5.25169 5.65987
+0.109291 0.875734
+3.08589 5.50296
+6.51358 6.62588
+5.34687 5.58204
+0.043587 0.932787
+-0.0264143 0.28677
+8.09722 8.37087
+5.46612 6.30285
+2.89146 3.49892
+6.73278 7.11762
+5.03068 5.90176
+1.7459 2.87727
+0.207707 0.448933
+7.00453 7.63105
+6.02789 7.87991
+8.1917 8.95854
+7.49014 8.73215
+8.48402 9.22063
+1.0467 2.4687
+0.241901 1.38802
+2.65867 2.81258
+5.46725 6.59448
+3.40578 3.75607
+4.2495 4.26392
+5.6608 6.213
+2.99705 3.88852
+6.17231 6.72018
+-0.17415 0.492739
+4.89596 6.49895
+4.68876 6.60218
+-0.0510568 1.46013
+8.87099 9.28179
+3.98894 4.5838
+-0.20015 1.59214
+8.80756 9.51828
+7.74921 8.53538
+-0.380041 0.440574
+2.69409 3.91466
+2.42747 4.56745
+6.25881 7.75647
+7.2941 7.77193
+2.60806 2.90251
+0.325028 1.22219
+8.29921 9.01416
+3.85524 5.45451
+5.2612 5.71877
+2.92849 3.73937
+8.6242 8.70808
+7.28153 7.35797
+1.65378 2.87917
+3.46034 4.24143
+3.99989 4.3199
+1.15266 3.60328
+4.8464 6.4887
+4.67021 4.68421
+6.96861 7.31554
+0.00723008 0.817047
+7.59589 8.88352
+5.56725 6.08465
+9.02409 9.19527
+5.81681 6.74193
+1.98221 2.98678
+8.76392 10.7646
+4.3903 4.50531
+1.0186 2.01838
+2.66674 2.74505
+2.41105 3.44579
+8.98295 9.18995
+8.14385 8.98779
+2.69613 3.60144
+0.445704 1.51319
+-0.634889 0.860409
+6.32737 7.10112
+7.88824 8.06838
+3.76271 4.43529
+7.66487 9.30221
+8.73974 9.59191
+3.08965 3.43006
+8.9518 9.96154
+0.727194 1.55228
+6.35214 7.12234
+2.71987 3.22996
+7.12786 7.4379
+-0.346107 0.837469
+8.47103 9.05987
+9.15744 10.628
+8.3237 10.093
+1.15052 1.16223
+6.95959 7.35423
+7.69488 8.44145
+4.21694 5.65913
+3.10562 3.37534
+9.73437 9.78252
+5.0458 5.53479
+7.80485 8.5163
+2.0442 3.75748
+-0.459177 0.498702
+7.38032 8.32195
+0.909659 2.11175
+7.08657 7.56877
+1.84997 3.10206
+4.2517 4.53819
+6.71655 7.04117
+1.06604 1.29153
+2.69273 3.31633
+2.19732 2.84826
+-0.723032 0.774865
+-0.289734 1.44645
+5.87194 7.71917
+1.01576 2.83685
+0.981927 0.998558
+3.07172 3.73201
+-0.112577 1.12642
+3.54063 3.67007
+7.21571 8.53815
+0.109957 0.839052
+6.86046 7.17211
+9.40878 9.69478
+0.989391 1.69046
+8.22287 8.8147
+1.48203 2.83308
+5.86418 8.0993
+0.749797 1.09852
+1.82996 2.50847
+0.28178 0.496017
+2.60694 3.00872
+8.6254 10.1698
+6.11641 6.41537
+7.19529 7.21342
+1.8214 2.17517
+0.991201 1.3788
+2.84924 3.12362
+5.75821 7.13843
+6.7106 7.35932
+6.6055 6.6829
+7.97105 8.58613
+1.56087 1.95845
+6.36782 7.10926
+2.43382 2.74699
+7.40509 8.8029
+8.42459 8.63142
+6.26128 7.55043
+4.6465 5.4431
+2.93214 3.29517
+0.157602 0.545214
+6.05931 6.72188
+1.7908 3.11731
+2.39217 3.58736
+7.07421 7.43852
+8.13419 9.74991
+9.53094 9.65319
+2.35726 3.68679
+-0.108561 0.874853
+6.87136 8.84157
+3.40803 4.58835
+7.50448 7.89932
+4.29762 5.53867
+0.863755 2.30032
+7.24847 7.95342
+2.89618 2.98849
+-0.928261 1.61922
+0.974105 2.91262
+6.99271 7.25856
+3.60995 5.01832
+1.26865 1.79704
+9.62217 9.80719
+1.02656 1.35514
+7.16502 7.32934
+3.12092 3.28857
+2.81374 3.84317
+8.73626 10.7585
+3.36982 3.61446
+5.08437 5.78949
+2.90218 3.0862
+9.2309 10.2523
+5.0967 5.48926
+9.73088 9.92708
+1.54013 2.78301
+6.73707 10.0789
+6.41735 6.838
+2.57935 3.04287
+5.719 6.70352
+5.42474 5.62732
+4.23904 4.69787
+4.16528 4.28736
+7.73477 8.84143
+4.90346 5.87324
+5.1969 6.14087
+3.48793 4.14182
+0.648493 1.07987
+6.88101 6.97932
+7.67342 8.74418
+5.16759 6.3871
+9.16292 9.49569
+8.77422 10.4817
+-0.358149 1.04178
+9.54616 10.3424
+3.12027 4.26504
+3.81223 4.73004
+1.2386 3.32247
+8.21963 8.42629
+9.10312 9.51016
+6.96107 7.43045
+2.98587 3.12365
+0.198165 0.211424
+5.19716 6.10856
+6.10553 6.3327
+3.98176 5.11099
+1.02512 1.04242
+4.27949 5.71947
+-0.457956 0.538807
+7.99877 9.48581
+5.88782 7.73303
+1.21496 2.85825
+8.46962 8.7862
+9.50182 10.1527
+5.85223 7.76234
+2.48368 2.52439
+2.35426 2.77405
+0.397056 0.482679
+0.160423 1.15786
+4.47109 4.8633
+4.74523 5.84196
+5.39177 5.75218
+9.00754 10.3249
+3.74813 4.03273
+3.08633 4.08426
+4.62672 5.29012
+1.92055 3.01442
+3.79279 4.5603
+9.52431 9.68334
+2.8126 3.32592
+-0.313688 0.490785
+9.06695 9.36835
+2.60321 4.14185
+4.40231 4.99535
+9.32205 10.1041
+5.3879 5.44349
+0.308728 1.0956
+9.05758 9.08283
+1.90313 2.50914
+7.1391 7.59459
+7.47357 7.95993
+1.25267 2.34827
+3.33222 4.36522
+8.78126 9.38611
+0.635979 1.62283
+8.3492 8.57545
+-0.572557 1.60517
+8.28855 9.03937
+3.47934 3.90271
+4.64498 5.43501
+0.872177 2.62011
+7.3893 7.58876
+2.14063 2.88063
+1.69361 1.75261
+4.19727 4.86483
+0.814676 1.27639
+8.19899 8.58203
+8.3394 8.99896
+9.31768 10.1694
+4.99218 5.19949
+4.2459 4.75266
+9.6314 9.64249
+4.038 4.75708
+7.92398 8.8579
+4.30747 4.54161
+7.51776 7.78258
+3.77611 5.1385
+3.53275 3.90278
+1.78619 2.12474
+3.18736 3.55159
+8.36759 8.52587
+5.52526 5.7843
+7.64174 8.09773
+4.37925 5.85699
+3.94295 5.31298
+-0.464623 0.795523
+7.02408 7.7048
+0.0690458 1.0008
+1.05445 1.32797
+0.126093 0.712612
+-0.809973 1.33869
+3.45568 3.96532
+0.433875 1.78679
+8.94667 9.65034
+1.98575 2.76936
+6.47974 7.67912
+2.74186 3.34153
+7.82655 9.32112
+4.71441 6.14932
+0.741177 1.76987
+8.05021 8.23239
+0.818503 0.882959
+7.13341 7.43399
+8.45939 8.93395
+4.44558 5.70161
+3.05657 3.86962
+8.75469 8.85537
+1.0922 2.23475
+6.00278 7.51598
+0.0530968 0.582206
+4.01788 5.48223
+1.30808 2.81869
+8.18848 8.59771
+2.43691 2.80685
+8.54045 10.6178
+7.58523 7.91634
+6.70183 7.49962
+5.81501 7.29783
+0.661853 1.58021
+6.50997 7.20411
+0.334292 1.40252
+-0.329585 0.742961
+2.38756 2.48935
+2.78114 3.58788
+7.97227 8.55379
+3.36753 4.57472
+5.14486 5.31457
+3.99691 5.47708
+6.36404 6.8741
+3.22519 4.63321
+1.80583 2.21824
+8.20747 9.42947
+5.90819 6.94368
+6.58559 6.85933
+2.99108 4.03832
+7.20963 9.6252
+3.10244 3.87265
+7.23018 7.91389
+7.18084 9.61063
+6.74145 6.86507
+8.40721 9.5751
+7.12352 9.45614
+2.06653 2.51786
+4.9155 5.04183
+1.34304 2.92777
+0.571315 1.17285
+8.05396 8.28214
+5.29142 6.24974
+8.93797 9.23051
+4.6108 5.45568
+6.46124 7.53124
+3.16695 4.37505
+2.76803 2.82764
+4.1531 4.84927
+8.19433 9.00383
+5.12114 6.22952
+2.2542 4.74849
+0.621192 0.871537
+1.37403 2.28895
+0.305704 1.3287
+8.70471 9.53085
+2.29164 3.56607
+2.42106 3.37382
+1.14309 2.03085
+9.17624 10.3281
+1.88864 2.70161
+0.932647 1.2473
+5.72385 6.55694
+5.25496 5.38675
+5.85771 6.69626
+7.37247 7.93094
+7.73499 7.98782
+4.91417 5.27506
+3.51127 3.84403
+6.96198 7.27686
+6.51176 7.74735
+4.19954 5.08222
+1.58115 1.83842
+2.11889 2.3408
+1.94427 2.00422
+5.59977 6.86555
+9.46942 10.3491
+9.18904 10.1988
+1.71938 3.01547
+4.3515 5.4951
+2.53792 5.85188
+0.3884 1.36228
+5.02469 5.62368
+6.82402 7.72203
+-0.320478 0.821539
+0.0885656 0.248783
+3.01725 3.44385
+6.63776 7.74386
+6.57899 7.9332
+4.82656 5.18327
+3.91909 4.43955
+0.0708319 0.101395
+2.59796 4.22775
+-0.433109 1.26978
+-0.434274 0.624336
+3.22018 4.25282
+4.63351 4.776
+8.889 9.56332
+5.35952 5.46531
+8.73832 9.22756
+2.03432 2.34194
+0.477994 1.43353
+1.2029 2.86844
+5.09945 5.76855
+8.89076 9.01771
+5.30284 6.31732
+1.56375 3.17543
+5.4773 6.36897
+5.30934 5.35073
+7.20096 7.7075
+6.51046 7.12888
+9.37127 10.0531
+-0.0484323 0.348687
+1.83241 2.2143
+8.28633 8.60462
+2.51014 3.65817
+3.27798 3.58685
+1.41567 2.23302
+7.50794 8.10378
+-0.0579575 2.10373
+-0.856005 0.96621
+2.96238 3.48434
+1.36304 1.90594
+2.9997 3.41214
+7.2763 8.087
+1.69207 2.74419
+5.41625 5.83917
+9.22139 9.53794
+1.17477 1.51576
+6.74597 7.90871
+0.678913 1.73759
+5.70863 5.7214
+8.88411 8.93377
+3.44409 4.54586
+0.958963 1.53878
+8.29904 9.3867
+2.52433 3.60238
+8.16257 8.21986
+2.11395 4.23455
+6.85451 7.40364
+0.20286 0.639736
+2.05848 2.49034
+0.547013 0.77336
+7.83609 8.11903
+2.16539 2.29286
+3.94232 4.31368
+8.53475 8.54519
+4.77462 6.4158
+4.08395 4.68214
+1.56902 2.23811
+1.61337 3.11768
+1.51181 1.65521
+0.0821202 2.09269
+4.77622 5.16243
+4.62148 5.75837
+0.613158 0.952696
+1.89128 3.04792
+7.57509 8.92834
+2.70465 4.2941
+4.95906 5.12442
+8.0927 8.17277
+0.796512 1.3215
+5.74134 6.45291
+9.68479 9.78978
+5.89261 6.2292
+6.11377 7.9339
+2.20571 2.67129
+3.46228 4.27058
+5.26723 6.2653
+4.04391 4.26562
+0.380382 0.818995
+7.58108 7.7618
+5.02375 6.13042
+4.20178 4.66297
+2.83039 3.0221
+2.36072 2.45545
+6.68854 9.20726
+2.91388 3.42464
+9.33373 9.73449
+7.75844 7.94625
+2.72414 2.89669
+6.65438 7.96623
+1.00647 1.05385
+2.63018 4.9432
+0.152187 1.60259
+8.86332 10.3631
+2.31523 2.6815
+8.00509 8.61794
+1.69711 1.75938
+8.65442 8.73697
+4.23917 4.32001
+9.66851 10.1925
+6.93943 7.49814
+8.51986 9.03561
+2.10317 2.5175
+0.539549 1.75683
+6.29423 7.93236
+8.64345 9.54556
+1.44069 1.6814
+9.10017 9.77088
+6.16731 7.40496
+0.570043 1.93192
+2.65761 3.88544
+1.46895 1.52688
+-0.369067 0.540647
+2.04868 2.72065
+2.1286 2.27858
+5.90157 6.16431
+1.55581 2.51851
+3.29705 3.81635
+3.4137 4.10991
+8.48699 10.1364
+8.43437 9.4642
+-0.037842 1.47589
+0.541735 1.7805
+0.499576 2.36065
+4.1415 4.72435
+4.77598 6.16872
+3.30388 3.61854
+6.43796 7.85966
+5.27157 5.70871
+0.919258 2.18653
+4.00961 4.07902
+3.78201 4.23596
+4.50464 4.791
+3.70253 5.30916
+8.59228 8.70036
+4.31103 5.69049
+5.31775 5.34378
+2.24198 2.64194
+6.66937 7.41675
+7.21753 8.42057
+4.35399 4.52398
+6.90698 7.30084
+3.44296 5.44378
+3.36719 4.89951
+3.38624 5.33856
+3.44877 3.53693
+5.81398 6.3016
+7.24655 7.33127
+3.86142 4.53134
+3.85894 6.88112
+6.45704 6.95699
+6.90997 8.24088
+5.68813 5.7611
+0.699911 0.824323
+6.73758 8.42517
+9.34644 10.07
+0.289929 1.30554
+8.30644 8.49113
+6.47667 7.16073
+4.28093 4.90236
+8.32678 8.57064
+7.09205 7.92316
+5.55599 5.63919
+1.0104 2.22875
+1.72237 3.53668
+2.54699 3.14823
+-0.668582 1.25485
+1.25582 1.37003
+1.35044 1.57807
+6.17083 6.30811
+0.618816 1.20065
+-0.540992 1.21634
+2.06673 4.28857
+9.03398 10.8112
+8.73735 9.22814
+1.30178 2.7599
+6.0221 7.34889
+8.30124 8.52159
+1.92023 3.34545
+2.99331 4.93358
+3.8412 3.93379
+1.455 2.77005
+0.538664 2.1118
+4.16926 4.26053
+0.699746 0.937609
+6.36024 6.6511
+2.34698 4.84463
+8.11109 8.76496
+4.05425 4.67773
+8.2284 9.78568
+1.64423 1.80353
+5.70109 6.93764
+7.2091 9.67224
+4.47015 5.23311
+4.29326 5.36144
+7.93151 8.96494
+4.61889 4.96487
+5.38473 5.43594
+9.35456 9.66489
+1.23737 3.04121
+1.16077 1.19519
+5.91037 7.55679
+6.88344 7.60181
+6.39705 8.65039
+1.61791 2.93041
+9.68285 10.1396
+9.03129 9.05839
+7.0683 8.29875
+7.19624 7.41696
+7.5266 8.38738
+-0.254571 1.01098
+1.30218 2.03222
+7.6432 7.73031
+4.99495 6.04757
+2.79394 3.29394
+0.31505 3.55963
+7.55382 8.18787
+6.00032 6.27664
+1.49355 1.79767
+5.21191 7.19537
+3.47816 3.75801
+2.10272 2.39494
+1.31887 1.93829
+7.14313 7.63055
+7.3141 7.77239
+6.03409 6.17265
+4.24946 4.53165
+0.0569272 2.56109
+8.44766 11.4872
+4.22879 4.28007
+6.92817 6.98775
+8.08859 9.0206
+-0.0748418 1.48605
+6.56698 7.0488
+4.46624 5.4952
+3.66085 4.05778
+6.44711 8.93943
+2.45735 2.49339
+0.0606673 0.416191
+-0.183838 0.750464
+7.08561 7.67275
+6.65423 6.90808
+0.0598735 0.364072
+5.2228 5.41543
+3.14042 3.19043
+2.40069 3.02829
+1.80441 2.1849
+3.47491 3.95775
+5.49162 6.63934
+2.03332 2.32288
+3.17234 5.25109
+2.58274 2.59951
+9.37994 9.97097
+4.71509 6.77966
+5.18915 6.84982
+6.12508 7.04354
+0.811202 1.98808
+1.46825 3.66984
+2.44386 4.15623
+7.60169 7.68242
+-0.43208 1.22222
+5.40569 5.66153
+0.391742 1.79408
+6.77742 8.43115
+9.12828 9.3851
+6.39541 6.80626
+5.17919 6.29326
+6.57263 8.12999
+3.439 4.62236
+8.40525 9.80086
+7.60986 7.70099
+1.32123 1.44213
+0.526574 1.92338
+9.57195 9.79591
+9.52103 9.63159
+3.79775 4.20608
+4.74446 4.89606
+9.00085 9.60025
+1.26279 2.08363
+4.13639 4.49232
+6.59409 7.18315
+1.0637 1.78425
+5.4213 6.87661
+4.24407 4.30987
+9.79732 10.1204
+4.24597 4.83541
+8.47705 8.5145
+4.34095 4.93842
+5.68168 6.96086
+7.48654 7.91072
+8.32005 8.45111
+5.24065 5.3032
+3.25982 3.94442
+5.58106 6.18764
+4.4243 5.58619
+6.36467 7.07082
+2.70051 3.56014
+5.94534 6.87688
+7.33638 7.7645
+4.57067 5.86652
+7.83993 8.36854
+9.03617 9.11629
+7.44672 7.95614
+6.05876 6.3594
+4.02496 4.97119
+3.01438 4.36109
+7.4932 7.92357
+7.51661 7.53354
+7.60692 8.49678
+1.76088 2.59103
+7.08578 7.39566
+4.83605 5.42933
+-0.186592 0.847663
+1.15879 2.33996
+8.11815 9.35472
+6.02584 7.62549
+0.881084 1.00015
+5.39067 6.27026
+0.910755 0.97444
+5.32174 5.65652
+7.69388 8.24928
+3.40521 3.7615
+5.60321 6.92388
+8.25096 8.34324
+0.00108913 2.16897
+0.508035 0.66573
+-0.0517816 0.0876197
+3.26472 4.30955
+1.99494 2.14903
+2.089 4.32368
+5.17378 5.75964
+2.8779 3.54361
+6.56459 6.90645
+1.43196 2.88337
+1.48917 1.94009
+3.40807 4.25784
+8.0334 8.13458
+8.22254 9.6175
+2.96308 3.14349
+5.04768 5.71252
+3.9977 4.72614
+1.44384 1.60782
+7.78147 8.19817
+7.03854 7.50085
+5.90747 7.06091
+2.89169 4.31831
+2.46167 3.16529
+9.13228 9.1504
+2.57975 3.05313
+5.75976 6.52958
+8.10499 8.98982
+8.43162 8.76377
+0.422917 0.668254
+1.69046 2.09962
+5.50386 6.66954
+0.0897183 0.564514
+3.50103 4.1041
+3.91918 4.52559
+4.39297 6.18876
+3.90396 4.90868
+9.69362 9.85528
+6.27994 6.95062
+8.01563 9.09433
+8.25641 9.72944
+8.22072 8.35423
+1.27059 1.61352
+8.53312 8.96235
+3.49185 3.9042
+5.79579 6.046
+0.489013 1.2147
+4.00074 4.177
+2.66625 2.93036
+7.20267 9.34958
+7.44659 8.54707
+8.99915 10.1143
+7.59922 7.82031
+8.38502 9.03222
+0.160075 0.294398
+4.14549 4.3927
+9.35554 10.248
+-0.159435 0.467922
+2.17272 3.72336
+8.63811 8.79976
+4.23215 4.66461
+6.99516 8.2035
+6.45212 7.88791
+6.20141 6.28633
+7.69396 8.82204
+4.50807 5.96315
+8.51725 8.89286
+0.939492 2.12064
+7.4615 7.62666
+8.46681 9.11769
+3.92828 5.40884
+9.05622 9.40015
+0.229625 0.860838
+2.05694 2.52113
+-0.217927 0.574255
+9.55146 10.3256
+8.31497 8.3417
+3.52833 4.47013
+7.7131 8.52058
+2.15462 2.66777
+5.7674 6.17553
+3.3358 4.10589
+2.06642 3.00412
+2.43387 2.85242
+5.09473 5.84276
+7.3287 7.54846
+4.64254 5.11465
+4.05785 4.93614
+4.25413 5.43513
+2.96476 3.15378
+3.53732 4.48239
+2.34137 4.01272
+2.24879 3.40626
+3.43323 4.49055
+0.871415 1.33068
+0.508929 1.65611
+4.92057 4.94743
+7.03376 7.35193
+5.73043 6.47264
+7.82417 9.93642
+5.24102 5.9178
+2.38528 4.1676
+6.27437 7.19631
+9.29267 9.53262
+4.10098 5.24964
+0.383714 0.833317
+5.97628 7.92987
+8.15799 8.96819
+8.1687 8.29862
+8.16289 10.5149
+7.38205 7.89765
+3.81883 4.15607
+9.46915 9.61755
+1.50756 1.51863
+2.34236 2.84689
+0.398473 1.15027
+1.05302 1.49155
+8.71687 9.35232
+1.0502 1.40395
+7.83685 8.76302
+7.7731 8.46899
+5.56618 5.97458
+2.90035 4.12043
+6.40644 6.68706
+3.95201 4.37075
+7.1831 7.67748
+9.42789 10.0914
+5.45198 7.01256
+8.64609 9.45756
+6.01864 6.31515
+7.64621 8.65533
+5.45654 5.76553
+2.04332 2.75476
+5.49454 5.85693
+6.13688 6.21927
+2.66255 2.7385
+4.8326 6.43772
+9.12704 9.45287
+-0.294488 0.318697
+2.26979 2.35516
+4.12949 5.58506
+3.01416 3.62246
+6.64697 7.10221
+6.44307 6.82985
+4.10484 4.73148
+7.42589 7.6029
+5.33055 5.50395
+2.46474 3.05847
+5.43677 5.59206
+2.13807 2.3988
+-0.38424 1.8121
+0.00916704 0.219304
+8.62621 10.2262
+3.33927 4.51169
+5.45656 7.13165
+5.29253 6.57917
+3.51704 3.9421
+8.63729 9.13361
+3.92626 4.3469
+6.83104 7.52695
+1.22258 2.28191
+0.447646 0.789809
+7.96543 8.54328
+2.24269 2.42571
+4.4161 5.40481
+0.813992 2.21792
+0.694664 0.974182
+6.50017 6.88902
+4.00723 4.65882
+9.05784 9.85062
+6.80276 6.98196
+0.105446 0.379881
+0.416982 0.53336
+9.01269 9.55204
+3.27197 4.23315
+6.7017 6.89704
+4.21512 4.42378
+4.86735 6.90949
+4.52235 5.36878
+2.62205 3.55746
+-0.551048 0.555476
+1.63274 2.71251
+4.26739 4.88085
+8.23129 9.77405
+2.49409 3.96851
+6.66387 6.88886
+7.72383 8.90611
+3.18511 3.27281
+0.73722 1.64435
+7.90329 9.02868
+6.94845 7.06773
+0.509461 1.54928
+4.63885 5.51652
+9.24395 9.5121
+1.00007 1.57161
+5.31349 5.45437
+0.929284 1.71034
+7.05985 7.63288
+7.38418 7.45373
+4.14937 6.5167
+7.49989 8.6081
+9.28313 9.57721
+4.41285 5.1497
+2.96148 3.09221
+1.58256 1.66419
+4.45116 5.43488
+5.70927 7.11699
+3.61105 3.93153
+5.92285 6.63773
+3.50065 4.48453
+7.97338 8.96464
+0.541394 0.965435
+4.46469 5.03925
+7.33695 7.6484
+9.64234 9.6938
+4.16378 4.17886
+7.10741 7.31549
+1.51829 2.62477
+2.1892 2.9684
+9.23767 10.0462
+7.87649 7.97087
+7.05385 7.85952
+6.91232 7.50277
+6.60185 7.81572
+2.27112 3.90211
+5.74452 8.2018
+6.25117 6.26911
+0.525893 1.53447
+0.392956 0.959233
+3.51591 4.71055
+3.10449 5.41156
+7.35964 7.65642
+2.89831 3.54334
+3.42338 3.68259
+4.75496 5.51419
+3.8792 4.48395
+2.18007 4.13236
+3.15798 3.16864
+8.91248 9.21598
+8.54636 9.34037
+7.93697 9.79709
+6.40205 8.9653
+9.67332 10.2252
+4.31771 5.25423
+7.27485 7.3725
+6.22971 7.11411
+1.16538 2.16762
+1.40443 1.6876
+3.14915 4.58847
+7.13761 8.72165
+4.38448 5.88699
+7.98309 9.19449
+8.491 9.05597
+5.55043 6.19359
+2.44006 3.36071
+9.56522 9.79903
+1.86129 2.00225
+1.65239 2.11478
+7.59392 8.4655
+2.44709 2.68538
+6.80932 7.04694
+8.8212 9.4182
+0.276845 0.956468
+8.17008 8.5538
+0.77864 2.06897
+6.78458 7.68692
+0.504907 2.67518
+5.56963 6.9058
+3.42691 3.5414
+2.52065 2.71583
+5.09924 6.26696
+0.223724 0.610039
+3.61258 5.29324
+0.388393 3.11131
+2.87763 4.45415
+8.26438 10.1169
+5.89742 8.17506
+1.89686 2.66651
+5.33662 5.68228
+3.37496 5.67291
+2.25713 2.36127
+0.402185 0.716342
+6.4231 6.79227
+3.22707 4.69314
+7.85092 8.77413
+3.31322 3.72455
+5.43021 7.7167
+8.5883 9.00864
+1.21371 1.71836
+6.35584 7.9706
+5.44438 5.50414
+5.31325 6.11217
+6.08888 6.78794
+7.70604 8.13257
+1.29858 2.48753
+5.54083 6.38817
+8.23948 9.82646
+7.5575 9.0224
+8.00415 9.39763
+0.488455 1.55358
+4.48727 5.20741
+6.46648 7.02349
+0.355939 0.611119
+9.4892 10.2189
+2.61893 2.82832
+0.268193 1.24687
+3.01964 5.19554
+6.29954 7.42795
+8.70796 9.48366
+5.39307 6.64597
+2.47001 2.60746
+5.30949 7.46529
+6.07973 6.16835
+0.764507 1.6144
+7.94123 8.52143
+1.88244 1.96592
+6.42103 7.02205
+7.673 7.73208
+6.66891 7.80675
+6.9305 7.5431
+6.62335 6.93873
+4.34846 5.77621
+0.49878 2.82928
+2.65221 2.80109
+7.45348 7.74372
+4.10129 5.26894
+3.87782 4.19855
+4.62113 5.22658
+2.84558 2.88185
+2.53209 2.86065
+8.94932 9.21967
+6.48046 6.89614
+5.81885 6.66829
+6.49129 6.62015
+8.5663 9.58685
+2.43346 3.89849
+9.36561 9.45886
+1.40232 2.65
+6.66 6.74041
+2.87007 3.49668
+4.71138 6.0184
+5.03638 6.08494
+7.77735 8.14253
+1.0301 1.27179
+2.58337 4.04699
+6.95419 7.89775
+7.81164 8.62551
+3.37669 3.96217
+4.68541 5.58692
+4.79697 6.34841
+3.95334 4.81962
+9.44006 10.0941
+4.91098 5.12386
+8.44273 10.1565
+3.6685 3.73156
+5.07599 5.33357
+-0.138235 0.260923
+2.71154 3.45603
+5.75096 6.16127
+4.4775 4.64308
+6.80557 8.97442
+5.49408 5.76652
+8.31937 9.12886
+3.26479 5.51673
+2.57425 3.03145
+2.42465 3.92714
+7.86505 8.50835
+3.29229 3.43549
+4.08537 4.69709
+7.83885 8.60616
+1.61622 2.72716
+9.10228 9.41907
+8.49325 9.46612
+-0.174644 0.351716
+1.95648 2.14825
+8.28844 8.4428
+4.35888 5.59521
+5.1396 5.22537
+0.330835 0.879566
+6.14972 6.82967
+3.14811 4.89049
+-0.231668 1.08277
+3.13526 4.94545
+8.32674 8.91046
+5.22364 5.48006
+9.84318 9.88416
+-1.07813 1.6965
+1.5095 2.0328
+8.03716 8.2792
+-1.01307 1.46703
+8.22096 9.0055
+8.9917 9.0415
+5.60623 6.74537
+3.15991 3.19314
+3.13863 3.26451
+0.739618 0.896958
+0.67599 1.18486
+3.37355 4.06303
+0.38605 0.410067
+3.03297 3.46387
+3.45867 3.79806
+8.67249 9.53278
+-0.213855 0.787363
+1.52316 2.61117
+8.31846 8.59736
+4.84685 4.94042
+7.41901 7.82623
+4.99029 5.09747
+5.3637 5.37612
+3.22123 4.77749
+3.21668 5.74743
+3.48748 4.59962
+8.00016 8.56269
+1.63631 2.42239
+1.05159 3.72319
+7.22643 7.95706
+5.65694 5.99195
+9.4469 9.66915
+0.857984 1.59867
+4.05869 5.69955
+2.65788 3.07259
+1.8038 3.38748
+3.91934 4.89922
+6.18534 6.70342
+2.85076 3.20176
+8.1897 9.9614
+0.685531 2.05322
+3.31097 4.00809
+8.26537 8.63475
+2.90508 4.07797
+1.25213 2.31285
+3.05752 4.03741
+-0.481913 0.605629
+1.87958 2.19386
+7.28689 7.76316
+4.82075 5.20688
+-0.08115 0.31839
+3.50085 5.89363
+1.31184 3.30269
+4.03137 4.81493
+6.11688 6.13923
+7.93584 8.43321
+4.9838 5.3733
+3.8174 4.11979
+8.56196 9.02824
+2.87809 3.89589
+7.95309 8.05432
+3.47469 3.63716
+6.61009 7.12576
+8.87374 9.79588
+7.31513 7.99089
+5.78084 6.68535
+4.96985 5.59877
+2.20236 2.52473
+0.661014 1.11035
+6.36183 6.58403
+6.67947 6.85093
+-0.242005 0.513902
+0.442966 1.72024
+6.4587 6.74016
+6.67958 8.0837
+8.98524 9.56405
+6.91409 7.59877
+3.73596 3.97705
+5.51193 5.96437
+3.72029 4.50126
+3.09896 3.23616
+8.83312 8.91774
+0.32173 0.486199
+4.21092 4.59955
+2.61616 4.07081
+1.89049 2.65559
+4.96401 5.00629
+9.33156 9.70914
+3.72455 4.61054
+8.91265 9.6563
+7.12401 8.04324
+6.65393 7.25572
+1.04032 1.24927
+3.0174 5.56006
+1.47645 2.26867
+3.49833 4.37416
+6.16877 6.34452
+6.47417 6.90595
+4.27056 4.92535
+7.60439 9.35352
+0.426219 0.754405
+8.5291 8.68579
+5.84717 6.64632
+1.99513 2.5284
+5.10669 7.83064
+6.99006 7.37272
+0.871836 1.5934
+3.6572 4.38875
+0.154617 0.290737
+5.91634 6.50415
+5.33982 5.45293
+6.92602 6.94691
+0.349512 1.61427
+8.02048 8.99943
+5.75598 7.34946
+5.86948 6.51327
+5.11707 5.6181
+6.27656 7.10043
+8.48922 9.73833
+8.35863 8.69746
+6.67829 7.07852
+8.51257 9.50383
+3.76636 4.33757
+4.82804 5.57166
+5.17892 5.61254
+1.35188 1.94069
+6.04969 6.06833
+5.34181 5.82455
+5.71714 6.71234
+0.966462 2.56278
+7.95169 8.15951
+6.53583 6.89673
+6.73246 8.34493
+8.71111 9.76467
+7.53215 9.56537
+0.619041 0.736713
+9.24399 9.50151
+8.57184 9.88538
+2.82682 3.77294
+4.2649 4.84602
+8.6621 8.96426
+8.04469 8.3189
+7.81877 8.42944
+2.78031 5.16589
+1.23076 1.43577
+8.35385 8.49632
+3.27901 3.66774
+0.595941 1.41354
+3.37123 5.16685
+9.11003 9.95515
+-0.25959 0.32069
+1.44153 1.70148
+1.61595 1.70799
+7.8201 8.53423
+8.5402 9.36947
+8.39125 9.8221
+6.2909 6.35773
+0.000933745 0.920054
+-0.21358 0.491025
+4.00874 4.03866
+3.43552 3.55874
+7.85942 7.98987
+7.6681 8.06748
+6.19541 7.14765
+8.53891 8.96393
+2.38789 3.26866
+-0.0162847 1.18379
+1.04764 1.52755
+0.400798 0.55475
+6.32001 6.94897
+5.9692 6.2012
+1.20784 2.67873
+3.58247 4.46372
+-0.229647 0.559407
+5.65979 5.73489
+2.32795 2.78462
+0.706144 1.55147
+4.56527 4.6636
+5.98901 7.20908
+9.27329 9.95152
+1.31296 1.70529
+5.82933 6.41329
+4.17452 5.29881
+4.15885 5.25117
+0.35549 1.3511
+1.0591 2.4463
+8.87597 9.55625
+6.66826 8.57255
+0.355945 1.40613
+5.39729 6.10218
+3.78791 4.37501
+9.53885 9.87184
+2.67568 2.82552
+4.44836 4.52939
+5.96764 7.40168
+6.35578 6.98546
+0.636857 1.19517
+3.3986 5.55448
+1.46493 2.66884
+-0.0676901 1.80921
+7.83396 8.53452
+8.3508 9.04561
+4.03407 6.0066
+0.997538 3.30635
+7.83064 8.03466
+4.57652 4.97461
+3.85952 4.15471
+0.960261 2.1069
+0.522458 1.52989
+8.81627 9.00768
+0.172256 1.29455
+5.69294 6.15752
+6.86391 7.75307
+2.32429 2.95415
+1.83191 1.90364
+0.400855 0.705649
+5.23264 5.39972
+5.19047 5.79842
+2.40804 2.89401
+0.462887 1.43874
+6.70213 7.90229
+4.37985 4.95797
+3.73768 4.30645
+0.756797 2.11146
+0.458724 0.472099
+3.93098 6.47147
+5.5294 6.00365
+2.97106 3.42174
+5.75875 5.80235
+7.96799 9.02105
+5.36254 7.22823
+6.56124 7.39973
+9.49234 9.57879
+2.87576 3.59509
+3.49182 4.28124
+8.68021 9.94486
+9.60199 10.1276
+9.70115 9.81776
+3.09609 3.98732
+5.00113 8.15031
+5.21248 5.74835
+9.23337 9.5696
+2.92777 3.56297
+2.52044 3.04905
+4.79908 5.05762
+1.98626 3.69659
+4.78726 6.20637
+7.39711 7.42831
+4.44319 4.78716
+9.28452 10.0832
+8.00774 8.85707
+9.22947 10.0523
+4.38653 4.86012
+5.15285 5.23106
+8.95413 9.75947
+2.90286 3.32407
+0.348694 1.39738
+-0.0660432 0.293424
+4.09079 4.2922
+6.0407 7.23031
+2.83771 3.72237
+8.54697 9.38898
+2.16742 3.45018
+8.83255 9.30343
+3.59112 3.6531
+7.53452 7.81898
+7.11781 7.19773
+8.2892 10.0259
+4.91072 5.06031
+5.8232 7.25924
+7.0641 8.31604
+9.477 9.63892
+5.8003 6.58306
+9.63988 10.2754
+0.654364 1.02398
+5.9488 6.85043
+7.86867 8.99891
+9.202 9.46902
+4.17932 4.20271
+6.50328 6.71085
+7.19848 8.15579
+5.62459 5.75449
+-0.159668 0.791409
+7.55683 8.7315
+1.03278 1.423
+0.751457 0.808785
+6.2203 6.50634
+1.64418 2.98238
+6.87468 7.00652
+6.36966 6.7117
+7.69893 8.89535
+0.419794 1.05032
+2.73928 4.31548
+0.409245 1.55228
+6.03905 6.39323
+0.409695 0.789834
+4.39148 4.40935
+1.14673 3.23607
+5.85562 6.44503
+6.87394 6.88742
+3.761 4.35136
+7.2208 8.01436
+6.49839 6.54002
+4.70791 5.91886
+4.24906 5.96619
+2.53482 3.91496
+-0.369254 0.69193
+4.81351 6.31088
+9.76066 10.0736
+1.4413 1.55942
+7.21917 8.88908
+6.03521 7.56826
+1.25568 1.42024
+5.47575 6.04431
+1.43099 1.99979
+5.1004 6.04088
+6.54798 6.56118
+1.0142 3.1564
+1.75267 2.1453
+1.28133 1.36044
+9.60996 10.0563
+1.14397 1.50247
+6.86688 7.08724
+8.38287 9.18041
+0.132076 1.27657
+6.52553 6.9301
+0.223917 1.41325
+1.18902 1.79753
+1.40084 1.75678
+1.94524 2.51929
+1.98276 2.62875
+0.763281 1.05483
+7.97952 8.51249
+1.059 3.05463
+5.33401 5.85094
+8.37442 8.64374
+6.62865 6.67315
+1.01707 1.64386
+0.113335 2.23523
+6.71906 8.00216
+-0.886574 1.29366
+4.20078 4.85294
+8.43336 9.06988
+3.55413 4.40768
+6.69076 9.01132
+6.18982 7.14109
+7.14381 7.7046
+8.63195 9.47031
+8.88052 9.84886
+3.34443 3.62637
+4.5862 4.72832
+4.95757 5.23571
+2.85993 4.04966
+1.43846 2.27425
+5.43112 6.30496
+-0.452609 1.55525
+7.17706 7.71287
+5.78537 5.79579
+8.51102 8.9466
+-0.472904 0.810489
+3.83688 4.24045
+8.04432 9.04582
+1.57259 3.37136
+1.22231 1.33582
+5.73006 6.26477
+2.90855 4.22125
+9.39717 9.4287
+3.63873 4.16094
+0.442035 2.08889
+0.294491 1.31124
+3.14755 3.86305
+6.57634 9.44898
+2.19051 2.41878
+4.99277 5.12569
+4.10425 4.9423
+4.83547 5.62769
+5.73879 5.78179
+8.90329 9.81905
+5.60168 6.17538
+5.83843 6.66128
+1.84271 2.57406
+3.01047 3.33662
+2.85037 3.79158
+3.49007 4.46877
+8.58942 9.51529
+0.613753 1.12824
+8.23757 9.54707
+9.27134 9.4196
+6.27126 6.56417
+2.17206 2.33018
+3.53588 5.17162
+8.6312 10.0868
+5.76342 6.66164
+9.01501 9.90984
+3.22004 4.18954
+4.37918 4.68595
+2.00928 3.49815
+6.64229 7.06693
+2.85962 4.58794
+8.45587 9.8897
+2.8481 3.65956
+8.65849 8.67336
+6.48486 6.58637
+5.82336 7.45254
+4.02267 4.59696
+2.24997 2.83815
+8.16201 8.55518
+7.40645 9.07085
+1.43137 1.50333
+8.7212 10.9419
+1.50523 2.44124
+1.92455 2.85819
+4.50866 4.53052
+5.75781 5.81275
+1.71013 2.0282
+9.31592 9.9015
+6.14972 8.18798
+1.85705 2.20068
+4.80971 5.10509
+3.31201 3.58168
+8.61824 9.31861
+7.19497 7.86933
+3.25381 4.53472
+5.62799 6.29537
+9.00659 10.021
+9.15156 9.74827
+2.0324 2.80741
+0.714403 1.00476
+1.26522 1.80417
+-0.362995 0.41758
+7.08785 7.71544
+5.55685 5.74045
+0.428866 3.03773
+7.61574 8.94894
+9.07256 9.69772
+4.49537 5.06822
+5.66388 6.48899
+1.69126 2.69607
+9.90539 10.0783
+6.56455 8.27128
+6.61988 7.86616
+7.42012 7.64493
+2.99922 3.35282
+4.69379 5.18947
+0.87894 1.30518
+9.47632 9.61234
+0.665754 0.855958
+-0.422778 2.11197
+3.38786 4.15441
+7.57236 8.75855
+1.89832 3.50224
+-0.185929 1.0777
+3.32911 5.53465
+6.91111 8.69247
+6.97456 7.86905
+4.75518 5.0948
+4.23733 5.83368
+8.52456 8.56086
+0.0978267 0.136564
+7.4668 7.99757
+5.52851 5.80858
+8.5833 8.88589
+5.10603 6.41348
+4.70682 6.59981
+8.60265 9.19477
+5.04514 6.24014
+4.49041 4.88669
+7.40925 9.15624
+0.80364 1.35315
+7.11604 8.01153
+0.267749 0.714089
+0.121521 0.822226
+9.30556 9.81307
+2.11398 2.92567
+5.97722 6.08022
+7.13483 7.22211
+8.00161 9.27274
+4.87681 5.51654
+3.11843 3.84311
+5.17747 5.98482
+3.6077 4.46306
+1.37454 2.2443
+4.93385 5.96357
+2.92184 4.0964
+4.88767 5.56353
+2.87394 3.76336
+0.326521 0.622872
+2.42056 2.45007
+-0.527891 0.827211
+6.73151 7.20155
+1.82048 2.54905
+1.35563 1.88701
+3.64202 4.10669
+5.22846 5.23953
+6.06271 6.46993
+2.71418 3.2081
+6.41179 7.57176
+7.45823 7.79609
+1.01227 1.39137
+9.0872 9.20132
+5.083 5.64038
+5.63236 5.97945
+-0.317645 0.822313
+0.865396 2.65587
+5.71839 5.98983
+1.50978 2.08611
+2.95824 3.70996
+0.264301 1.02233
+8.22351 8.98589
+4.87805 5.24127
+2.31329 3.46752
+6.19539 6.69676
+5.18643 5.40947
+7.15453 7.66643
+1.20694 2.25111
+7.87378 7.89093
+5.16514 5.604
+8.68354 9.01395
+7.33753 9.37499
+2.94627 4.06036
+8.64337 8.85727
+0.0353092 1.0128
+6.98437 7.35718
+6.77073 6.79959
+3.13559 3.70735
+7.40139 8.27017
+4.01174 4.39788
+3.22281 5.11647
+7.79256 8.58737
+0.642233 1.39694
+7.18603 8.69453
+3.37803 3.59355
+0.762287 0.84262
+4.21823 4.52565
+0.894924 1.35434
+0.844327 1.19938
+5.57958 7.05431
+-0.631066 1.55134
+3.78962 4.17935
+9.15329 10.4824
+5.47536 5.52975
+8.81243 9.16088
+4.45989 4.94123
+8.68235 9.45112
+8.04719 10.3938
+8.87349 9.40483
+0.502543 0.570283
+2.08512 2.47652
+-0.654512 0.804355
+3.68569 5.21711
+5.33017 5.80226
+3.44991 5.31415
+-0.00417763 2.95077
+7.17784 7.9318
+1.2721 1.31642
+5.24415 5.64173
+2.79434 3.28746
+4.54991 6.49276
+4.74707 5.12555
+7.36365 8.15777
+0.913049 1.79828
+1.47498 1.83425
+2.64271 3.38567
+4.78159 5.44718
+7.6087 7.66442
+-0.484393 0.909893
+3.16824 3.23757
+4.43021 5.90284
+4.25954 4.74995
+6.58742 7.24125
+1.86151 2.27069
+3.16459 4.5945
+1.06471 2.08965
+3.31028 3.83029
+1.52593 2.47521
+0.703789 1.42451
+1.47969 1.68923
+2.92352 4.24089
+9.84088 9.93485
+3.18205 4.27817
+7.39345 7.78945
+3.78808 5.41572
+4.38624 6.75693
+6.93065 7.16977
+1.01289 2.19807
+3.37006 3.54196
+5.50238 5.58285
+-0.225113 1.99347
+1.67796 1.86943
+6.1999 6.35102
+3.80494 4.74814
+1.13294 2.02639
+1.1965 2.6548
+-0.284453 0.856092
+4.26565 5.02196
+9.66948 9.88874
+6.20287 6.25528
+4.38154 6.65806
+3.77411 4.3075
+5.77177 6.78486
+9.16311 9.816
+3.22861 3.42009
+3.36573 4.34724
+6.76951 7.58025
+4.83813 5.23042
+3.87192 4.37372
+5.56859 5.90066
+-0.368163 1.4593
+5.44031 7.81671
+2.66342 2.99253
+6.11846 7.69499
+4.98811 5.17531
+4.45078 4.67513
+4.88206 4.94128
+2.51813 3.0268
+0.461292 1.15264
+2.34766 4.48652
+0.198819 2.23425
+6.85634 6.98248
+0.912438 1.81872
+4.84933 6.34912
+5.15613 5.82891
+0.172772 0.994083
+3.37381 3.64549
+1.98836 3.2697
+1.64344 2.06049
+0.766585 3.09305
+7.8979 8.28046
+4.34856 5.01341
+6.69809 7.24239
+5.19034 7.04959
+5.3747 6.92123
+7.8893 10.1251
+6.11207 6.99125
+5.37115 6.84111
+9.04786 9.11002
+6.45326 6.64415
+-0.76294 0.92832
+0.980411 1.8166
+3.05536 3.50031
+6.10827 7.55786
+6.57848 9.06264
+7.66855 8.861
+4.80276 4.82283
+1.99932 3.2877
+9.45229 9.80653
+0.457474 0.778684
+5.44444 5.95239
+5.60974 8.05169
+7.64656 7.79632
+6.78372 7.65134
+6.93878 7.82023
+9.08292 9.55308
+9.16329 9.25802
+1.4909 2.38688
+4.31881 5.3564
+5.12535 5.60119
+2.44591 2.54637
+7.36929 7.80452
+2.13707 2.97655
+9.73557 9.94588
+1.96637 3.36097
+0.857068 2.29643
+5.58224 5.91142
+8.90714 9.0255
+9.77988 10.0711
+0.41121 0.970955
+-0.518356 0.91447
+7.58725 7.71255
+8.1435 8.78712
+6.5487 7.17991
+4.94961 5.50283
+8.14086 9.03281
+3.51281 5.24806
+3.5786 3.84066
+6.27435 8.37735
+8.65263 9.5555
+2.87484 3.56117
+5.57707 6.55879
+-0.111276 0.264178
+3.60894 4.15477
+2.82322 3.64397
+8.40669 9.1127
+8.43089 10.5298
+1.38472 2.2453
+1.74464 2.00472
+4.01588 4.67572
+0.408869 0.938602
+2.06155 3.46067
+4.4871 5.08963
+2.4435 3.87355
+1.32864 2.55801
+4.78579 5.26122
+7.43027 7.57749
+6.90971 7.32716
+8.01095 9.46872
+9.41627 10.524
+8.83143 10.4474
+0.631816 1.75513
+1.72965 2.17123
+-0.513239 1.1886
+6.75616 6.7984
+2.49278 4.26493
+0.230011 0.966298
+3.78506 4.95013
+2.03886 3.14808
+7.87309 10.5637
+3.54564 3.58055
+1.91974 2.9194
+4.8503 4.98668
+4.66494 4.83558
+7.57916 8.24358
+4.78743 5.38547
+2.81034 3.34534
+1.00297 2.0138
+6.87593 7.17736
+3.93157 5.0655
+3.10361 4.05519
+8.22876 8.38326
+7.48377 8.31026
+2.23106 3.4905
+0.130934 0.606709
+1.22344 2.55898
+7.55829 7.92597
+4.10977 4.86263
+0.122756 0.264176
+3.8357 4.15854
+1.28414 2.13031
+0.280029 0.805504
+2.88245 4.1704
+5.57936 6.94781
+6.22719 6.33201
+-0.761013 1.16475
+6.16636 7.12566
+2.98935 3.192
+2.23263 2.34362
+3.9082 4.11692
+2.66865 3.5275
+1.87676 2.43966
+4.60035 5.39332
+2.74287 3.73097
+2.81953 3.96666
+5.73644 6.04042
+4.02179 4.52419
+3.26438 4.07346
+1.22509 2.13719
+7.91885 9.71846
+1.28152 1.48079
+7.97918 9.26344
+8.75682 9.8677
+7.25678 7.45362
+8.16161 8.87066
+1.21873 2.37224
+7.76739 9.06346
+3.89932 5.03406
+3.53901 4.37006
+2.93795 4.04333
+6.36543 6.72985
+4.72622 4.98804
+1.86205 1.99008
+0.784581 2.05264
+0.978519 2.91723
+3.9067 6.47195
+0.735425 2.38151
+8.37394 8.41609
+6.91804 7.23374
+9.39259 10.1026
+7.28732 7.43466
+4.75982 5.44264
+6.71504 7.53933
+2.17125 2.54358
+0.703562 1.39087
+-0.221711 0.541965
+9.22839 9.39159
+9.53465 9.97585
+1.44304 2.53666
+7.886 8.85051
+9.33174 10.1632
+2.60898 3.42889
+1.73658 2.02589
+6.31651 6.77762
+7.26755 8.34499
+9.01312 10.9837
+7.47361 8.96251
+7.98365 8.02586
+1.40065 3.44891
+9.44617 9.55391
+8.24265 9.34849
+9.366 10.4216
+0.375354 1.17522
+3.37114 3.38278
+-0.742469 1.07634
+4.29988 4.81879
+4.18605 7.21928
+7.41047 8.29198
+6.68173 7.60225
+3.24292 3.30695
+1.8951 3.42167
+3.97359 4.2857
+4.72621 5.80575
+4.75014 5.02239
+6.43454 6.94568
+7.16601 8.10355
+2.16685 2.23666
+6.70852 8.63284
+8.16988 8.95848
+0.277002 1.30648
+1.5803 2.28632
+2.22634 2.34679
+0.200623 0.814959
+5.27457 6.51651
+2.49533 2.90705
+6.48922 6.69528
+8.18879 8.63551
+2.75159 3.633
+0.884853 1.56434
+1.87488 3.98951
+4.24783 5.17713
+6.22499 6.56095
+5.68238 5.99272
+3.75553 3.85012
+4.87543 5.39966
+6.62671 8.72493
+3.50262 4.05131
+5.38952 5.4974
+7.84971 7.94051
+5.39123 6.66564
+5.43986 6.17256
+7.48968 7.7677
+4.2685 4.57296
+1.75169 4.11058
+5.03634 5.16102
+4.68003 4.84715
+8.36249 9.98761
+8.94297 10.6969
+6.21572 6.24305
+7.90303 8.0672
+7.90426 8.41244
+5.98512 7.93187
+5.13297 5.27136
+6.58367 7.4971
+4.72663 5.22956
+7.99667 8.59246
+4.3303 5.92188
+1.3132 1.80875
+7.70104 9.20947
+1.78862 2.00473
+9.63678 9.65571
+-0.264416 0.318054
+2.70004 3.40777
+2.74642 3.73608
+3.6494 3.6743
+8.03113 9.22851
+1.07526 1.3116
+4.05436 5.33291
+4.60907 6.03605
+7.83426 9.10358
+2.27997 2.77309
+5.63139 6.92616
+4.40717 5.25214
+1.98986 3.5062
+2.42393 2.9584
+1.94336 3.08456
+1.20185 3.01827
+0.641733 2.10095
+7.25046 8.29391
+0.640392 1.26451
+3.9588 4.85492
+6.83036 7.41101
+6.48581 7.08757
+6.48734 8.47856
+9.55084 10.3774
+-0.173137 1.26574
+2.32702 2.58775
+2.7463 3.13914
+7.86951 8.62807
+5.96916 7.92759
+0.217046 1.70373
+1.04207 1.05755
+4.79058 5.07902
+4.19024 5.35395
+9.00175 9.83715
+8.37554 9.275
+4.5204 4.82999
+3.49936 4.75519
+7.07916 7.74619
+6.66726 7.35282
+7.39513 8.55523
+7.50381 9.60708
+1.39304 2.26927
+2.84101 4.76376
+1.21779 1.59353
+4.7893 5.70143
+9.12195 9.57131
+5.40461 6.15443
+2.86445 4.26837
+8.01324 10.9082
+2.96659 3.8042
+2.4897 4.59323
+6.37887 7.15878
+7.00143 7.6419
+3.22491 3.41843
+1.22852 3.31783
+2.09881 2.56121
+4.43205 4.67051
+4.39328 4.66715
+2.38355 3.39058
+0.638802 1.59399
+5.32717 5.81376
+8.00353 9.72007
+8.77281 9.81649
+8.95552 9.86609
+2.90915 3.96556
+3.88176 4.93124
+6.45945 7.69942
+-0.108577 1.57424
+0.304992 0.320561
+6.47789 6.5515
+1.98211 2.05312
+6.2741 7.35626
+9.45057 9.67918
+5.2916 5.48037
+0.158802 0.712187
+6.42002 6.84323
+9.11085 9.13063
+9.42446 9.95882
+6.03624 6.96469
+9.2473 9.6286
+7.10342 8.71163
+3.34072 3.35187
+7.4602 8.58506
+8.7963 8.81873
+0.323615 2.22687
+0.326746 1.76681
+2.20062 2.76862
+7.55181 7.85006
+0.941035 1.28117
+8.76643 9.60019
+9.19731 9.33092
+6.0479 6.57293
+6.12725 6.24356
+7.53078 8.92488
+3.1841 3.48283
+1.85544 2.01888
+7.3849 9.29183
+5.03915 5.27721
+4.77142 5.46282
+-0.291696 1.14641
+1.61367 2.20867
+5.31853 6.69431
+2.52731 3.13139
+4.86677 5.18106
+4.50183 4.60969
+5.95881 6.09964
+2.41939 4.42026
+6.92003 7.17891
+4.29584 5.48557
+8.02803 9.06315
+2.82326 3.49599
+5.8647 5.87561
+2.38814 3.62688
+6.32418 7.17662
+5.99907 6.5059
+3.84698 4.14446
+9.80728 9.82132
+5.2366 6.30871
+9.81878 9.91004
+1.53024 1.83525
+2.98035 3.68531
+4.5418 6.98786
+5.19561 5.9846
+0.946068 1.46672
+3.26948 4.71928
+6.13476 7.68682
+8.36934 9.65072
+6.40074 7.14762
+1.01349 1.80493
+8.4514 10.25
+-0.180382 0.682704
+1.03041 1.63565
+5.64642 6.96069
+2.73598 3.67485
+5.8705 6.66157
+4.68343 4.7176
+5.83787 7.6818
+1.42529 2.234
+3.73726 4.19241
+5.38341 5.81884
+1.13088 1.69073
+0.968034 1.98828
+1.06007 1.11039
+3.50129 4.51807
+5.83133 6.77904
+-0.334945 1.29129
+0.326706 1.16015
+9.15028 10.4391
+5.13047 6.79712
+1.06952 1.38997
+5.79345 6.49898
+7.88149 8.5143
+8.00404 8.09794
+8.22725 8.28904
+6.38406 6.61356
+6.32166 6.73458
+7.17066 7.32049
+1.64338 3.79327
+7.92135 8.55568
+7.15578 7.42231
+6.70701 7.65427
+5.76608 7.63064
+3.54163 4.08662
+3.81402 6.76906
+4.5998 4.61865
+9.01471 9.18718
+5.21234 5.73335
+0.946018 1.39917
+6.99714 8.29739
+5.64458 6.93965
+3.39809 5.70907
+6.32284 6.83604
+8.50347 8.53097
+3.90118 4.85721
+9.41198 9.62076
+4.41514 5.55152
+7.69979 7.81249
+5.34434 5.37105
+7.25274 7.76114
+7.67383 7.92718
+5.82851 6.29417
+0.935651 1.2842
+0.639586 0.786771
+6.39823 8.31226
+3.67546 4.89035
+9.20323 9.57287
+2.33896 2.99576
+8.51933 8.80243
+0.983098 1.11084
+8.48215 9.42998
+7.29586 7.3914
+2.00695 2.89046
+2.60909 2.62433
+2.04118 2.92033
+7.60386 9.01419
+7.32896 7.73342
+9.51693 9.54891
+5.1323 5.24962
+6.35326 7.18302
+2.50952 3.51872
+3.4149 3.57431
+9.18412 10.4976
+5.68123 6.42697
+5.87758 6.0124
+6.3202 6.64588
+8.2547 9.98176
+5.50949 5.7854
+0.0824268 0.128178
+2.17292 3.76233
+7.22786 7.68214
+5.09326 6.4151
+4.30171 4.86688
+2.39206 3.47399
+7.95152 8.35556
+2.40133 2.936
+2.77819 3.87516
+3.252 4.33376
+9.54269 9.7513
+6.6747 6.73043
+0.611474 1.97158
+7.65864 8.53689
+1.58345 1.8017
+2.56917 2.8152
+8.5424 8.8301
+4.98159 5.44499
+5.82482 6.03578
+3.55509 4.90785
+5.77028 5.94747
+0.163965 1.1379
+2.85039 2.94261
+4.24343 4.67273
+3.22636 4.06084
+6.03662 6.21018
+4.55495 5.07697
+1.91173 2.51739
+6.54894 7.24036
+5.55502 6.92676
+0.245707 0.586188
+2.28044 3.29563
+4.71378 5.25198
+8.28953 8.44891
+9.42282 10.179
+5.0548 5.73614
+6.3203 6.43659
+6.54178 8.82077
+3.67181 4.17365
+8.51445 8.96445
+1.69648 2.84524
+0.194222 0.920147
+2.48533 2.59803
+1.66002 1.6739
+4.79833 4.95404
+1.09801 1.11009
+6.62529 7.4066
+8.0099 8.37262
+3.55429 4.11824
+6.2666 7.12137
+7.83222 8.01342
+9.37156 9.72961
+1.1647 4.04434
+4.50719 5.09068
+3.25175 3.75482
+8.28659 9.30848
+7.30009 8.60755
+-1.12073 1.21016
+0.310087 0.725712
+8.3746 9.13511
+9.11925 10.2234
+9.68703 9.7137
+0.603098 0.844291
+5.88373 6.99327
+0.852802 1.43297
+3.7463 5.82283
+7.69639 8.25446
+-0.337322 0.977113
+8.76606 9.16618
+3.43527 3.6616
+3.93587 5.39471
+5.66569 7.20462
+5.34999 5.7193
+3.25589 3.706
+1.52012 2.55985
+4.74228 5.43725
+5.15323 5.51652
+7.77237 8.33717
+-0.0514419 0.914127
+9.27182 9.59476
+8.14192 9.74859
+6.42702 7.20331
+7.51351 7.68358
+7.0947 7.46059
+7.97635 8.59449
+2.39931 2.66008
+5.79481 5.94673
+4.41054 4.81613
+2.72202 3.61239
+2.86039 3.44719
+1.81115 3.28151
+-0.566995 0.734214
+9.61998 9.72024
+7.4163 7.61821
+0.42522 0.552659
+3.17617 4.36942
+0.740294 1.36953
+7.13755 8.39966
+0.219186 0.892588
+3.78307 5.2905
+0.783026 1.76155
+3.01893 3.33055
+3.12143 3.5713
+-0.792679 0.92539
+0.668572 1.12961
+3.88619 4.30545
+7.59276 8.1776
+4.71509 5.05622
+6.53406 7.04242
+1.581 2.21984
+4.7144 5.51372
+2.76338 3.50211
+0.16364 0.293599
+5.92365 6.10636
+3.11174 4.29165
+5.49295 6.48717
+-0.503239 0.795707
+7.30558 8.12408
+2.10674 4.13456
+7.11985 8.01932
+1.34672 1.48739
+4.05778 5.69084
+2.83686 2.9115
+6.4471 6.53909
+0.467374 1.84371
+2.76467 2.94177
+4.87867 5.33932
+0.892878 1.96273
+1.13934 2.27205
+7.76918 8.39409
+6.72181 7.43901
+7.0836 8.68472
+7.12924 7.56332
+0.689172 1.62922
+9.41146 9.91043
+0.398265 1.27579
+6.29966 7.4874
+5.09438 5.65334
+6.04623 6.4687
+5.75305 6.89731
+0.308118 0.459501
+3.63692 4.30501
+3.1755 3.71009
+7.32787 7.52785
+2.23235 4.09978
+2.71191 2.91513
+0.209457 0.840713
+7.31489 7.38296
+6.21245 6.91111
+5.75983 5.96049
+5.92056 8.24518
+-0.354452 0.489638
+4.05894 5.34828
+1.56299 1.57414
+2.85083 3.27455
+8.78323 10.0012
+0.208502 1.26471
+6.10824 6.79285
+5.55114 8.03968
+6.13077 6.32342
+7.34865 7.82592
+3.94835 4.75016
+7.8268 8.72249
+4.85131 5.07903
+5.40398 6.0134
+2.85971 3.85293
+0.126379 1.45545
+3.15768 4.28388
+9.64566 9.70016
+4.47514 6.31064
+6.44995 7.2894
+4.70992 6.13777
+3.91128 4.22263
+7.35627 8.07739
+2.49215 2.68749
+8.09946 9.16929
+0.925679 1.92784
+8.48437 8.63892
+7.2255 9.18109
+-0.00840282 0.0168954
+5.91933 6.6274
+4.16086 4.64302
+8.27009 8.47868
+1.73372 2.93094
+8.17421 9.17705
+9.19136 9.43222
+0.0653594 0.648416
+8.69 8.96184
+8.99355 9.40832
+6.25088 6.26945
+6.72391 7.38424
+9.59708 10.3496
+6.00971 6.18818
+4.64468 5.75797
+3.64832 5.30079
+5.99378 7.8792
+6.5388 6.99379
+7.31694 8.43802
+3.66227 4.92638
+9.55964 10.3796
+-0.14433 0.29095
+3.56716 3.71252
+3.82062 4.27788
+8.10405 9.35275
+7.17891 7.46539
+1.17698 1.29602
+4.48829 5.03134
+7.18025 8.13852
+9.42388 10.3634
+5.2158 6.17469
+5.22926 6.52397
+5.16731 6.40625
+6.53348 7.269
+2.07834 2.39172
+9.65044 10.1519
+8.64551 10.1294
+9.29006 10.5993
+1.50639 2.83173
+5.71675 5.99216
+3.0783 3.35571
+0.115401 1.31431
+8.03988 8.11942
+3.11917 4.53956
+1.14552 1.1646
+5.34782 6.43017
+0.0701702 1.0368
+0.183335 0.440704
+6.33438 7.71607
+2.11533 2.64323
+7.12104 7.13366
+7.21548 8.26968
+3.13445 4.13568
+4.57452 4.74602
+2.60889 3.69846
+7.21184 7.47573
+6.87651 7.03405
+2.65431 3.94352
+1.50006 1.70087
+6.16344 7.54429
+7.02057 7.73067
+8.27833 9.01489
+0.500833 0.597845
+8.34751 9.88925
+2.80242 2.91837
+5.29424 6.079
+8.36276 9.10074
+0.216887 0.268335
+1.30798 3.16393
+3.93851 4.22658
+2.58028 3.14744
+9.31131 10.3451
+7.37262 8.84852
+4.45306 5.6723
+3.74535 4.0721
+4.90174 5.63875
+3.41847 4.65199
+3.10265 3.82548
+6.56126 6.97557
+2.57449 2.95098
+7.97418 9.06301
+9.2203 9.66829
+4.64922 4.96305
+8.83034 10.115
+6.6685 6.89847
+7.36585 7.48669
+8.66761 9.39287
+0.562216 0.961875
+7.56292 7.81006
+8.50715 8.95572
+0.572825 2.24755
+5.9367 6.06766
+-0.769578 0.776163
+4.48224 4.9553
+8.21069 9.29643
+8.57206 9.47175
+1.10032 1.21371
+3.76306 3.87152
+6.46197 8.18457
+6.96501 9.70727
+3.42357 3.93484
+0.818601 2.42743
+-0.119739 0.397938
+-0.378761 0.523892
+8.03394 9.35409
+3.60283 3.98864
+2.21789 2.70607
+-0.255329 0.319063
+6.20806 6.22609
+7.1283 8.04391
+3.73565 4.03638
+8.5374 9.10987
+5.22675 5.35072
+7.51777 7.58439
+9.12636 10.4159
+9.15003 9.40672
+0.217863 1.19883
+9.42416 9.9178
+2.55337 3.8088
+7.03655 7.98242
+9.17171 9.8047
+0.110162 0.722738
+3.16467 3.58897
+6.47244 7.12961
+1.0456 1.65614
+1.58456 1.62844
+1.79039 1.84035
+6.24286 7.07838
+9.08631 9.11684
+3.05068 3.40838
+2.81212 4.03665
+2.52011 3.09841
+8.06001 8.16356
+7.07649 7.52685
+2.47666 2.86548
+8.66241 8.95103
+-0.298116 0.662697
+0.822443 2.46125
+2.07619 2.33674
+4.84135 6.21034
+7.49625 8.13026
+7.85854 8.29618
+3.01722 3.37062
+6.54393 7.30306
+2.21113 2.30166
+8.32138 8.57349
+6.2995 6.33514
+3.0018 3.56886
+4.63378 5.52214
+6.71908 8.96715
+2.29809 2.95581
+8.34947 8.71096
+4.96902 5.32075
+9.51051 9.72733
+3.311 4.77789
+3.50233 3.66309
+4.95177 5.76002
+6.12876 7.22391
+6.27743 6.79393
+3.60638 3.6833
+5.20305 5.50848
+7.16065 8.88358
+9.45049 10.2539
+6.16892 7.0314
+8.08479 9.74516
+0.0717867 0.669987
+2.17569 3.34098
+4.81716 5.7509
+7.63999 8.01157
+5.87228 6.60363
+3.39621 4.35575
+4.96079 5.07901
+7.57639 8.82003
+8.27285 8.52609
+0.665858 1.64782
+1.74256 2.07126
+6.19512 6.4258
+0.664592 1.30896
+0.180682 1.43746
+6.46752 6.81303
+2.55562 3.08708
+9.33695 9.63312
+6.33821 6.77092
+7.88252 8.55026
+8.17937 8.45385
+-0.415294 0.793096
+5.22077 5.54553
+8.67808 9.10041
+1.72096 1.92024
+0.492778 1.48076
+2.29514 2.88531
+0.0934389 1.37614
+8.40297 9.11121
+3.66605 3.91717
+-0.274468 0.867811
+9.41428 9.56659
+1.22657 2.12792
+8.71336 9.85384
+5.09347 5.42905
+2.02877 2.36652
+5.99112 7.40703
+0.911618 3.48138
+4.84352 5.11131
+1.16309 2.08613
+5.58561 5.84805
+0.663543 1.08921
+1.83189 3.93269
+4.07731 4.38879
+4.04789 4.9989
+2.09457 3.61279
+2.00982 2.94396
+7.37537 7.66574
+5.08648 5.80122
+9.19959 10.2263
+4.26136 4.86194
+6.67875 7.61134
+1.27462 2.48399
+7.2237 7.82324
+-0.0141009 0.0441377
+8.32069 8.36192
+2.82562 3.0717
+-0.528918 1.25301
+1.90486 3.04714
+1.34489 1.75301
+3.14332 4.03322
+8.55351 10.8681
+9.09824 10.3828
+0.496868 0.622499
+7.11112 7.62765
+0.335233 0.528962
+6.71335 7.13937
+6.78574 7.71172
+9.13568 9.22251
+7.10299 7.64765
+3.64747 4.06685
+8.64041 9.40111
+2.43515 2.93081
+2.95476 3.68588
+0.0863751 0.777976
+6.5891 8.18165
+8.80986 10.0735
+0.568868 1.63785
+4.41677 5.42049
+8.72857 9.88426
+3.67467 4.25442
+8.98168 10.1087
+5.08611 5.50098
+1.28982 2.34422
+-0.914176 0.969847
+4.35042 4.42735
+4.02282 5.08164
+9.00566 9.4791
+2.71821 3.24065
+3.20252 3.24988
+8.61559 9.6733
+3.15157 4.7685
+3.59348 4.67872
+0.286864 0.36279
+8.40374 10.528
+7.53647 8.13523
+6.81591 6.90226
+7.68111 9.10704
+8.37958 8.73818
+3.25808 4.40893
+1.50348 3.00641
+0.20803 1.40949
+3.93771 4.84177
+2.79232 3.35329
+4.2666 4.63588
+0.341784 1.46241
+1.53063 2.06724
+8.58212 8.86194
+8.95411 9.70651
+8.71591 9.26292
+6.66088 6.7009
+3.95881 5.93917
+8.5823 8.76007
+-0.308958 0.34174
+1.03188 1.37677
+7.52675 9.84031
+4.27952 4.32984
+1.83465 2.27607
+8.12096 8.64922
+2.22605 4.40067
+0.00929139 0.871342
+0.376531 1.29354
+3.5257 4.30165
+1.95846 4.09589
+-0.200922 0.799272
+0.24432 1.76673
+4.73477 5.06514
+8.97059 9.2276
+2.89618 2.93969
+0.168256 1.03325
+3.44522 3.83622
+2.74889 2.76042
+6.07155 6.7979
+9.06484 9.09804
+7.56658 9.29215
+4.3084 5.45621
+-0.0786996 1.12809
+8.48249 9.74107
+6.4196 6.61469
+1.57119 1.87612
+3.15463 3.86251
+2.0089 2.57741
+6.53618 7.12035
+7.07901 7.29396
+0.114756 0.887413
+8.90806 9.65731
+4.0921 5.23407
+2.63441 2.92344
+4.31769 4.98832
+8.90336 9.26837
+8.25313 8.91204
+2.87758 4.00212
+-0.708243 0.789072
+3.28656 4.55872
+5.73177 5.80293
+5.40596 5.5844
+4.09318 4.57774
+6.16178 7.00613
+8.5514 10.5495
+6.83987 7.3056
+1.06341 1.97923
+7.82153 9.00722
+0.923069 1.42337
+1.83408 2.82331
+5.75305 7.23576
+0.241909 0.96721
+1.16645 2.10491
+5.41819 6.09839
+7.49242 7.69495
+0.347233 0.383681
+2.33245 2.53467
+4.91249 5.27759
+8.11182 9.2758
+0.0955456 0.548659
+-0.359909 0.48055
+1.64759 3.47097
+6.37855 7.40015
+0.423283 2.08857
+4.10068 4.46856
+2.58389 2.69626
+0.848483 2.72258
+8.67321 8.88903
+2.07607 3.42398
+3.11033 3.80741
+2.24735 3.48626
+8.11883 8.7687
+0.29959 1.41603
+4.84924 5.13641
+1.44102 1.74592
+1.13437 2.50296
+1.75876 3.09859
+4.75363 5.90838
+7.36423 8.20074
+5.51578 6.42652
+0.915633 1.86015
+9.44679 10.3479
+2.61691 3.60215
+6.26524 7.2538
+2.74326 3.12649
+5.83934 6.98592
+9.1111 10.4891
+2.27066 2.82709
+8.19359 8.67233
+0.834236 1.7066
+6.19288 7.21392
+-0.249843 0.891821
+2.5652 3.25132
+5.25356 5.88905
+3.99545 4.18918
+1.93186 2.51527
+4.44621 4.82421
+5.89181 7.36963
+2.77321 3.60627
+2.76444 3.88016
+2.50062 2.66105
+1.14846 1.66146
+2.951 4.81656
+3.81976 4.01061
+4.75674 5.59916
+6.74092 7.08289
+2.09989 2.32514
+0.220723 0.865303
+5.48107 5.71875
+1.48372 2.88941
+0.484577 1.12051
+8.93618 9.7185
+1.89769 3.65655
+2.0129 3.55214
+9.23173 10.3694
+0.286189 1.22753
+0.453785 1.55541
+2.24068 2.6541
+8.80917 10.4969
+7.12801 7.15222
+9.25745 9.9103
+5.73429 6.76901
+7.54454 8.47157
+1.96008 3.74997
+8.00837 9.25665
+1.66384 2.07613
+5.53014 5.97461
+-1.32495 1.33319
+4.58479 5.2263
+7.92048 8.75668
+6.87595 7.02522
+0.157713 0.389585
+7.48277 7.51261
+8.10714 8.38399
+0.0802723 0.587088
+1.13024 1.71135
+5.71769 6.84757
+3.08261 4.31054
+2.95952 5.09762
+6.62815 7.44256
+5.0805 5.8499
+3.38489 3.73265
+1.10644 2.18331
+4.70493 7.31686
+2.2253 2.6338
+0.778359 1.6265
+6.94211 7.2149
+4.20976 4.99342
+7.47792 7.67881
+7.06219 8.76137
+4.97677 6.12206
+6.30829 6.69361
+6.19977 6.76781
+9.67636 10.2172
+3.41958 3.69137
+0.374486 0.943711
+4.00837 4.80107
+8.85401 10.1325
+6.0938 7.8919
+1.51055 3.08998
+8.94594 10.3139
+1.06714 2.65511
+0.703202 0.850595
+4.87735 6.00659
+8.3067 8.39924
+7.78071 8.3155
+1.98737 2.81116
+6.86323 8.07974
+1.03479 1.34584
+0.490512 0.670211
+5.82122 6.1901
+5.50836 6.63385
+7.9192 8.9606
+0.913719 2.18983
+4.97151 5.70909
+4.19907 4.37712
+2.01188 2.63318
+7.84813 9.3771
+5.32667 7.48502
+8.50951 10.1006
+-0.551637 0.930509
+1.06511 2.23353
+1.91111 3.42663
+9.37528 9.55327
+7.27975 7.38741
+3.46676 4.83165
+7.36137 8.70333
+-0.295762 0.623228
+8.48558 8.81076
+2.71689 3.41873
+6.49265 8.11042
+5.25516 5.57336
+6.10462 7.05991
+8.76997 9.15164
+7.86196 8.30651
+7.82765 9.24604
+5.98573 6.34182
+6.45367 7.47857
+3.27018 5.10835
+1.3079 2.37423
+-0.261387 0.338113
+7.60683 8.81791
+4.7346 7.41988
+5.25597 5.28517
+3.76704 4.52226
+3.91774 6.66976
+5.69618 8.92667
+1.86148 3.07531
+5.57404 6.51438
+9.39049 9.77921
+2.38692 4.21416
+6.84909 7.23633
+7.2379 7.58761
+4.73485 6.11606
+7.80013 8.08105
+1.72701 3.40244
+2.44475 4.4072
+9.72565 9.77726
+3.35288 4.06493
+8.91215 9.92325
+8.67991 9.65865
+0.253195 0.764339
+4.23564 5.59497
+1.84752 2.14986
+-0.502957 0.528737
+1.32656 2.11347
+9.81563 10.0213
+7.60114 8.05035
+8.51797 8.83342
+-0.394604 1.41267
+7.71614 8.63514
+0.530249 0.968898
+2.90463 3.01675
+7.58098 8.71658
+-0.253747 1.28827
+1.832 2.39006
+7.2268 7.27225
+3.84076 4.66703
+2.2564 2.73185
+7.31508 8.46008
+4.99387 5.64948
+7.21239 7.79983
+7.60231 7.8473
+0.555482 1.41892
+1.25539 1.73665
+8.41561 8.96404
+5.06771 5.17664
+0.0655744 2.10718
+8.00222 8.65909
+7.48841 7.83609
+6.30909 6.89448
+9.1697 9.55942
+1.36259 2.22582
+-0.923854 0.994771
+3.43724 4.64053
+8.09411 8.19574
+4.84869 5.52805
+2.69802 3.4119
+9.0613 9.29405
+0.565216 0.687165
+5.93495 6.57426
+1.86925 2.75493
+1.41068 2.00824
+1.60612 1.62471
+3.11499 5.89909
+2.69806 3.90538
+3.76301 4.22135
+3.30065 4.70725
+5.56461 7.02137
+8.35335 8.99287
+4.79259 4.88508
+6.7911 7.52912
+8.14843 8.28583
+3.67629 5.06406
+5.71462 7.04747
+9.06721 9.99733
+4.87932 6.8586
+8.00814 9.57664
+7.03069 7.51623
+9.0989 9.57644
+2.70873 3.91296
+1.64425 1.7007
+6.53716 6.99033
+8.29874 8.74509
+1.88941 2.57626
+4.65337 5.23247
+9.04723 9.06665
+3.52258 3.61496
+1.1207 1.80143
+0.680601 1.98384
+2.94593 5.38692
+2.65685 2.67932
+9.00469 10.2054
+6.44318 7.2657
+4.66656 5.33893
+3.41719 4.72453
+3.12403 4.21748
+6.67973 6.81775
+3.54347 4.14978
+3.02554 3.50812
+3.91883 3.93657
+7.31721 7.89895
+1.86275 2.85473
+6.23266 6.4449
+7.59855 9.38013
+9.07084 9.49309
+0.557656 2.6851
+6.899 7.37693
+4.23162 5.84314
+8.54108 9.37672
+3.9513 4.79746
+7.299 8.29678
+5.58879 5.88551
+9.14992 9.22385
+9.1914 9.31788
+4.95663 5.56316
+2.16516 2.39538
+0.722262 1.89664
+7.76447 7.80026
+2.77772 3.39136
+9.59513 9.78635
+1.02728 1.2181
+7.32631 7.56611
+7.37389 7.46163
+6.87949 8.18689
+8.95602 9.81169
+5.85364 6.63434
+0.129136 2.13484
+7.09608 7.71167
+7.1487 8.34258
+7.48738 8.3172
+8.77247 9.95985
+7.6706 9.56828
+8.14268 8.61726
+6.5455 7.90871
+4.57866 4.78453
+3.63937 4.42349
+5.18905 5.36516
+4.68884 5.62995
+5.88338 7.83824
+-0.002979 0.145818
+4.42981 4.77141
+0.558593 1.07999
+6.91713 7.36159
+5.13948 6.20805
+3.34368 4.07112
+7.27365 7.8383
+9.6898 9.9514
+6.14332 6.75102
+2.16534 2.78843
+2.8007 4.37952
+7.67047 7.72955
+8.77377 9.85092
+1.26087 1.55193
+6.29788 6.58511
+7.68178 9.05777
+0.383336 1.21247
+2.55185 4.30874
+8.91971 9.21836
+3.67638 4.68596
+8.13843 9.13684
+-0.424353 1.97502
+2.71499 2.93977
+0.104447 0.387901
+4.09592 4.67009
+0.808593 0.920798
+5.01258 6.30662
+4.97668 6.57412
+8.44135 9.03816
+2.78932 3.72809
+6.71337 7.15128
+4.27234 4.50127
+6.78266 9.70351
+6.48026 7.51491
+7.36296 8.42283
+4.80339 7.3704
+6.24735 7.3132
+0.134626 0.364187
+2.73854 4.09422
+0.809997 1.19657
+6.41154 6.50244
+7.16847 8.56485
+1.53582 3.33985
+1.92874 2.86427
+6.95941 7.01378
+5.8592 6.54917
+2.51802 2.75622
+3.3894 3.6957
+2.2547 2.64693
+8.62054 9.1951
+8.86378 10.0003
+1.87892 2.28732
+3.83146 4.21484
+1.53262 1.99692
+7.86048 7.93125
+1.79437 2.68269
+3.92781 4.24119
+5.43044 5.47935
+0.322904 0.618854
+3.42383 5.18531
+4.00989 5.83612
+7.06304 8.76582
+5.88039 6.77654
+8.638 8.9479
+1.73391 2.09002
+1.04861 2.84779
+-0.313019 0.557659
+3.35245 4.1308
+9.05373 9.57205
+5.85684 6.49193
+6.00719 6.86421
+4.25244 4.65772
+5.15865 5.61529
+8.78498 9.77544
+8.33803 9.26452
+3.42915 4.92279
+8.29884 8.94035
+5.10232 5.35924
+4.33571 4.86695
+7.86184 7.90029
+7.34345 7.36214
+0.201624 0.800371
+9.05882 10.5503
+4.32188 5.03154
+-0.0456982 1.22298
+2.90921 3.60013
+1.69306 2.36564
+7.79029 9.15059
+4.65205 5.06538
+6.34552 8.32176
+7.92695 9.32585
+7.17903 8.09903
+9.53561 9.60287
+0.365723 1.23929
+0.542889 0.849053
+8.15061 8.93512
+6.40042 6.41053
+5.82666 6.5488
+1.00893 1.83717
+1.76021 2.11893
+7.61076 8.6242
+2.32513 3.4856
+4.39023 6.01094
+-0.11754 0.421848
+6.76371 6.94513
+4.67607 5.58732
+-0.201992 0.765553
+7.42926 7.44429
+2.57485 2.85339
+2.74138 4.13421
+8.21645 9.18107
+6.28184 6.4996
+7.129 7.74678
+7.76842 8.74924
+3.5359 4.35892
+3.04103 3.24376
+2.29389 2.92164
+6.96306 7.64415
+8.82053 9.04584
+1.19911 2.06167
+5.91357 7.6773
+0.150241 1.23291
+4.48681 5.41762
+6.89156 8.13443
+5.37828 5.79944
+2.13694 2.91102
+1.35932 2.08272
+6.14309 6.23278
+4.03202 5.88521
+7.23417 7.43704
+1.2501 2.60793
+2.12334 3.65727
+7.05722 8.77078
+0.437873 0.585933
+6.33338 9.16643
+2.44724 4.40234
+2.92012 3.64047
+1.2039 3.25195
+8.6611 10.0398
+8.0088 9.13622
+5.96562 7.08515
+5.45181 6.65246
+0.742546 2.38958
+4.12919 4.93571
+0.428823 0.84483
+1.45226 2.5869
+9.50727 10.0211
+7.69194 8.66273
+1.25706 2.44554
+5.23247 5.47762
+0.499178 1.70722
+7.26569 8.72467
+3.59815 5.50022
+1.03601 2.43445
+0.092414 0.927635
+3.7917 3.995
+6.21977 8.40398
+3.1513 3.81188
+9.80482 10.0951
+8.65564 9.33687
+2.06164 3.49152
+2.09754 2.34929
+0.66126 2.31888
+5.34832 6.82603
+7.91038 8.59105
+0.695523 0.800961
+2.33406 2.71629
+8.37774 10.9253
+9.7682 10.106
+9.44382 9.5743
+8.78009 9.47645
+1.87309 3.04127
+1.86724 2.13913
+3.30049 3.52416
+7.18508 7.6648
+1.3736 2.12153
+2.41879 5.06716
+1.87815 2.29743
+1.76646 2.06335
+9.73034 9.95475
+0.497489 0.686102
+6.96908 7.17338
+9.23111 10.0148
+3.30981 4.21787
+9.53311 10.3734
+-0.067709 0.147251
+8.44557 8.82047
+7.10407 7.47639
+0.834352 1.36908
+9.1598 10.6508
+4.22018 4.38279
+3.8295 3.95462
+3.97302 4.97247
+1.55856 2.31013
+0.0217962 0.486978
+1.69845 2.65786
+-0.489562 0.582187
+5.10621 5.6055
+9.8478 9.85919
+6.15389 6.92324
+7.11469 8.0418
+3.20625 3.78209
+5.93389 7.66892
+1.15134 1.18023
+6.84797 7.4239
+2.9483 3.22279
+-0.43205 0.764755
+7.17846 7.33313
+5.4729 8.26894
+6.19512 7.32132
+0.591934 0.767568
+0.49266 1.80691
+9.08272 9.72242
+5.85683 6.36905
+5.27625 7.13913
+3.60853 3.98155
+0.642811 1.10253
+1.27117 1.5329
+8.76096 9.61776
+4.9498 5.12847
+7.53282 7.80438
+1.40487 1.65657
+3.45329 3.84307
+3.25698 3.49614
+2.38651 2.89802
+8.23114 8.99016
+9.58516 10.4145
+5.5185 6.27733
+0.583068 0.892249
+1.93142 2.35084
+7.94845 9.22667
+2.47963 3.9005
+3.46106 3.86301
+7.77744 8.43735
+1.41072 1.73969
+9.12904 10.4307
+3.52227 3.66861
+5.4743 5.86487
+-0.51727 1.63657
+5.09861 7.03162
+5.14763 5.93411
+3.23526 3.47376
+0.9702 1.74063
+9.28366 10.3322
+1.80257 1.92265
+8.63597 9.08467
+4.16006 4.97753
+6.37418 6.39374
+5.82376 6.62429
+7.74751 8.68962
+1.63821 2.53399
+4.9864 6.40969
+0.680772 0.995608
+3.74344 3.83319
+0.898055 1.8593
+2.36839 2.39307
+7.21046 7.51006
+0.60893 2.91523
+3.15017 4.30412
+5.02219 6.28886
+4.60541 4.73379
+8.41196 8.58978
+8.84706 10.8198
+6.95807 7.54952
+5.54729 6.9315
+4.62574 4.73423
+3.35252 3.59865
+1.02207 1.71791
+3.16408 3.73993
+0.639222 1.69519
+7.57978 8.05813
+2.41371 2.77174
+8.65544 10.093
+6.31988 6.70758
+6.5301 8.39328
+0.578825 1.20331
+1.1243 2.07824
+5.86555 6.72397
+6.37103 6.81736
+1.12086 3.46541
+2.59503 3.44073
+5.27128 5.3616
+2.87331 3.4352
+5.48408 6.67916
+3.36016 4.09125
+0.813671 0.9811
+0.812162 3.22209
+6.85104 6.86306
+0.671311 0.979685
+2.75962 2.82659
+2.42186 2.49827
+7.82974 9.59669
+3.48851 3.60085
+8.47775 10.9574
+8.6863 10.6155
+0.196484 1.07469
+1.19293 1.45012
+5.79166 6.18466
+6.51597 6.6793
+9.78341 10.1992
+8.17879 9.59257
+6.96178 8.73165
+4.09161 4.31908
+3.19514 3.4072
+5.5101 6.32978
+0.188435 1.84481
+9.41738 10.0379
+1.46994 1.6294
+4.21915 5.39529
+5.46567 5.86638
+8.19414 9.201
+4.38616 4.55193
+2.31105 2.73345
+6.05897 6.12297
+8.84135 9.74232
+9.44943 10.2225
+3.27501 3.66059
+0.524904 1.74374
+7.7228 8.43799
+5.13274 5.82863
+8.2787 8.94491
+1.61463 2.03499
+7.04346 8.69977
+0.938308 2.38676
+0.00208037 0.0186158
+1.98744 2.05864
+7.05787 8.16211
+1.68383 2.04684
+2.24812 2.28257
+0.685061 1.2947
+2.25379 2.92827
+6.0052 6.24797
+7.06213 7.86344
+0.751849 2.96376
+0.0977921 0.513746
+8.43792 9.10545
+2.80769 3.09276
+9.19308 9.59741
+4.74365 4.99708
+8.41385 8.58422
+4.28093 5.9281
+4.26205 4.75417
+1.48035 1.61363
+1.4264 1.80922
+3.48365 4.52935
+1.78396 2.96351
+8.4134 8.96536
+8.65646 9.34781
+1.88027 2.97804
+8.92531 9.02743
+6.91815 7.88895
+5.68023 7.37521
+3.93105 4.6123
+0.385874 1.30785
+1.80151 2.24385
+8.43781 9.33927
+6.69643 8.001
+6.12062 6.673
+4.8316 6.63067
+9.00443 9.08204
+1.5651 2.65023
+3.57517 4.40231
+5.85127 8.02219
+8.02586 10.018
+2.00514 2.75138
+6.32104 7.84285
+8.90914 9.78319
+4.91325 6.27817
+3.87406 4.80327
+8.57887 9.30685
+1.40351 1.71079
+-0.217977 0.224497
+8.37711 9.56393
+5.54644 5.77714
+8.18206 8.36015
+0.774967 1.97899
+9.10434 10.1721
+9.39621 10.1135
+4.80108 4.90605
+9.45978 9.96227
+2.85412 4.05215
+5.71985 7.16735
+2.35081 2.82214
+9.34881 10.5899
+7.13014 7.82872
+4.54931 4.89725
+9.41397 9.9131
+8.90226 9.55276
+8.27995 9.83651
+9.2767 9.6053
+0.388751 1.40317
+5.01478 5.88869
+6.41521 7.21754
+1.22552 1.39067
+3.75771 3.81571
+4.39362 6.04592
+8.82639 8.84544
+4.59289 4.89208
+1.52235 1.64285
+1.85893 4.52056
+1.91781 2.78253
+3.34677 4.54987
+9.26905 10.6019
+7.10958 8.02083
+0.765257 1.66957
+2.17169 2.70214
+4.2293 6.38089
+1.41111 2.45992
+5.76864 6.85715
+2.19944 2.93182
+9.03727 9.6454
+3.82652 4.35225
+2.52642 3.09725
+7.77868 9.35844
+0.337665 1.00787
+1.92021 2.04418
+4.41862 5.95486
+9.47606 9.62386
+1.12113 1.55658
+5.26701 7.09712
+8.81478 9.34863
+6.29447 7.43847
+2.82379 3.57268
+7.9735 8.79936
+3.30176 5.50666
+6.36009 6.8864
+4.13583 5.00627
+0.510514 0.882245
+6.93864 7.78543
+2.04039 2.4298
+3.18337 3.19424
+4.20059 4.67088
+0.316687 0.707377
+0.169106 1.68194
+8.26665 10.2362
+1.1124 1.78306
+2.84603 3.33142
+9.48756 9.96651
+9.4301 9.7316
+0.234674 1.23981
+0.493232 0.522565
+1.342 1.41739
+2.57196 4.08221
+1.54201 2.52284
+5.32049 6.00052
+8.54218 8.59452
+-0.030524 1.64476
+2.31645 2.72528
+4.71898 4.92827
+0.0872997 1.74969
+0.994278 1.76964
+1.34411 2.77952
+0.156817 2.10245
+5.78094 6.34389
+3.09336 3.10563
+8.14245 9.0928
+9.34202 9.75484
+9.78415 10.0211
+4.68383 5.19384
+6.09441 7.90512
+6.74941 6.76118
+1.78693 1.91697
+2.34369 2.62141
+-0.20756 0.829082
+3.57681 5.11448
+2.44234 4.45153
+4.84521 5.31902
+1.80487 3.64498
+2.46125 3.02549
+-0.334514 0.64288
+8.06406 8.49886
+1.74559 2.54474
+6.05883 6.46529
+9.00014 10.2271
+8.00064 8.5061
+0.909467 0.980765
+8.65862 8.69736
+8.11457 8.77049
+3.93237 5.02485
+4.64507 5.34852
+3.92405 4.19449
+5.02381 5.21722
+3.76203 3.78396
+6.74925 7.34781
+8.2556 8.63585
+3.92521 3.99739
+1.44641 2.31509
+0.23516 0.917239
+4.4614 6.35489
+3.33221 3.95247
+1.73289 2.07919
+6.92385 7.55052
+8.74351 9.41125
+9.41451 10.1785
+7.4001 8.81081
+2.97038 3.12524
+7.26043 7.77569
+5.56625 5.59344
+5.70977 6.33362
+7.61443 8.43218
+1.05308 1.82947
+0.377602 1.57633
+6.42483 7.51505
+4.73011 5.43693
+7.72 8.09098
+9.20063 9.82287
+6.88273 7.35327
+6.88423 7.68356
+3.55293 3.6227
+0.947096 1.76021
+3.66411 5.67117
+9.31422 10.1035
+6.84847 6.98956
+2.16221 4.45806
+0.853284 3.15932
+2.48673 2.89793
+3.37633 3.90938
+1.6141 1.66363
+1.6658 3.01723
+0.419408 1.01736
+0.712239 0.791538
+2.25249 3.62425
+8.09772 10.2367
+1.46651 1.48148
+1.73233 2.0489
+7.42679 9.23232
+7.97446 9.53281
+2.74677 4.03955
+-0.169412 0.872795
+4.90663 5.40277
+7.62122 9.49334
+6.55971 7.34259
+3.71957 5.03775
+3.33226 4.06459
+0.634912 1.52603
+3.65506 4.09318
+4.31463 4.60534
+8.58287 9.85385
+0.334759 0.7232
+2.14027 2.866
+6.06611 6.3625
+2.53013 3.18764
+4.30913 4.89247
+6.53234 6.92328
+7.66419 8.61762
+1.37598 2.26754
+8.06279 8.80692
+5.28688 5.70608
+0.509396 1.34606
+8.80589 9.29765
+9.3801 10.3988
+0.402662 0.597735
+5.87213 6.63371
+2.79136 3.763
+6.20615 7.25189
+7.54065 9.62156
+4.12107 5.04454
+5.60294 6.69246
+1.20845 1.49272
+1.75679 2.56397
+2.83939 3.85147
+6.21362 6.71341
+9.01824 9.2388
+4.66617 5.04944
+1.48766 2.55674
+8.89442 9.42175
+5.29411 5.39531
+6.66271 8.68733
+0.730461 1.42466
+6.22927 6.55086
+0.566776 1.17299
+3.06104 4.17775
+5.28026 5.73966
+5.76071 7.61585
+7.83786 9.58106
+6.32199 6.46961
+8.89555 9.17429
+3.85772 4.97805
+6.63352 8.79211
+7.87234 7.94131
+6.53479 7.87979
+3.90293 4.50376
+6.21371 7.31788
+1.00497 1.75003
+6.90351 8.02435
+2.29142 3.9809
+6.26632 6.45283
+-0.0354471 1.31727
+8.80046 9.20169
+7.86905 8.36819
+0.848737 1.82393
+7.98136 9.40712
+3.97765 4.95399
+8.70252 9.26275
+3.13412 4.29389
+2.06446 3.55839
+7.67918 8.44509
+5.96082 6.40336
+1.20461 2.36924
+4.76741 5.74978
+9.41217 9.94305
+7.36736 8.07119
+3.44102 3.56957
+3.59893 4.52751
+4.2613 6.41628
+1.65321 3.02235
+3.70067 3.86657
+0.0176327 1.1215
+4.13592 4.88595
+8.73668 9.0834
+1.80944 2.95584
+6.05721 6.93009
+5.08206 5.38626
+1.86749 1.89392
+3.58284 4.10506
+0.0885586 1.47709
+5.46502 5.93066
+8.45338 8.47878
+3.46789 4.02317
+0.975506 1.15814
+7.12758 7.60073
+7.99582 8.56746
+3.11435 3.83805
+4.51166 4.52472
+8.39096 8.75934
+8.42208 9.66019
+2.48498 4.73703
+3.50301 4.81264
+6.40196 7.0733
+8.52138 8.82265
+1.49822 1.74634
+7.08547 7.93508
+3.47832 4.42948
+6.08646 6.20865
+4.46334 4.65278
+3.80008 4.08214
+3.4853 5.44308
+5.48109 6.18681
+6.59161 8.04307
+7.36554 7.38201
+5.2144 5.31725
+4.62607 7.25804
+1.24345 1.81263
+5.49248 8.16867
+6.4056 8.26316
+7.67828 8.56923
+2.46187 2.56974
+2.22942 3.27248
+7.14933 8.06682
+2.3236 2.95462
+4.18028 4.80535
+4.981 5.54215
+7.23261 7.34863
+4.96309 6.06396
+4.24402 4.44364
+0.917707 1.32687
+1.19806 1.65106
+3.7725 5.31412
+9.70021 9.84203
+5.99824 7.77474
+3.32636 3.84266
+8.59841 9.07653
+7.9916 9.14415
+0.786519 1.84655
+0.166394 1.47834
+2.87633 3.52808
+7.53804 9.56807
+6.14406 6.16189
+1.63428 3.96845
+1.10307 1.58897
+1.30032 2.85313
+7.89803 8.32723
+8.77593 8.90136
+1.68804 2.69447
+4.5956 4.6743
+7.39643 8.29839
+6.93629 7.82243
+6.10289 7.677
+1.83835 2.34295
+1.04506 1.91684
+8.95277 9.43817
+0.36153 0.643665
+1.02408 3.18963
+4.02972 4.40301
+2.80428 2.82552
+6.51718 6.64956
+0.185341 1.56607
+6.1658 7.59364
+4.09288 4.11687
+6.90205 7.16338
+5.0755 5.39478
+4.5614 4.83286
+5.8489 8.76295
+9.70079 10.0431
+8.44334 8.54714
+3.00139 3.66327
+5.34458 6.38895
+7.11481 7.96865
+4.66776 5.15678
+0.390138 0.53352
+2.01116 3.32839
+6.78761 6.97068
+4.57477 5.0724
+1.14098 1.36134
+7.4559 8.30327
+0.700932 2.40437
+1.90469 1.99046
+4.30064 5.11485
+7.84433 8.48543
+5.96212 7.49882
+3.93055 3.96317
+0.546327 1.04814
+8.96011 9.0404
+7.89255 8.06149
+0.669924 2.6944
+-0.00972314 0.837474
+6.07199 6.37467
+2.73659 3.19833
+5.9576 7.10966
+9.1316 9.14737
+5.26101 6.59184
+5.77697 8.08876
+0.68623 0.782805
+0.842619 1.39893
+5.82075 6.15957
+4.36394 4.88479
+7.1828 7.90107
+3.3331 4.39923
+6.54243 7.24966
+2.809 2.96491
+4.18514 4.61948
+4.95453 5.33929
+8.33288 9.52867
+9.05785 10.4276
+2.58917 4.74403
+1.34279 1.89014
+4.93626 5.75424
+7.75031 7.92788
+9.00904 9.02402
+3.91286 5.15124
+6.98486 7.34688
+-0.173169 0.415019
+0.652242 1.51556
+3.50184 5.30486
+3.72563 4.09022
+4.60463 6.58985
+3.34219 4.31833
+2.55445 2.58651
+6.14573 6.3669
+4.52336 6.37342
+9.37606 9.76836
+2.4198 3.36929
+2.89109 3.66974
+5.62463 6.05989
+0.674219 1.84165
+0.590017 1.71153
+1.54622 2.10277
+6.48003 6.55663
+3.56355 3.98573
+0.743671 1.87049
+3.27833 6.0722
+4.76267 6.9967
+2.80188 4.03037
+0.372694 0.482111
+5.73987 5.9529
+8.84732 9.49033
+0.833944 1.8157
+4.06126 4.36615
+0.884619 2.34622
+6.86723 6.99141
+8.07737 9.05193
+8.35903 9.00761
+8.84777 9.74001
+8.58058 9.05479
+8.28076 8.44566
+4.55155 5.65475
+2.44314 3.38966
+3.22172 4.50395
+7.1808 7.90376
+0.639636 1.72606
+5.46807 5.94322
+9.02146 9.87864
+-0.628472 0.655557
+4.29775 5.9553
+6.77525 7.38152
+6.51827 6.93542
+8.95252 9.52939
+0.755406 1.19973
+7.69455 7.86912
+0.170143 1.12949
+7.69254 8.08221
+2.08238 3.27051
+1.28662 1.78628
+1.21208 2.79391
+-0.155739 1.7071
+8.28833 9.10011
+5.77789 6.6954
+1.98395 2.35216
+5.77469 6.05177
+2.77565 5.81092
+-1.53416 2.30576
+6.93529 8.04506
+3.91553 4.55593
+5.57201 6.29071
+1.54149 1.86613
+4.09163 4.31234
+8.47834 11.1229
+5.70376 7.02981
+2.24683 3.79925
+5.4793 6.41036
+5.27644 6.81729
+0.13273 0.371437
+1.22959 1.41618
+0.551957 1.03276
+2.01269 2.4018
+8.77113 9.09395
+8.11753 8.46262
+0.39406 0.783705
+5.35964 5.48227
+7.24727 8.23233
+7.74525 8.85748
+0.0115736 0.882607
+1.78575 2.19684
+8.32514 9.0503
+3.11074 3.34975
+0.847464 2.13237
+0.310898 0.393528
+8.68841 10.518
+1.10032 1.83755
+2.42286 3.02554
+1.16364 2.80986
+1.46419 2.11421
+7.46021 7.90273
+6.86556 7.62542
+1.91466 3.79843
+3.1056 3.83969
+3.41591 4.26565
+0.285122 1.21372
+3.75441 5.52385
+1.07643 2.63403
+6.17341 7.67244
+9.13122 9.5132
+4.39696 6.15885
+3.7207 4.07729
+6.80782 7.1958
+6.65933 6.67105
+8.51535 8.7263
+5.98305 7.17759
+2.19609 2.46108
+8.21186 8.96908
+2.94729 3.60562
+3.31907 3.9297
+0.463492 0.626603
+2.62143 3.55089
+5.76898 6.79002
+1.45502 1.56525
+4.80797 5.62389
+5.87337 6.70588
+2.92765 3.50929
+0.412987 0.951057
+3.64594 4.40269
+-0.043401 0.502176
+4.54802 5.44613
+1.20218 1.8732
+2.75547 2.96745
+7.10348 7.7945
+9.74845 9.98835
+4.83718 6.4836
+2.30563 2.5903
+4.74016 6.30789
+6.42192 6.93329
+5.37294 6.73938
+2.4365 3.05787
+1.08283 3.79193
+4.90426 5.93563
+3.8874 4.83301
+0.13909 0.983027
+4.07407 5.61421
+8.62875 10.6851
+8.10233 8.29952
+2.23047 2.4691
+7.34617 7.39475
+1.66309 2.3032
+7.11207 10.0686
+4.52412 6.38666
+2.48323 2.96878
+7.47877 8.86547
+2.67607 4.33436
+6.83659 8.21075
+2.87313 3.39011
+2.81911 4.07729
+0.227877 0.657898
+6.57843 7.14311
+-0.591405 1.56925
+7.08018 7.59
+9.09558 9.3923
+9.48544 9.79474
+0.740233 2.33129
+8.51111 11.134
+7.79219 8.0281
+1.73821 1.89316
+9.21077 9.29488
+5.38354 6.46025
+4.30403 4.5472
+0.0893758 0.919238
+7.94464 8.51053
+5.27119 6.3741
+5.22476 6.00588
diff --git a/bottleneck/tests/data/ws_tests/test_5_A b/bottleneck/tests/data/ws_tests/test_5_A
new file mode 100644
index 0000000..51cff1c
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_5_A
@@ -0,0 +1,5 @@
+7.50638 7.78005
+0.991758 2.12178
+5.18481 6.61702
+6.14703 7.08581
+4.09936 4.83024
diff --git a/bottleneck/tests/data/ws_tests/test_5_A.pd.dipha b/bottleneck/tests/data/ws_tests/test_5_A.pd.dipha
new file mode 100644
index 0000000..be84441
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_5_A.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_5_B b/bottleneck/tests/data/ws_tests/test_5_B
new file mode 100644
index 0000000..be62ed3
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_5_B
@@ -0,0 +1,5 @@
+5.8232 6.36308
+2.16066 2.48668
+2.38754 4.91418
+4.77403 5.43982
+0.291412 1.11147
diff --git a/bottleneck/tests/data/ws_tests/test_5_B.pd.dipha b/bottleneck/tests/data/ws_tests/test_5_B.pd.dipha
new file mode 100644
index 0000000..14ca67c
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_5_B.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_diag1_A b/bottleneck/tests/data/ws_tests/test_diag1_A
new file mode 100644
index 0000000..f7f90ff
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag1_A
@@ -0,0 +1 @@
+1.0 1.0
diff --git a/bottleneck/tests/data/ws_tests/test_diag1_A.pd.dipha b/bottleneck/tests/data/ws_tests/test_diag1_A.pd.dipha
new file mode 100644
index 0000000..fa4a4d9
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag1_A.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_diag1_B b/bottleneck/tests/data/ws_tests/test_diag1_B
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag1_B
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/bottleneck/tests/data/ws_tests/test_diag1_B.pd.dipha b/bottleneck/tests/data/ws_tests/test_diag1_B.pd.dipha
new file mode 100644
index 0000000..621a55f
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag1_B.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_diag2_A b/bottleneck/tests/data/ws_tests/test_diag2_A
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag2_A
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/bottleneck/tests/data/ws_tests/test_diag2_A.pd.dipha b/bottleneck/tests/data/ws_tests/test_diag2_A.pd.dipha
new file mode 100644
index 0000000..621a55f
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag2_A.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_diag2_B b/bottleneck/tests/data/ws_tests/test_diag2_B
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag2_B
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/bottleneck/tests/data/ws_tests/test_diag2_B.pd.dipha b/bottleneck/tests/data/ws_tests/test_diag2_B.pd.dipha
new file mode 100644
index 0000000..621a55f
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag2_B.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_diag3_A b/bottleneck/tests/data/ws_tests/test_diag3_A
new file mode 100644
index 0000000..151d4b1
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag3_A
@@ -0,0 +1,220 @@
+1.391781911475341 1.391781911475341
+1.395142124726278 1.395142124726278
+1.514181227875788 1.514181227875788
+1.528291566797427 1.528291566797427
+1.585389310674157 1.585389310674157
+1.629232116709072 1.629232116709072
+1.641428662445941 1.641428662445941
+1.646998748860116 1.646998748860116
+1.652915988616469 1.652915988616469
+1.69199679556404 1.69199679556404
+1.705727462482595 1.705727462482595
+1.706819293048617 1.706819293048617
+1.720175733750729 1.720175733750729
+1.728031840308488 1.728031840308488
+1.73797421040929 1.73797421040929
+1.739519744204842 1.739519744204842
+1.76132425248022 1.76132425248022
+1.767766952966369 1.767766952966369
+1.792444271021371 1.792444271021371
+1.831487552809192 1.831487552809192
+1.837086616049901 1.837086616049901
+1.851186504948943 1.851186504948943
+1.860502132730509 1.860502132730509
+1.8619433117852 1.8619433117852
+1.878229072834972 1.878229072834972
+1.880655074837347 1.880655074837347
+1.883647832802556 1.883647832802556
+1.884127769927503 1.884127769927503
+1.892969784466709 1.892969784466709
+1.916936460787894 1.916936460787894
+1.931545068229315 1.931545068229315
+1.937626522143119 1.937626522143119
+1.942267721488891 1.942267721488891
+1.963295334827521 1.963295334827521
+1.975655395743736 1.975655395743736
+1.981448090925679 1.981448090925679
+1.986220565173897 1.986220565173897
+1.98709020812351 1.98709020812351
+1.989420269013254 1.989420269013254
+2.007874648480185 2.007874648480185
+2.012179388983059 2.012179388983059
+2.019051972834053 2.019051972834053
+2.023278848058142 2.023278848058142
+2.026190677562545 2.026190677562545
+2.041594763633561 2.041594763633561
+2.042508934597344 2.042508934597344
+2.04305394648524 2.04305394648524
+2.052514683218775 2.052514683218775
+2.059038785694094 2.059038785694094
+2.062577320792516 2.062577320792516
+2.063488177732052 2.063488177732052
+2.067806664626417 2.067806664626417
+2.073013782498534 2.073013782498534
+2.08646120854976 2.08646120854976
+2.098476357223667 2.098476357223667
+2.101378199886176 2.101378199886176
+2.101927506425904 2.101927506425904
+2.12671744783454 2.12671744783454
+2.143966150630584 2.143966150630584
+2.145312642688415 2.145312642688415
+2.148704396208969 2.148704396208969
+2.153092682531471 2.153092682531471
+2.157553654759374 2.157553654759374
+2.176659075756566 2.176659075756566
+2.177260578806816 2.177260578806816
+2.179141269427014 2.179141269427014
+2.201895416482074 2.201895416482074
+2.202563945779844 2.202563945779844
+2.205113735193028 2.205113735193028
+2.207345865351049 2.207345865351049
+2.208922099676958 2.208922099676958
+2.218057898922937 2.218057898922937
+2.228610453267036 2.228610453267036
+2.241314066596301 2.241314066596301
+2.242145210071643 2.242145210071643
+2.253976266568437 2.253976266568437
+2.255324860119305 2.255324860119305
+2.271300972641221 2.271300972641221
+2.279438361991067 2.279438361991067
+2.286592331830957 2.286592331830957
+2.287159411646074 2.287159411646074
+2.296653147995115 2.296653147995115
+2.301754785182811 2.301754785182811
+2.30409930499031 2.30409930499031
+2.32141477565108 2.32141477565108
+2.347789281926012 2.347789281926012
+2.347827987256373 2.347827987256373
+2.349391321950732 2.349391321950732
+2.350129292983257 2.350129292983257
+2.358679083392328 2.358679083392328
+2.372845273125388 2.372845273125388
+2.385040766846267 2.385040766846267
+2.42114588843816 2.42114588843816
+2.425116524931602 2.425116524931602
+2.426518521893022 2.426518521893022
+2.43211651886311 2.43211651886311
+2.441302771998711 2.441302771998711
+2.446429340510857 2.446429340510857
+2.446547553904861 2.446547553904861
+2.45764765793376 2.45764765793376
+2.461222149682938 2.461222149682938
+2.467900747394114 2.467900747394114
+2.473214152160872 2.473214152160872
+2.5 2.5
+2.503557913626332 2.503557913626332
+2.504315621146863 2.504315621146863
+2.515634290122204 2.515634290122204
+2.516231935083851 2.516231935083851
+2.517558892374071 2.517558892374071
+2.526325773757754 2.526325773757754
+2.531164001388939 2.531164001388939
+2.53128061055404 2.53128061055404
+2.539387277827314 2.539387277827314
+2.540864599180268 2.540864599180268
+2.548084457784768 2.548084457784768
+2.548923292215475 2.548923292215475
+2.551730202825644 2.551730202825644
+2.553178578801818 2.553178578801818
+2.560295747947446 2.560295747947446
+2.566321603108612 2.566321603108612
+2.568932286976676 2.568932286976676
+2.574887688783916 2.574887688783916
+2.581809142325336 2.581809142325336
+2.584541960262555 2.584541960262555
+2.585511915815223 2.585511915815223
+2.592970592044868 2.592970592044868
+2.596055336381078 2.596055336381078
+2.598560573626668 2.598560573626668
+2.614019084614256 2.614019084614256
+2.618463725327216 2.618463725327216
+2.622883674481145 2.622883674481145
+2.627791161528314 2.627791161528314
+2.63535653879261 2.63535653879261
+2.654825898255443 2.654825898255443
+2.660423271276714 2.660423271276714
+2.667148030102869 2.667148030102869
+2.67012591760915 2.67012591760915
+2.698712599567882 2.698712599567882
+2.72180967799905 2.72180967799905
+2.732466204434637 2.732466204434637
+2.734187392905275 2.734187392905275
+2.737296308103857 2.737296308103857
+2.745724923243991 2.745724923243991
+2.749541709159369 2.749541709159369
+2.752925621447035 2.752925621447035
+2.754183973113479 2.754183973113479
+2.763972022430258 2.763972022430258
+2.766941997926879 2.766941997926879
+2.773850925522978 2.773850925522978
+2.777506755238121 2.777506755238121
+2.780333194223143 2.780333194223143
+2.783060349483276 2.783060349483276
+2.78679029681548 2.78679029681548
+2.786792895521339 2.786792895521339
+2.795170825459034 2.795170825459034
+2.801104989227437 2.801104989227437
+2.80525433080833 2.80525433080833
+2.805376738133109 2.805376738133109
+2.806844454092663 2.806844454092663
+2.811611818684648 2.811611818684648
+2.811994908451803 2.811994908451803
+2.816002798930236 2.816002798930236
+2.816814002472584 2.816814002472584
+2.818569391261086 2.818569391261086
+2.821660827076439 2.821660827076439
+2.822317588351085 2.822317588351085
+2.824910409962511 2.824910409962511
+2.829322097471409 2.829322097471409
+2.833852169620359 2.833852169620359
+2.839287537694811 2.839287537694811
+2.841714730677953 2.841714730677953
+2.841715058318205 2.841715058318205
+2.851653306950001 2.851653306950001
+2.853639002902003 2.853639002902003
+2.85515962291442 2.85515962291442
+2.855333736885793 2.855333736885793
+2.872540314564304 2.872540314564304
+2.879449214478037 2.879449214478037
+2.881003856158217 2.881003856158217
+2.881074731438092 2.881074731438092
+2.893589165559115 2.893589165559115
+2.898664743213686 2.898664743213686
+2.90387832180792 2.90387832180792
+2.919095859678745 2.919095859678745
+2.924945175440496 2.924945175440496
+2.931795145696962 2.931795145696962
+2.932285006979528 2.932285006979528
+2.934606807227626 2.934606807227626
+2.936392671567475 2.936392671567475
+2.953794710898493 2.953794710898493
+2.958055395706548 2.958055395706548
+2.960407744013656 2.960407744013656
+2.960759715914242 2.960759715914242
+2.969702548922556 2.969702548922556
+2.970149844982665 2.970149844982665
+2.978953970679893 2.978953970679893
+2.979075864664287 2.979075864664287
+2.984665519558418 2.984665519558418
+3.04548240149063 3.04548240149063
+3.050688336416719 3.050688336416719
+3.05773927378742 3.05773927378742
+3.059596740753369 3.059596740753369
+3.059762479996741 3.059762479996741
+3.088543279751235 3.088543279751235
+3.093580813520995 3.093580813520995
+3.104787362108069 3.104787362108069
+3.173380191779681 3.173380191779681
+3.583124637167399 3.583124637167399
+3.630658112409034 3.630658112409034
+3.631421639368965 3.631421639368965
+3.751087101339956 3.751087101339956
+3.800845709568037 3.800845709568037
+3.846558940956666 3.846558940956666
+4 4
+4 4
+4.076238038291317 4.076238038291317
+4.455547086147983 4.455547086147983
+5.356087357608394 5.356087357608394
+5.54364842773721 5.54364842773721
+7.587654388717225 7.587654388717225
diff --git a/bottleneck/tests/data/ws_tests/test_diag3_A.pd.dipha b/bottleneck/tests/data/ws_tests/test_diag3_A.pd.dipha
new file mode 100644
index 0000000..0dbfb89
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag3_A.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_diag3_B b/bottleneck/tests/data/ws_tests/test_diag3_B
new file mode 100644
index 0000000..bb8655a
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag3_B
@@ -0,0 +1,193 @@
+1.167089173446239 1.167089173446239
+1.256234452640111 1.256234452640111
+1.303693422257498 1.303693422257498
+1.413255970488646 1.413255970488646
+1.697910382446573 1.697910382446573
+1.718844728805093 1.718844728805093
+1.734124820632724 1.734124820632724
+1.749572938304276 1.749572938304276
+1.770320424526358 1.770320424526358
+1.786344763036807 1.786344763036807
+1.810054737907635 1.810054737907635
+1.815127306170105 1.815127306170105
+1.837806648681218 1.837806648681218
+1.870552189043019 1.870552189043019
+1.897240351979503 1.897240351979503
+1.935562152643027 1.935562152643027
+1.952562418976663 1.952562418976663
+1.959552126104175 1.959552126104175
+1.979899732318601 1.979899732318601
+2.00044500769347 2.00044500769347
+2.028951227523087 2.028951227523087
+2.037678749316724 2.037678749316724
+2.047911420446857 2.047911420446857
+2.075181804515723 2.075181804515723
+2.077245386452578 2.077245386452578
+2.084751316684838 2.084751316684838
+2.084860886126203 2.084860886126203
+2.103286477421968 2.103286477421968
+2.106856827309345 2.106856827309345
+2.113139266068691 2.113139266068691
+2.114594962503455 2.114594962503455
+2.115917727493158 2.115917727493158
+2.122335878797089 2.122335878797089
+2.127359082726206 2.127359082726206
+2.131673381033273 2.131673381033273
+2.155015793320908 2.155015793320908
+2.162480684365264 2.162480684365264
+2.195207236194009 2.195207236194009
+2.203279931784429 2.203279931784429
+2.205567995563669 2.205567995563669
+2.212933962936773 2.212933962936773
+2.215081271089993 2.215081271089993
+2.225989037578865 2.225989037578865
+2.24218929203347 2.24218929203347
+2.246321319993257 2.246321319993257
+2.280059407166517 2.280059407166517
+2.284117669032543 2.284117669032543
+2.293233992770926 2.293233992770926
+2.298815356955373 2.298815356955373
+2.300542634724628 2.300542634724628
+2.326408290042679 2.326408290042679
+2.328797162040625 2.328797162040625
+2.36025798094028 2.36025798094028
+2.365031313604634 2.365031313604634
+2.372266311053883 2.372266311053883
+2.400053902049271 2.400053902049271
+2.409134054334209 2.409134054334209
+2.411368235895246 2.411368235895246
+2.415934766378347 2.415934766378347
+2.420989857074179 2.420989857074179
+2.422520269961376 2.422520269961376
+2.43377629944218 2.43377629944218
+2.449308615746858 2.449308615746858
+2.452936540056068 2.452936540056068
+2.453698388060092 2.453698388060092
+2.454711357943602 2.454711357943602
+2.459202673400056 2.459202673400056
+2.493778305287384 2.493778305287384
+2.537394117473177 2.537394117473177
+2.544674753106669 2.544674753106669
+2.558904304820755 2.558904304820755
+2.563089994365716 2.563089994365716
+2.565476194422898 2.565476194422898
+2.599756049189921 2.599756049189921
+2.603619661709009 2.603619661709009
+2.609775379385211 2.609775379385211
+2.622552038976658 2.622552038976658
+2.623798471910885 2.623798471910885
+2.635711198661633 2.635711198661633
+2.644229304223612 2.644229304223612
+2.661919064427223 2.661919064427223
+2.666783921498494 2.666783921498494
+2.675503310152301 2.675503310152301
+2.684228699964661 2.684228699964661
+2.696854617267681 2.696854617267681
+2.700538654666735 2.700538654666735
+2.744886611436907 2.744886611436907
+2.748618547996708 2.748618547996708
+2.757981496641135 2.757981496641135
+2.774766825791652 2.774766825791652
+2.784491736143893 2.784491736143893
+2.796482184304273 2.796482184304273
+2.800849254751463 2.800849254751463
+2.816963410000067 2.816963410000067
+2.825207379914743 2.825207379914743
+2.831286409028398 2.831286409028398
+2.844827082550712 2.844827082550712
+2.853558438121966 2.853558438121966
+2.859806035663089 2.859806035663089
+2.878956033959891 2.878956033959891
+2.886422825109222 2.886422825109222
+2.891566924618832 2.891566924618832
+2.892028419188578 2.892028419188578
+2.893138900330932 2.893138900330932
+2.894250936382814 2.894250936382814
+2.90112201577666 2.90112201577666
+2.902172795370005 2.902172795370005
+2.90967533504119 2.90967533504119
+2.919687125962211 2.919687125962211
+2.923711238894001 2.923711238894001
+2.929041907338841 2.929041907338841
+2.938734873084349 2.938734873084349
+2.939642428979572 2.939642428979572
+2.943010909640486 2.943010909640486
+2.944210926048103 2.944210926048103
+2.951091358234723 2.951091358234723
+2.953950275008233 2.953950275008233
+2.966943157369611 2.966943157369611
+2.982522008227535 2.982522008227535
+2.992174049247434 2.992174049247434
+2.993098995839607 2.993098995839607
+2.995311055519335 2.995311055519335
+2.996708164866609 2.996708164866609
+2.999922110096644 2.999922110096644
+3 3
+3.000364533251431 3.000364533251431
+3.003840990677832 3.003840990677832
+3.006672301312824 3.006672301312824
+3.016489409140306 3.016489409140306
+3.021123787004333 3.021123787004333
+3.039117818612596 3.039117818612596
+3.039555193616473 3.039555193616473
+3.049952247267922 3.049952247267922
+3.057673482371216 3.057673482371216
+3.06920083507411 3.06920083507411
+3.075505231082782 3.075505231082782
+3.079038628197304 3.079038628197304
+3.084265889701239 3.084265889701239
+3.086837468106297 3.086837468106297
+3.103873984398081 3.103873984398081
+3.11528125482979 3.11528125482979
+3.119720021802376 3.119720021802376
+3.132543753577128 3.132543753577128
+3.141822873359038 3.141822873359038
+3.143502053175705 3.143502053175705
+3.153232877003746 3.153232877003746
+3.157586960809866 3.157586960809866
+3.157966892275408 3.157966892275408
+3.163583225161638 3.163583225161638
+3.178188125342772 3.178188125342772
+3.178475867931057 3.178475867931057
+3.179372297765929 3.179372297765929
+3.186437137237586 3.186437137237586
+3.188053957464282 3.188053957464282
+3.199351610026191 3.199351610026191
+3.204566427513051 3.204566427513051
+3.22885278850648 3.22885278850648
+3.229088648916556 3.229088648916556
+3.236685523936269 3.236685523936269
+3.239854786600373 3.239854786600373
+3.255809161351669 3.255809161351669
+3.287718056143732 3.287718056143732
+3.294038308299402 3.294038308299402
+3.313688277153076 3.313688277153076
+3.325783245946608 3.325783245946608
+3.331072954808429 3.331072954808429
+3.354962852285211 3.354962852285211
+3.357502741262644 3.357502741262644
+3.373668509804576 3.373668509804576
+3.408653045775418 3.408653045775418
+3.416281541503763 3.416281541503763
+3.443144279972986 3.443144279972986
+3.492970564191033 3.492970564191033
+3.493767805580122 3.493767805580122
+3.559084134799019 3.559084134799019
+3.559898699300211 3.559898699300211
+3.833585501974904 3.833585501974904
+4.099502076836052 4.099502076836052
+4.484082147277348 4.484082147277348
+4.505718324707756 4.505718324707756
+4.891723119528026 4.891723119528026
+5.065300494905414 5.065300494905414
+5.188599238535201 5.188599238535201
+5.36134479630535 5.36134479630535
+5.609786508140671 5.609786508140671
+7.08640314680382 7.08640314680382
+7.113765883549079 7.113765883549079
+7.328944131981744 7.328944131981744
+7.63625182217108 7.63625182217108
+7.716743341311718 7.716743341311718
+7.938093404092351 7.938093404092351
+8.112783377863046 8.112783377863046
+8.131485096731454 8.131485096731454
diff --git a/bottleneck/tests/data/ws_tests/test_diag3_B.pd.dipha b/bottleneck/tests/data/ws_tests/test_diag3_B.pd.dipha
new file mode 100644
index 0000000..3fbfd90
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_diag3_B.pd.dipha
Binary files differ
diff --git a/bottleneck/tests/data/ws_tests/test_list.txt b/bottleneck/tests/data/ws_tests/test_list.txt
new file mode 100644
index 0000000..27340d8
--- /dev/null
+++ b/bottleneck/tests/data/ws_tests/test_list.txt
@@ -0,0 +1,21 @@
+test_5_A test_5_B 1.0 -1.0 4.320655
+test_5_A test_5_B 2.0 -1.0 1.7323016335246
+test_5_A test_5_B 3.0 -1.0 1.396199948
+test_5_A test_5_B 1.0 1.0 6.603006
+test_5_A test_5_B 2.0 1.0 2.73426775794691
+test_5_A test_5_B 3.0 1.0 2.13072755216204
+test_5_A test_5_B 1.0 2.0 5.1888795679967
+test_5_A test_5_B 2.0 2.0 2.26649677575857
+test_5_A test_5_B 3.0 2.0 1.86434961396614
+test_100_A test_100_B 1.0 -1.0 27.5573259
+test_100_A test_100_B 2.0 -1.0 3.38004972483238
+test_100_A test_100_B 3.0 -1.0 1.9045814702967
+test_100_A test_100_B 1.0 1.0 40.4375855
+test_100_A test_100_B 2.0 1.0 4.75252460986668
+test_100_A test_100_B 3.0 1.0 2.556594741819
+test_100_A test_100_B 1.0 2.0 31.7187555735287
+test_100_A test_100_B 2.0 2.0 3.81132239777023
+test_100_A test_100_B 3.0 2.0 2.09695346034248
+test_diag1_A test_diag1_B 1.0 -1.0 0.0
+test_diag2_A test_diag2_B 1.0 -1.0 0.0
+test_diag3_A test_diag3_B 1.0 -1.0 0.0
diff --git a/bottleneck/tests/test_hera_bottleneck.cpp b/bottleneck/tests/test_hera_bottleneck.cpp
new file mode 100644
index 0000000..f22e415
--- /dev/null
+++ b/bottleneck/tests/test_hera_bottleneck.cpp
@@ -0,0 +1,611 @@
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+
+#include "bottleneck.h"
+
+using PairVector = std::vector<std::pair<double, double>>;
+using PairVectorF = std::vector<std::pair<float, float>>;
+
+std::vector<std::string> split_on_delim(const std::string& s, char delim)
+{
+ std::stringstream ss(s);
+ std::string token;
+ std::vector<std::string> tokens;
+ while(std::getline(ss, token, delim)) {
+ tokens.push_back(token);
+ }
+ return tokens;
+}
+
+
+// single row in a file with test cases
+struct TestFromFileCase {
+
+ std::string file_1;
+ std::string file_2;
+ double delta;
+ double answer;
+ std::vector<std::pair<int, int>> longest_edges;
+ double internal_p { hera::get_infinity<double>() };
+
+ TestFromFileCase(const std::string& s)
+ {
+ auto tokens = split_on_delim(s, ' ');
+// assert(tokens.size() > 5);
+ assert(tokens.size() % 2 == 0);
+
+ size_t token_idx = 0;
+ file_1 = tokens.at(token_idx++);
+ file_2 = tokens.at(token_idx++);
+ delta = std::stod(tokens.at(token_idx++));
+ answer = std::stod(tokens.at(token_idx++));
+ while(token_idx < tokens.size() - 1) {
+ int v1 = std::stoi(tokens[token_idx++]);
+ int v2 = std::stoi(tokens[token_idx++]);
+ longest_edges.emplace_back(v1, v2);
+ }
+ }
+};
+
+std::ostream& operator<<(std::ostream& out, const TestFromFileCase& s)
+{
+ out << "[" << s.file_1 << ", " << s.file_2 << ", norm = ";
+ if (s.internal_p != hera::get_infinity()) {
+ out << s.internal_p;
+ } else {
+ out << "infinity";
+ }
+ out << ", answer = " << s.answer << ", edges { ";
+ for(auto e : s.longest_edges) {
+ out << e.first << " <-> " << e.second << ", ";
+ }
+ out << "} ]";
+ return out;
+}
+
+
+TEST_CASE("simple cases", "bottleneckDistApprox")
+{
+ PairVector diagram_A, diagram_B;
+ double delta = 0.01;
+ //double internal_p = hera::get_infinity<double>();
+
+ SECTION("trivial: two empty diagrams") {
+ REQUIRE( 0.0 == hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta));
+ }
+
+ SECTION("trivial: one empty diagram, one single-point diagram") {
+
+ diagram_A.emplace_back(1.0, 2.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ REQUIRE( fabs(d1 - 0.5) <= 0.00000000001 );
+
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ REQUIRE( fabs(d2 - 0.5) <= 0.00000000001 );
+ }
+
+ SECTION("trivial: two single-point diagrams-1") {
+
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(13.0, 19.0); // (3, 3)
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double correct_answer = 3.0;
+ REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer);
+ REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer);
+ }
+
+ SECTION("trivial: two single-point diagrams-2") {
+
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(130.0, 138.0); // (4, 4)
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double correct_answer = 5.0;
+ REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer );
+ REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer );
+
+ }
+
+}
+
+TEST_CASE("float version", "check_template")
+{
+ PairVectorF diagram_A, diagram_B;
+ float delta = 0.01;
+ //float internal_p = hera::get_infinity<double>();
+
+ SECTION("trivial: two empty diagrams") {
+ REQUIRE( 0.0 == hera::bottleneckDistApprox<PairVectorF>(diagram_A, diagram_B, delta));
+ REQUIRE( 0.0 == hera::bottleneckDistExact<PairVectorF>(diagram_A, diagram_B));
+ }
+
+ SECTION("trivial: two single-point diagrams-2") {
+
+ diagram_A.emplace_back(10, 20); // (5, 5)
+ diagram_B.emplace_back(130, 138); // (4, 4)
+
+ float d1 = hera::bottleneckDistApprox<PairVectorF>(diagram_A, diagram_B, delta);
+ float d2 = hera::bottleneckDistApprox<PairVectorF>(diagram_B, diagram_A, delta);
+ float d3 = hera::bottleneckDistExact<PairVectorF>(diagram_B, diagram_A);
+ float correct_answer = 5;
+ REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer );
+ REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer );
+
+ }
+
+}
+
+
+TEST_CASE("infinity points", "bottleneckDistApprox")
+{
+ PairVector diagram_A, diagram_B;
+ double delta = 0.01;
+
+ // do not use Hera's infinity! it is -1
+ double inf = std::numeric_limits<double>::infinity();
+
+ SECTION("two points at infinity, no finite points") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double corr_answer = 1.0;
+ REQUIRE( fabs(d - corr_answer) <= delta * corr_answer);
+ }
+
+ SECTION("two points at infinity") {
+
+ // edge cost 3.0
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(13.0, 19.0); // (3, 3)
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double corr_answer = 3.0;
+ REQUIRE( fabs(d - corr_answer) <= delta * corr_answer);
+ }
+
+ SECTION("three points at infinity, no finite points") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double corr_answer = inf;
+ REQUIRE( d == corr_answer );
+ }
+
+ SECTION("three points at infinity") {
+
+ // edge cost 3.0
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(13.0, 19.0); // (3, 3)
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double corr_answer = inf;
+ REQUIRE( d == corr_answer );
+ }
+
+
+ SECTION("all four corners at infinity, no finite points, finite answer") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double corr_answer = 1.0;
+
+ REQUIRE( d == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-1") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-2") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-3") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-4") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, with finite points, infinite answer-1") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, with finite points, infinite answer-2") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, with finite points, infinite answer-3") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-4") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+
+ SECTION("simple small example with finite answer") {
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.9, inf);
+ diagram_B.emplace_back(1.1, inf);
+
+ // 1.1 - 1.0 + 2.0 - 1.9 = 0.2
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(inf, 1.9);
+ diagram_B.emplace_back(inf, 1.1);
+
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::bottleneckDistExact<>(diagram_A, diagram_B);
+ double d2 = hera::bottleneckDistExact<>(diagram_B, diagram_A);
+ double corr_answer = 3.0;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+
+
+ }
+
+}
+
+TEST_CASE("longest edge", "bottleneckDistApprox")
+{
+ PairVector diagram_A, diagram_B;
+ hera::bt::MatchingEdge<double> longest_edge_1;
+ hera::bt::MatchingEdge<double> longest_edge_2;
+ double delta = 0.01;
+
+ SECTION("trivial: two empty diagrams") {
+ // should not fail
+ REQUIRE( 0.0 == hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta, longest_edge_1, true));
+ }
+
+ SECTION("trivial: one empty diagram, one single-point diagram") {
+
+ diagram_A.emplace_back(1.0, 2.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta, longest_edge_1, true);
+ REQUIRE(longest_edge_1.first.getRealX() == 1.0);
+ REQUIRE(longest_edge_1.first.getRealY() == 2.0);
+
+ double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta, longest_edge_2, true);
+ REQUIRE(longest_edge_2.second.getRealX() == 1.0);
+ REQUIRE(longest_edge_2.second.getRealY() == 2.0);
+ }
+
+ SECTION("trivial: two single-point diagrams-1") {
+
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(11.0, 19.0);
+
+ double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta, longest_edge_1, true);
+
+ REQUIRE(longest_edge_1.first.getRealX() == 10.0);
+ REQUIRE(longest_edge_1.first.getRealY() == 20.0);
+
+ REQUIRE(longest_edge_1.second.getRealX() == 11.0);
+ REQUIRE(longest_edge_1.second.getRealY() == 19.0);
+
+// double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta, longest_edge_2, true);
+// REQUIRE(longest_edge_2.second.getRealX() == 1.0);
+// REQUIRE(longest_edge_2.second.getRealY() == 2.0);
+// double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+// double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+// double correct_answer = 3.0;
+// REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer);
+// REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer);
+ }
+//
+// SECTION("trivial: two single-point diagrams-2") {
+//
+// diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+// diagram_B.emplace_back(130.0, 138.0); // (4, 4)
+//
+// double d1 = hera::bottleneckDistApprox<>(diagram_A, diagram_B, delta);
+// double d2 = hera::bottleneckDistApprox<>(diagram_B, diagram_A, delta);
+// double correct_answer = 5.0;
+// REQUIRE( fabs(d1 - correct_answer) <= delta * correct_answer );
+// REQUIRE( fabs(d2 - correct_answer) <= delta * correct_answer );
+//
+// }
+
+}
+
+TEST_CASE("file cases", "bottleneck_dist")
+{
+ PairVector diagram_A, diagram_B;
+ hera::bt::MatchingEdge<double> longest_edge;
+
+ const char* file_name = "../tests/data/test_list.txt";
+ std::string dir_prefix = "../tests/data/";
+ std::ifstream f;
+ f.open(file_name);
+ std::vector<TestFromFileCase> test_params;
+ std::string s;
+ while (std::getline(f, s)) {
+ test_params.emplace_back(s);
+ //std::cout << "read test params " << test_params.back() << std::endl;
+ }
+
+ SECTION("from file:") {
+
+ for (const auto& ts : test_params) {
+ bool read_file_A = hera::readDiagramPointSet(dir_prefix + ts.file_1, diagram_A);
+ bool read_file_B = hera::readDiagramPointSet(dir_prefix + ts.file_2, diagram_B);
+ REQUIRE(read_file_A);
+ REQUIRE(read_file_B);
+
+ double hera_answer = hera::bottleneckDistApprox(diagram_A, diagram_B, ts.delta, longest_edge, true);
+ std::pair<int, int> hera_le { longest_edge.first.get_user_id(), longest_edge.second.get_user_id() };
+
+ REQUIRE((hera_answer == ts.answer or fabs(hera_answer - ts.answer) <= ts.delta * hera_answer));
+ REQUIRE((ts.longest_edges.empty() or
+ std::find(ts.longest_edges.begin(), ts.longest_edges.end(), hera_le) != ts.longest_edges.end()));
+
+ double hera_answer_exact = hera::bottleneckDistExact(diagram_A, diagram_B, 14, longest_edge, true);
+ std::pair<int, int> hera_le_exact { longest_edge.first.get_user_id(), longest_edge.second.get_user_id() };
+
+ REQUIRE((hera_answer_exact == ts.answer or
+ fabs(hera_answer_exact - ts.answer) <= 0.0001 * ts.answer));
+
+ REQUIRE((ts.longest_edges.empty() or
+ std::find(ts.longest_edges.begin(), ts.longest_edges.end(), hera_le_exact) !=
+ ts.longest_edges.end()));
+
+ // check that longest_edge length matches the bottleneck distance
+
+ double hera_le_cost;
+ bool check_longest_edge_cost = true;
+ if (longest_edge.first.get_user_id() >= 0 and longest_edge.second.get_user_id() < 0) {
+ // longest edge: off-diagonal point of A connected to its diagonal projection
+ hera_le_cost = longest_edge.first.get_persistence(ts.internal_p);
+ } else if (longest_edge.first.get_user_id() < 0 and longest_edge.second.get_user_id() >= 0) {
+ // longest edge: off-diagonal point of B connected to its diagonal projection
+ hera_le_cost = longest_edge.second.get_persistence(ts.internal_p);
+ } else if (longest_edge.first.get_user_id() >= 0 and longest_edge.second.get_user_id() >= 0) {
+ // longest edge connects two off-diagonal points of A and B
+ hera_le_cost = hera::bt::dist_l_inf_slow(longest_edge.first, longest_edge.second);
+ } else {
+ check_longest_edge_cost = false;
+ }
+// if (check_longest_edge_cost and hera_le_cost != hera_answer_exact) {
+// std::cout << "PROBLEM HERE: " << ts << ", longest edge " << longest_edge.first << " - "
+// << longest_edge.second << ", hera_le_cost " << hera_le_cost << ", answwer "
+// << hera_answer_exact << std::endl;
+// }
+ REQUIRE( (not check_longest_edge_cost or fabs(hera_le_cost - hera_answer_exact) < 0.0001 * hera_answer_exact) );
+ std::cout << ts << " PASSED " << std::endl;
+ }
+ }
+
+}
diff --git a/bottleneck/tests/tests_main.cpp b/bottleneck/tests/tests_main.cpp
new file mode 100644
index 0000000..d24407e
--- /dev/null
+++ b/bottleneck/tests/tests_main.cpp
@@ -0,0 +1,3 @@
+#define LOG_AUCTION
+#define CATCH_CONFIG_MAIN
+#include "catch/catch.hpp"
diff --git a/license.txt b/license.txt
new file mode 100644
index 0000000..8f7e4f5
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
diff --git a/matching/CMakeLists.txt b/matching/CMakeLists.txt
new file mode 100644
index 0000000..a391d84
--- /dev/null
+++ b/matching/CMakeLists.txt
@@ -0,0 +1,56 @@
+project(matching_distance)
+cmake_minimum_required(VERSION 3.5.1)
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+include(GenerateExportHeader)
+find_package(Boost REQUIRED)
+
+# Default to Release
+
+if (NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
+endif (NOT CMAKE_BUILD_TYPE)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include
+ SYSTEM ${BOOST_INCLUDE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../bottleneck/include)
+
+set(CMAKE_CXX_STANDARD 14)
+
+
+if (NOT WIN32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -Wall -Wextra ")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -D_GLIBCXX_DEBUG")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -O2 -g -ggdb")
+endif (NOT WIN32)
+
+file(GLOB BT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../bottleneck/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/../bottleneck/include/*.hpp)
+file(GLOB MD_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
+
+file(GLOB SRC_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp)
+
+find_package(Threads)
+set(libraries ${libraries} "stdc++fs" ${CMAKE_THREAD_LIBS_INIT})
+
+
+find_package(OpenMP)
+if (OPENMP_FOUND)
+ set(libraries ${libraries} ${OpenMP_CXX_LIBRARIES})
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
+endif()
+
+
+add_executable(matching_dist "example/matching_dist.cpp" ${MD_HEADERS} ${BT_HEADERS} )
+target_link_libraries(matching_dist PUBLIC ${libraries})
+
+add_executable(module_example "example/module_example.cpp" ${MD_HEADERS} ${BT_HEADERS} )
+target_link_libraries(module_example PUBLIC ${libraries})
+
+
+add_executable(matching_distance_test ${SRC_TEST_FILES} ${BT_HEADERS} ${MD_HEADERS})
+target_link_libraries(matching_distance_test PUBLIC ${libraries})
diff --git a/matching/README.md b/matching/README.md
new file mode 100644
index 0000000..ac3220e
--- /dev/null
+++ b/matching/README.md
@@ -0,0 +1,69 @@
+# Matching distance between bifiltrations and 2-persistence modules.
+
+## Accompanying paper
+M. Kerber, A. Nigmetov,
+Efficient Approximation of the Matching Distance for 2-parameter persistence.
+SoCG 2020.
+
+Bug reports can be sent to "anigmetov EMAIL SIGN lbl DOT gov".
+
+## Dependencies
+
+* Your compiler must support C++11.
+* Boost.
+
+## Usage:
+
+1. To use a standalone command-line utility matching_dist:
+
+`./matching_dist -d dimension -e relative_error file1 file2`
+
+If `relative_error` is not specified, the default 0.1 is used.
+If `dimension` is not specified, the default value is 0.
+Run `./matching_dist` without parameters to see other options.
+
+The output is an approximation of the exact distance (which is assumed to be non-zero).
+Precisely: if *d_exact* is the true distance and *d_approx* is the output, then
+
+> | d_exact - d_approx | / d_exact < relative_error.
+
+Files file1 and file2 must contain 1-critical bi-filtrations in a plain text format which is similar to PHAT. The first line of a file must say *bifiltration_phat_like*. The second line contains the total number of simplices *N*. The next *N* lines contain simplices in the format *dim x y boundary*.
+* *dim*: the dimension of the simplex
+* *x, y*: coordinates of the critical value
+* *boundary*: indices of simplices forming the boundary of the current simplex. Indices are separated by space.
+* Simplices are indexed starting from 0.
+
+For example, the bi-filtration of a segment with vertices appearing at (0,0) and the 1-segment appearing at (3,4) shall be written as:
+
+> bifiltration_phat_like
+> 3
+> \# lines starting with \# are ignored
+> \# vertex A has dimension 0, hence no boundary, its index is 0
+> 0 0 0
+> \# vertex B has index 1
+> 0 0 0
+> \# 1-dimensional simplex {A, B}
+> 1 3 4 0 1
+
+2. To use from your code.
+
+Here you can compute the matching distance either between bi-filtrations or between persistence modules.
+First, you need to include `#include "matching_distance.h"` Practically every class you need is parameterized by Real type, which should be either float or double. The header provides two functions called `matching_distance.`
+See `example/module_example.cpp` for additional details.
+
+## License
+
+See `licence.txt` in the repository root folder.
+
+## Building
+
+CMakeLists.txt can be used to build the command-line utility in the standard
+way. On Linux/Mac/Windows with Cygwin:
+> `mkdir build`
+> `cd build`
+> `cmake ..`
+> `make`
+
+On Windows with Visual Studio: use `cmake-gui` to create the solution in build directory and build it with VS.
+
+The library itself is header-only and does not require separate compilation.
diff --git a/matching/example/matching_dist.cpp b/matching/example/matching_dist.cpp
new file mode 100644
index 0000000..2e0f1eb
--- /dev/null
+++ b/matching/example/matching_dist.cpp
@@ -0,0 +1,366 @@
+#include "common_defs.h"
+
+#include <iostream>
+#include <string>
+#include <cassert>
+#include <experimental/filesystem>
+
+#ifdef MD_EXPERIMENTAL_TIMING
+#include <chrono>
+#endif
+
+#include "opts/opts.h"
+
+#include "matching_distance.h"
+
+using Real = double;
+
+using namespace md;
+
+namespace fs = std::experimental::filesystem;
+
+#ifdef PRINT_HEAT_MAP
+void print_heat_map(const md::HeatMaps<Real>& hms, std::string fname, const CalculationParams<Real>& params)
+{
+ std::set<Real> mu_vals, lambda_vals;
+ auto hm_iter = hms.end();
+ --hm_iter;
+ int max_level = hm_iter->first;
+
+ int level_cardinality = 4;
+ for(int i = 0; i < params.initialization_depth; ++i) {
+ level_cardinality *= 4;
+ }
+ for(int i = params.initialization_depth + 1; i <= max_level; ++i) {
+ assert(static_cast<decltype(level_cardinality)>(hms.at(i).size()) == level_cardinality);
+ level_cardinality *= 4;
+ }
+
+ std::map<std::pair<Real, Real>, Real> hm_x_flat, hm_x_steep, hm_y_flat, hm_y_steep;
+
+ for(const auto& dual_point_value_pair : hms.at(max_level)) {
+ const DualPoint& k = dual_point_value_pair.first;
+ mu_vals.insert(k.mu());
+ lambda_vals.insert(k.lambda());
+ }
+
+ std::vector<Real> lambda_vals_vec(lambda_vals.begin(), lambda_vals.end());
+ std::vector<Real> mu_vals_vec(mu_vals.begin(), mu_vals.end());
+
+ std::ofstream ofs {fname};
+ if (not ofs.good()) {
+ std::cerr << "Cannot write heat map to file " << fname << std::endl;
+ throw std::runtime_error("Cannot open file for writing heat map");
+ }
+
+ std::vector<std::vector<Real>> heatmap_to_print(2 * mu_vals_vec.size(),
+ std::vector<Real>(2 * lambda_vals_vec.size(), 0.0));
+
+ for(auto axis_type : {AxisType::x_type, AxisType::y_type}) {
+ bool is_x_type = axis_type == AxisType::x_type;
+ for(auto angle_type : {AngleType::flat, AngleType::steep}) {
+ bool is_flat = angle_type == AngleType::flat;
+
+ int mu_idx_begin, mu_idx_end;
+
+ if (is_x_type) {
+ mu_idx_begin = mu_vals_vec.size() - 1;
+ mu_idx_end = -1;
+ } else {
+ mu_idx_begin = 0;
+ mu_idx_end = mu_vals_vec.size();
+ }
+
+ int lambda_idx_begin, lambda_idx_end;
+
+ if (is_flat) {
+ lambda_idx_begin = 0;
+ lambda_idx_end = lambda_vals_vec.size();
+ } else {
+ lambda_idx_begin = lambda_vals_vec.size() - 1;
+ lambda_idx_end = -1;
+ }
+
+ int mu_idx_final = is_x_type ? 0 : mu_vals_vec.size();
+
+ for(int mu_idx = mu_idx_begin; mu_idx != mu_idx_end; (mu_idx_begin < mu_idx_end) ? mu_idx++ : mu_idx--) {
+ Real mu = mu_vals_vec.at(mu_idx);
+
+ if (mu == 0.0 and axis_type == AxisType::x_type)
+ continue;
+
+ int lambda_idx_final = is_flat ? 0 : lambda_vals_vec.size();
+
+ for(int lambda_idx = lambda_idx_begin;
+ lambda_idx != lambda_idx_end;
+ (lambda_idx_begin < lambda_idx_end) ? lambda_idx++ : lambda_idx--) {
+
+ Real lambda = lambda_vals_vec.at(lambda_idx);
+
+ if (lambda == 0.0 and angle_type == AngleType::flat)
+ continue;
+
+ DualPoint dp(axis_type, angle_type, lambda, mu);
+ Real dist_value = hms.at(max_level).at(dp);
+
+ heatmap_to_print.at(mu_idx_final).at(lambda_idx_final) = dist_value;
+
+// fmt::print("HM, dp = {}, mu_idx_final = {}, lambda_idx_final = {}, value = {}\n", dp, mu_idx_final,
+// lambda_idx_final, dist_value);
+
+ lambda_idx_final++;
+ }
+ mu_idx_final++;
+ }
+ }
+ }
+
+ for(size_t m_idx = 0; m_idx < heatmap_to_print.size(); ++m_idx) {
+ for(size_t l_idx = 0; l_idx < heatmap_to_print.at(m_idx).size(); ++l_idx) {
+ ofs << heatmap_to_print.at(m_idx).at(l_idx) << " ";
+ }
+ ofs << std::endl;
+ }
+
+ ofs.close();
+}
+#endif
+
+int main(int argc, char** argv)
+{
+ using opts::Option;
+ using opts::PosOption;
+ opts::Options ops;
+
+ CalculationParams<Real> params;
+
+ bool help = false;
+
+#ifdef MD_EXPERIMENTAL_TIMING
+ bool no_stop_asap = false;
+#endif
+
+
+#ifdef PRINT_HEAT_MAP
+ bool heatmap_only = false;
+#endif
+
+ // default values are the best for practical use
+ // if compiled with MD_EXPERIMENTAL_TIMING, user can supply
+ // different bounds and traverse strategies
+ // separated by commas, all combinations will be timed.
+ // See corresponding >> operators in matching_distance.h
+ // for possible values.
+ std::string bounds_list_str = "local_combined";
+ std::string traverse_list_str = "BFS";
+
+ ops >> Option('m', "max-iterations", params.max_depth, "maximal number of iterations (refinements)")
+ >> Option('e', "max-error", params.delta, "error threshold")
+ >> Option('d', "dim", params.dim, "dim")
+ >> Option('i', "initial-depth", params.initialization_depth, "initialization depth")
+#ifdef MD_EXPERIMENTAL_TIMING
+ >> Option("no-stop-asap", no_stop_asap,
+ "don't stop looping over points, if cell cannot be pruned (asap is on by default)")
+ >> Option("bounds", bounds_list_str, "bounds to use, separated by ,")
+ >> Option("traverse", traverse_list_str, "traverse strategy to use, separated by ,")
+#endif
+#ifdef PRINT_HEAT_MAP
+ >> Option("heatmap-only", heatmap_only, "only save heatmap (bruteforce)")
+#endif
+ >> Option('h', "help", help, "show help message");
+
+ std::string fname_a;
+ std::string fname_b;
+
+ if (!ops.parse(argc, argv) || help || !(ops >> PosOption(fname_a) >> PosOption(fname_b))) {
+ std::cerr << "Usage: " << argv[0] << " bifiltration-file-1 bifiltration-file-2\n" << ops << std::endl;
+ return 1;
+ }
+
+#ifdef MD_EXPERIMENTAL_TIMING
+ params.stop_asap = not no_stop_asap;
+#else
+ params.stop_asap = true;
+#endif
+
+ auto bounds_list = split_by_delim(bounds_list_str, ',');
+ auto traverse_list = split_by_delim(traverse_list_str, ',');
+
+ Bifiltration<Real> bif_a(fname_a);
+ Bifiltration<Real> bif_b(fname_b);
+
+ bif_a.sanity_check();
+ bif_b.sanity_check();
+
+ std::vector<BoundStrategy> bound_strategies;
+ std::vector<TraverseStrategy> traverse_strategies;
+
+ for(std::string s : bounds_list) {
+ bound_strategies.push_back(bs_from_string(s));
+ }
+
+ for(std::string s : traverse_list) {
+ traverse_strategies.push_back(ts_from_string(s));
+ }
+
+
+#ifdef MD_EXPERIMENTAL_TIMING
+
+ struct ExperimentResult {
+ CalculationParams<Real> params {CalculationParams<Real>()};
+ int n_hera_calls {0};
+ double total_milliseconds_elapsed {0};
+ Real distance {0};
+ Real actual_error {std::numeric_limits<double>::max()};
+ int actual_max_depth {0};
+
+ int x_wins {0};
+ int y_wins {0};
+ int ad_wins {0};
+
+ int seconds_elapsed() const
+ {
+ return static_cast<int>(total_milliseconds_elapsed / 1000);
+ }
+
+ double savings_ratio_old() const
+ {
+ long int max_possible_calls = 0;
+ long int calls_on_level = 4;
+ for(int i = 0; i <= actual_max_depth; ++i) {
+ max_possible_calls += calls_on_level;
+ calls_on_level *= 4;
+ }
+ return static_cast<double>(n_hera_calls) / static_cast<double>(max_possible_calls);
+ }
+
+ double savings_ratio() const
+ {
+ return static_cast<double>(n_hera_calls) / calls_on_actual_max_depth();
+ }
+
+ long long int calls_on_actual_max_depth() const
+ {
+ long long int result = 1;
+ for(int i = 0; i < actual_max_depth; ++i) {
+ result *= 4;
+ }
+ return result;
+ }
+
+ ExperimentResult() { }
+
+ ExperimentResult(CalculationParams<Real> p, int nhc, double tme, double d)
+ :
+ params(p), n_hera_calls(nhc), total_milliseconds_elapsed(tme), distance(d) { }
+ };
+
+ const int n_repetitions = 1;
+
+#ifdef PRINT_HEAT_MAP
+ if (heatmap_only) {
+ bound_strategies.clear();
+ bound_strategies.push_back(BoundStrategy::bruteforce);
+ traverse_strategies.clear();
+ traverse_strategies.push_back(TraverseStrategy::breadth_first);
+ }
+#endif
+
+ std::map<std::tuple<BoundStrategy, TraverseStrategy>, ExperimentResult> results;
+ for(BoundStrategy bound_strategy : bound_strategies) {
+ for(TraverseStrategy traverse_strategy : traverse_strategies) {
+ CalculationParams<Real> params_experiment;
+ params_experiment.bound_strategy = bound_strategy;
+ params_experiment.traverse_strategy = traverse_strategy;
+ params_experiment.max_depth = params.max_depth;
+ params_experiment.initialization_depth = params.initialization_depth;
+ params_experiment.delta = params.delta;
+ params_experiment.dim = params.dim;
+ params_experiment.hera_epsilon = params.hera_epsilon;
+ params_experiment.stop_asap = params.stop_asap;
+
+ if (traverse_strategy == TraverseStrategy::depth_first and bound_strategy == BoundStrategy::bruteforce)
+ continue;
+
+ // if bruteforce, clamp max iterations number to 7,
+ // save user-provided max_iters in user_max_iters and restore it later.
+ // remember: params is passed by reference to return real relative error and heat map
+
+ int user_max_iters = params.max_depth;
+#ifdef PRINT_HEAT_MAP
+ if (bound_strategy == BoundStrategy::bruteforce and not heatmap_only) {
+ params_experiment.max_depth = std::min(7, params.max_depth);
+ }
+#endif
+ double total_milliseconds_elapsed = 0;
+ int total_n_hera_calls = 0;
+ Real dist;
+ for(int i = 0; i < n_repetitions; ++i) {
+ auto t1 = std::chrono::high_resolution_clock().now();
+ dist = matching_distance(bif_a, bif_b, params_experiment);
+ auto t2 = std::chrono::high_resolution_clock().now();
+ total_milliseconds_elapsed += std::chrono::duration_cast<std::chrono::milliseconds>(
+ t2 - t1).count();
+ total_n_hera_calls += params_experiment.n_hera_calls;
+ }
+
+ auto key = std::make_tuple(bound_strategy, traverse_strategy);
+ results[key].params = params_experiment;
+ results[key].n_hera_calls = total_n_hera_calls / n_repetitions;
+ results[key].total_milliseconds_elapsed = total_milliseconds_elapsed / n_repetitions;
+ results[key].distance = dist;
+ results[key].actual_error = params_experiment.actual_error;
+ results[key].actual_max_depth = params_experiment.actual_max_depth;
+
+ if (bound_strategy == BoundStrategy::bruteforce) { params_experiment.max_depth = user_max_iters; }
+
+#ifdef PRINT_HEAT_MAP
+ if (bound_strategy == BoundStrategy::bruteforce) {
+ fs::path fname_a_path {fname_a.c_str()};
+ fs::path fname_b_path {fname_b.c_str()};
+ fs::path fname_a_wo = fname_a_path.filename();
+ fs::path fname_b_wo = fname_b_path.filename();
+ std::string heat_map_fname = fmt::format("{0}_{1}_dim_{2}_weighted_values_xyp.txt", fname_a_wo.string(),
+ fname_b_wo.string(), params_experiment.dim);
+ fs::path path_hm = fname_a_path.replace_filename(fs::path(heat_map_fname.c_str()));
+ std::cout << "Saving heatmap to " << heat_map_fname;
+ print_heat_map(params_experiment.heat_maps, path_hm.string(), params);
+ }
+#endif
+ }
+ }
+
+// std::cout << "File_1;File_2;Boundstrategy;TraverseStrategy;InitalDepth;NHeraCalls;SavingsRatio;Time;Distance;Error;PushStrategy;MaxDepth;CallsOnMaxDepth;Delta;Dimension" << std::endl;
+ for(auto bs : bound_strategies) {
+ for(auto ts : traverse_strategies) {
+ auto key = std::make_tuple(bs, ts);
+
+ fs::path fname_a_path {fname_a.c_str()};
+ fs::path fname_b_path {fname_b.c_str()};
+ fs::path fname_a_wo = fname_a_path.filename();
+ fs::path fname_b_wo = fname_b_path.filename();
+
+ std::cout << fname_a_wo.string() << ";" << fname_b_wo.string() << ";" << bs << ";" << ts << ";";
+ std::cout << results[key].params.initialization_depth << ";";
+ std::cout << results[key].n_hera_calls << ";"
+ << results[key].savings_ratio() << ";"
+ << results[key].total_milliseconds_elapsed << ";"
+ << results[key].distance << ";"
+ << results[key].actual_error << ";"
+ << "xyp" << ";"
+ << results[key].actual_max_depth << ";"
+ << results[key].calls_on_actual_max_depth() << ";"
+ << params.delta << ";"
+ << params.dim
+ << std::endl;
+ }
+ }
+#else
+ params.bound_strategy = bound_strategies.back();
+ params.traverse_strategy = traverse_strategies.back();
+
+ Real dist = matching_distance<Real>(bif_a, bif_b, params);
+ std::cout << dist << std::endl;
+#endif
+ return 0;
+}
diff --git a/matching/example/module_example.cpp b/matching/example/module_example.cpp
new file mode 100644
index 0000000..aec38c2
--- /dev/null
+++ b/matching/example/module_example.cpp
@@ -0,0 +1,68 @@
+#include <iostream>
+#include "matching_distance.h"
+
+using namespace md;
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ // create generators.
+ // A generator is a point in plane,
+ // generators are stored in a vector of points:
+ PointVec<double> gens_a;
+
+ // module A will have one generator that appears at point (0, 0)
+ gens_a.emplace_back(0, 0);
+
+ // relations are stored in a vector of relations
+ using RelationVec = ModulePresentation<double>::RelVec;
+ RelationVec rels_a;
+
+ // A relation is a struct with position and column
+ using Relation = ModulePresentation<double>::Relation;
+
+ // at this point the relation rel_a_1 will appear:
+ Point<double> rel_a_1_position { 1, 1 };
+
+ // vector IndexVec contains non-zero indices of the corresponding relation
+ // (we work over Z/2). Since we have one generator only, the relation
+ // contains only one entry, 0
+ IndexVec rel_a_1_components { 0 };
+
+ // construct a relation from position and column:
+ Relation rel_a_1 { rel_a_1_position, rel_a_1_components };
+
+ // and add it to a vector of relations
+ rels_a.push_back(rel_a_1);
+
+ // after populating vectors of generators and relations
+ // construct a module:
+ ModulePresentation<double> module_a { gens_a, rels_a };
+
+
+ // same for module_b. It will also have just one
+ // generator and one relation, but at different positions.
+
+ PointVec<double> gens_b;
+ gens_b.emplace_back(1, 1);
+
+ RelationVec rels_b;
+
+ Point<double> rel_b_1_position { 2, 2 };
+ IndexVec rel_b_1_components { 0 };
+
+ rels_b.emplace_back(rel_b_1_position, rel_b_1_components);
+
+ ModulePresentation<double> module_b { gens_b, rels_b };
+
+ // create CalculationParams
+ CalculationParams<double> params;
+ // set relative error to 10 % :
+ params.delta = 0.1;
+ // go at most 8 levels deep in quadtree:
+ params.max_depth = 8;
+
+ double dist = matching_distance(module_a, module_b, params);
+ std::cout << "dist = " << dist << std::endl;
+
+ return 0;
+}
diff --git a/matching/include/bifiltration.h b/matching/include/bifiltration.h
new file mode 100644
index 0000000..5b188d4
--- /dev/null
+++ b/matching/include/bifiltration.h
@@ -0,0 +1,136 @@
+#ifndef MATCHING_DISTANCE_BIFILTRATION_H
+#define MATCHING_DISTANCE_BIFILTRATION_H
+
+#include <string>
+#include <ostream>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <cassert>
+
+#include "common_util.h"
+#include "box.h"
+#include "simplex.h"
+#include "dual_point.h"
+#include "phat/boundary_matrix.h"
+#include "phat/compute_persistence_pairs.h"
+
+#include "common_util.h"
+
+namespace md {
+
+ template<class Real>
+ class Bifiltration {
+ public:
+ using SimplexVector = std::vector<Simplex<Real>>;
+
+ Bifiltration() = default;
+
+ Bifiltration(const Bifiltration&) = default;
+
+ Bifiltration(Bifiltration&&) = default;
+
+ Bifiltration& operator=(const Bifiltration& other)& = default;
+
+ Bifiltration& operator=(Bifiltration&& other) = default;
+
+ Bifiltration(const std::string& fname); // read from file
+
+ template<class Iter>
+ Bifiltration(Iter begin, Iter end)
+ : simplices_(begin, end)
+ {
+ init();
+ }
+
+ Diagram<Real> weighted_slice_diagram(const DualPoint<Real>& line, int dim) const;
+
+ SimplexVector simplices() const { return simplices_; }
+
+ // translate all points by vector (a,a)
+ void translate(Real a);
+
+ // return minimal value of x- and y-coordinates
+ // among all simplices
+ Real minimal_coordinate() const;
+
+ // return box that contains positions of all simplices
+ Box<Real> bounding_box() const;
+
+ void sanity_check() const;
+
+ int maximal_dim() const { return maximal_dim_; }
+
+ Real max_x() const;
+
+ Real max_y() const;
+
+ Real min_x() const;
+
+ Real min_y() const;
+
+ void add_simplex(Index _id, Point<Real> birth, int _dim, const Column& _bdry);
+
+ void save(const std::string& filename, BifiltrationFormat format = BifiltrationFormat::rivet); // save to file
+
+ void scale(Real lambda);
+
+ private:
+ SimplexVector simplices_;
+
+ Box<Real> bounding_box_;
+ int maximal_dim_ {-1};
+
+ void init();
+
+ void rivet_format_reader(std::ifstream&);
+
+ void phat_like_format_reader(std::ifstream&);
+
+ // in Rene format each simplex knows IDs of its boundary facets
+ // postprocess_phat_like_format fills vector of IDs of boundary facets
+ // in each simplex
+ void postprocess_phat_like_format();
+
+ // in Rivet format each simplex knows its vertices,
+ // postprocess_rivet_format fills vector of IDs of boundary facets
+ // in each simplex
+ void postprocess_rivet_format();
+
+ };
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const Bifiltration<Real>& bif);
+
+ template<class Real>
+ class BifiltrationProxy {
+ public:
+ BifiltrationProxy(const Bifiltration<Real>& bif, int dim = 0);
+ // return critical values of simplices that are important for current dimension (dim and dim+1)
+ PointVec<Real> positions() const;
+ // set current dimension
+ int set_dim(int new_dim);
+
+ // wrappers of Bifiltration
+ int maximal_dim() const;
+ void translate(Real a);
+ Real minimal_coordinate() const;
+ Box<Real> bounding_box() const;
+ Real max_x() const;
+ Real max_y() const;
+ Real min_x() const;
+ Real min_y() const;
+ Diagram<Real> weighted_slice_diagram(const DualPoint<Real>& slice) const;
+
+ private:
+ int dim_ { 0 };
+ mutable PointVec<Real> cached_positions_;
+ Bifiltration<Real> bif_;
+
+ void cache_positions() const;
+ };
+}
+
+#include "bifiltration.hpp"
+
+#endif //MATCHING_DISTANCE_BIFILTRATION_H
diff --git a/matching/include/bifiltration.hpp b/matching/include/bifiltration.hpp
new file mode 100644
index 0000000..3d20516
--- /dev/null
+++ b/matching/include/bifiltration.hpp
@@ -0,0 +1,412 @@
+namespace md {
+
+ template<class Real>
+ void Bifiltration<Real>::init()
+ {
+ auto lower_left = max_point<Real>();
+ auto upper_right = min_point<Real>();
+ for(const auto& simplex : simplices_) {
+ lower_left = greatest_lower_bound<>(lower_left, simplex.position());
+ upper_right = least_upper_bound<>(upper_right, simplex.position());
+ maximal_dim_ = std::max(maximal_dim_, simplex.dim());
+ }
+ bounding_box_ = Box<Real>(lower_left, upper_right);
+ }
+
+ template<class Real>
+ Bifiltration<Real>::Bifiltration(const std::string& fname)
+ {
+ std::ifstream ifstr {fname.c_str()};
+ if (!ifstr.good()) {
+ std::string error_message = "Cannot open file " + fname;
+ std::cerr << error_message << std::endl;
+ throw std::runtime_error(error_message);
+ }
+
+ BifiltrationFormat input_format;
+
+ std::string s;
+
+ while(ignore_line(s)) {
+ std::getline(ifstr, s);
+ }
+
+ if (s == "bifiltration") {
+ input_format = BifiltrationFormat::rivet;
+ } else if (s == "bifiltration_phat_like") {
+ input_format = BifiltrationFormat::phat_like;
+ } else {
+ std::cerr << "Unknown format: '" << s << "' in file " << fname << std::endl;
+ throw std::runtime_error("unknown bifiltration format");
+ }
+
+ switch(input_format) {
+ case BifiltrationFormat::rivet :
+ rivet_format_reader(ifstr);
+ break;
+ case BifiltrationFormat::phat_like :
+ phat_like_format_reader(ifstr);
+ break;
+ }
+
+ ifstr.close();
+
+ init();
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::rivet_format_reader(std::ifstream& ifstr)
+ {
+ std::string s;
+ // read axes names, ignore them
+ std::getline(ifstr, s);
+ std::getline(ifstr, s);
+
+ Index index = 0;
+ while(std::getline(ifstr, s)) {
+ if (!ignore_line(s)) {
+ simplices_.emplace_back(index++, s, BifiltrationFormat::rivet);
+ }
+ }
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::phat_like_format_reader(std::ifstream& ifstr)
+ {
+ // read stream line by line; do not use >> operator
+ std::string s;
+ std::getline(ifstr, s);
+
+ // first line contains number of simplices
+ long n_simplices = std::stol(s);
+
+ // all other lines represent a simplex
+ Index index = 0;
+ while(index < n_simplices) {
+ std::getline(ifstr, s);
+ if (!ignore_line(s)) {
+ simplices_.emplace_back(index++, s, BifiltrationFormat::phat_like);
+ }
+ }
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::scale(Real lambda)
+ {
+ for(auto& s : simplices_) {
+ s.scale(lambda);
+ }
+ init();
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::sanity_check() const
+ {
+#ifdef DEBUG
+ // check that boundary has correct number of simplices,
+ // each bounding simplex has correct dim
+ // and appears in the filtration before the simplex it bounds
+ for(const auto& s : simplices_) {
+ assert(s.dim() >= 0);
+ assert(s.dim() == 0 or s.dim() + 1 == (int) s.boundary().size());
+ for(auto bdry_idx : s.boundary()) {
+ Simplex bdry_simplex = simplices()[bdry_idx];
+ assert(bdry_simplex.dim() == s.dim() - 1);
+ assert(bdry_simplex.position().is_less(s.position(), false));
+ }
+ }
+#endif
+ }
+
+ template<class Real>
+ Diagram<Real> Bifiltration<Real>::weighted_slice_diagram(const DualPoint<Real>& line, int dim) const
+ {
+ DiagramKeeper<Real> dgm;
+
+ // make a copy for now; I want slice_diagram to be const
+ std::vector<Simplex<Real>> simplices(simplices_);
+
+// std::vector<Simplex> simplices;
+// simplices.reserve(simplices_.size() / 2);
+// for(const auto& s : simplices_) {
+// if (s.dim() <= dim + 1 and s.dim() >= dim)
+// simplices.emplace_back(s);
+// }
+
+ for(auto& simplex : simplices) {
+ Real value = line.weighted_push(simplex.position());
+ simplex.set_value(value);
+ }
+
+ std::sort(simplices.begin(), simplices.end(),
+ [](const Simplex<Real>& a, const Simplex<Real>& b) { return a.value() < b.value(); });
+ std::map<Index, Index> index_map;
+ for(Index i = 0; i < (int) simplices.size(); i++) {
+ index_map[simplices[i].id()] = i;
+ }
+
+ phat::boundary_matrix<> phat_matrix;
+ phat_matrix.set_num_cols(simplices.size());
+ std::vector<Index> bd_in_slice_filtration;
+ for(Index i = 0; i < (int) simplices.size(); i++) {
+ phat_matrix.set_dim(i, simplices[i].dim());
+ bd_in_slice_filtration.clear();
+ //std::cout << "new col" << i << std::endl;
+ for(int j = 0; j < (int) simplices[i].boundary().size(); j++) {
+ // F[i] contains the indices of its facet wrt to the
+ // original filtration. We have to express it, however,
+ // wrt to the filtration along the slice. That is why
+ // we need the index_map
+ //std::cout << "Found " << F[i].bd[j] << ", returning " << index_map[F[i].bd[j]] << std::endl;
+ bd_in_slice_filtration.push_back(index_map[simplices[i].boundary()[j]]);
+ }
+ std::sort(bd_in_slice_filtration.begin(), bd_in_slice_filtration.end());
+ phat_matrix.set_col(i, bd_in_slice_filtration);
+ }
+ phat::persistence_pairs phat_persistence_pairs;
+ phat::compute_persistence_pairs<phat::twist_reduction>(phat_persistence_pairs, phat_matrix);
+
+ dgm.clear();
+ constexpr Real real_inf = std::numeric_limits<Real>::infinity();
+ for(long i = 0; i < (long) phat_persistence_pairs.get_num_pairs(); i++) {
+ std::pair<phat::index, phat::index> new_pair = phat_persistence_pairs.get_pair(i);
+ bool is_finite_pair = new_pair.second != phat::k_infinity_index;
+ Real birth = simplices.at(new_pair.first).value();
+ Real death = is_finite_pair ? simplices.at(new_pair.second).value() : real_inf;
+ int dim = simplices[new_pair.first].dim();
+ assert(dim + 1 == simplices[new_pair.second].dim());
+ if (birth != death) {
+ dgm.add_point(dim, birth, death);
+ }
+ }
+
+ return dgm.get_diagram(dim);
+ }
+
+ template<class Real>
+ Box<Real> Bifiltration<Real>::bounding_box() const
+ {
+ return bounding_box_;
+ }
+
+ template<class Real>
+ Real Bifiltration<Real>::minimal_coordinate() const
+ {
+ return std::min(bounding_box_.lower_left().x, bounding_box_.lower_left().y);
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::translate(Real a)
+ {
+ bounding_box_.translate(a);
+ for(auto& simplex : simplices_) {
+ simplex.translate(a);
+ }
+ }
+
+ template<class Real>
+ Real Bifiltration<Real>::max_x() const
+ {
+ if (simplices_.empty())
+ return 1;
+ auto me = std::max_element(simplices_.cbegin(), simplices_.cend(),
+ [](const auto& s_a, const auto& s_b) { return s_a.position().x < s_b.position().x; });
+ assert(me != simplices_.cend());
+ return me->position().x;
+ }
+
+ template<class Real>
+ Real Bifiltration<Real>::max_y() const
+ {
+ if (simplices_.empty())
+ return 1;
+ auto me = std::max_element(simplices_.cbegin(), simplices_.cend(),
+ [](const auto& s_a, const auto& s_b) { return s_a.position().y < s_b.position().y; });
+ assert(me != simplices_.cend());
+ return me->position().y;
+ }
+
+ template<class Real>
+ Real Bifiltration<Real>::min_x() const
+ {
+ if (simplices_.empty())
+ return 0;
+ auto me = std::min_element(simplices_.cbegin(), simplices_.cend(),
+ [](const auto& s_a, const auto& s_b) { return s_a.position().x < s_b.position().x; });
+ assert(me != simplices_.cend());
+ return me->position().x;
+ }
+
+ template<class Real>
+ Real Bifiltration<Real>::min_y() const
+ {
+ if (simplices_.empty())
+ return 0;
+ auto me = std::min_element(simplices_.cbegin(), simplices_.cend(),
+ [](const auto& s_a, const auto& s_b) { return s_a.position().y < s_b.position().y; });
+ assert(me != simplices_.cend());
+ return me->position().y;
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::add_simplex(Index _id, Point<Real> birth, int _dim, const Column& _bdry)
+ {
+ simplices_.emplace_back(_id, birth, _dim, _bdry);
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::save(const std::string& filename, md::BifiltrationFormat format)
+ {
+ switch(format) {
+ case BifiltrationFormat::rivet:
+ throw std::runtime_error("Not implemented");
+ break;
+ case BifiltrationFormat::phat_like: {
+ std::ofstream f(filename);
+ if (not f.good()) {
+ std::cerr << "Bifiltration::save: cannot open file " << filename << std::endl;
+ throw std::runtime_error("Cannot open file for writing ");
+ }
+ f << simplices_.size() << "\n";
+
+ for(const auto& s : simplices_) {
+ f << s.dim() << " " << s.position().x << " " << s.position().y << " ";
+ for(int b : s.boundary()) {
+ f << b << " ";
+ }
+ f << std::endl;
+ }
+
+ }
+ break;
+ }
+ }
+
+ template<class Real>
+ void Bifiltration<Real>::postprocess_rivet_format()
+ {
+ std::map<Column, Index> facets_to_ids;
+
+ // fill the map
+ for(Index i = 0; i < (Index) simplices_.size(); ++i) {
+ assert(simplices_[i].id() == i);
+ facets_to_ids[simplices_[i].vertices_] = i;
+ }
+
+// for(const auto& s : simplices_) {
+// facets_to_ids[s] = s.id();
+// }
+
+ // main loop
+ for(auto& s : simplices_) {
+ assert(not s.vertices_.empty());
+ assert(s.facet_indices_.empty());
+ Column facet_indices;
+ for(Index i = 0; i <= s.dim(); ++i) {
+ Column facet;
+ for(Index j : s.vertices_) {
+ if (j != i)
+ facet.push_back(j);
+ }
+ auto facet_index = facets_to_ids.at(facet);
+ facet_indices.push_back(facet_index);
+ }
+ s.facet_indices_ = facet_indices;
+ } // loop over simplices
+ }
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const Bifiltration<Real>& bif)
+ {
+ os << "Bifiltration [" << std::endl;
+ for(const auto& s : bif.simplices()) {
+ os << s << std::endl;
+ }
+ os << "]" << std::endl;
+ return os;
+ }
+
+ template<class Real>
+ BifiltrationProxy<Real>::BifiltrationProxy(const Bifiltration<Real>& bif, int dim)
+ :
+ dim_(dim),
+ bif_(bif)
+ {
+ cache_positions();
+ }
+
+ template<class Real>
+ void BifiltrationProxy<Real>::cache_positions() const
+ {
+ cached_positions_.clear();
+ for(const auto& simplex : bif_.simplices()) {
+ if (simplex.dim() == dim_ or simplex.dim() == dim_ + 1)
+ cached_positions_.push_back(simplex.position());
+ }
+ }
+
+ template<class Real>
+ PointVec<Real>
+ BifiltrationProxy<Real>::positions() const
+ {
+ if (cached_positions_.empty()) {
+ cache_positions();
+ }
+ return cached_positions_;
+ }
+
+ // translate all points by vector (a,a)
+ template<class Real>
+ void BifiltrationProxy<Real>::translate(Real a)
+ {
+ bif_.translate(a);
+ }
+
+ // return minimal value of x- and y-coordinates
+ // among all simplices
+ template<class Real>
+ Real BifiltrationProxy<Real>::minimal_coordinate() const
+ {
+ return bif_.minimal_coordinate();
+ }
+
+ // return box that contains positions of all simplices
+ template<class Real>
+ Box<Real> BifiltrationProxy<Real>::bounding_box() const
+ {
+ return bif_.bounding_box();
+ }
+
+ template<class Real>
+ Real BifiltrationProxy<Real>::max_x() const
+ {
+ return bif_.max_x();
+ }
+
+ template<class Real>
+ Real BifiltrationProxy<Real>::max_y() const
+ {
+ return bif_.max_y();
+ }
+
+ template<class Real>
+ Real BifiltrationProxy<Real>::min_x() const
+ {
+ return bif_.min_x();
+ }
+
+ template<class Real>
+ Real BifiltrationProxy<Real>::min_y() const
+ {
+ return bif_.min_y();
+ }
+
+
+ template<class Real>
+ Diagram<Real> BifiltrationProxy<Real>::weighted_slice_diagram(const DualPoint<Real>& slice) const
+ {
+ return bif_.weighted_slice_diagram(slice, dim_);
+ }
+
+}
+
diff --git a/matching/include/box.h b/matching/include/box.h
new file mode 100644
index 0000000..4243667
--- /dev/null
+++ b/matching/include/box.h
@@ -0,0 +1,59 @@
+#ifndef MATCHING_DISTANCE_BOX_H
+#define MATCHING_DISTANCE_BOX_H
+
+#include <cassert>
+#include <limits>
+
+#include "common_util.h"
+
+namespace md {
+
+ template<class Real_>
+ struct Box {
+ public:
+ using Real = Real_;
+ private:
+ Point<Real> ll;
+ Point<Real> ur;
+
+ public:
+ Box(Point<Real> ll = Point<Real>(), Point<Real> ur = Point<Real>())
+ :ll(ll), ur(ur)
+ {
+ }
+
+ Box(Point<Real> center, Real width, Real height) :
+ ll(Point<Real>(center.x - 0.5 * width, center.y - 0.5 * height)),
+ ur(Point<Real>(center.x + 0.5 * width, center.y + 0.5 * height))
+ {
+ }
+
+
+ inline double width() const { return ur.x - ll.x; }
+
+ inline double height() const { return ur.y - ll.y; }
+
+ inline Point<Real> lower_left() const { return ll; }
+ inline Point<Real> upper_right() const { return ur; }
+ inline Point<Real> center() const { return Point<Real>((ll.x + ur.x) / 2, (ll.y + ur.y) / 2); }
+
+ inline bool operator==(const Box& p)
+ {
+ return this->ll == p.ll && this->ur == p.ur;
+ }
+
+ std::vector<Box> refine() const;
+
+ std::vector<Point<Real>> corners() const;
+
+ void translate(Real a);
+ };
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const Box<Real>& box);
+
+} // namespace md
+
+#include "box.hpp"
+
+#endif //MATCHING_DISTANCE_BOX_H
diff --git a/matching/include/box.hpp b/matching/include/box.hpp
new file mode 100644
index 0000000..f551d84
--- /dev/null
+++ b/matching/include/box.hpp
@@ -0,0 +1,52 @@
+namespace md {
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const Box<Real>& box)
+ {
+ os << "Box(lower_left = " << box.lower_left() << ", upper_right = " << box.upper_right() << ")";
+ return os;
+ }
+
+ template<class Real>
+ void Box<Real>::translate(Real a)
+ {
+ ll.x += a;
+ ll.y += a;
+ ur.x += a;
+ ur.y += a;
+ }
+
+ template<class Real>
+ std::vector<Box<Real>> Box<Real>::refine() const
+ {
+ std::vector<Box<Real>> result;
+
+// 1 | 2
+// 0 | 3
+
+ Point<Real> new_ll = lower_left();
+ Point<Real> new_ur = center();
+ result.emplace_back(new_ll, new_ur);
+
+ new_ll.y = center().y;
+ new_ur.y = ur.y;
+ result.emplace_back(new_ll, new_ur);
+
+ new_ll = center();
+ new_ur = upper_right();
+ result.emplace_back(new_ll, new_ur);
+
+ new_ll.y = ll.y;
+ new_ur.y = center().y;
+ result.emplace_back(new_ll, new_ur);
+
+ return result;
+ }
+
+ template<class Real>
+ std::vector<Point<Real>> Box<Real>::corners() const
+ {
+ return {ll, Point<Real>(ll.x, ur.y), ur, Point<Real>(ur.x, ll.y)};
+ };
+
+}
diff --git a/matching/include/cell_with_value.h b/matching/include/cell_with_value.h
new file mode 100644
index 0000000..3548a11
--- /dev/null
+++ b/matching/include/cell_with_value.h
@@ -0,0 +1,141 @@
+#ifndef MATCHING_DISTANCE_CELL_WITH_VALUE_H
+#define MATCHING_DISTANCE_CELL_WITH_VALUE_H
+
+#include <algorithm>
+
+#include "common_defs.h"
+#include "common_util.h"
+#include "dual_box.h"
+
+namespace md {
+
+ enum class ValuePoint {
+ center,
+ lower_left,
+ lower_right,
+ upper_left,
+ upper_right
+ };
+
+ inline std::ostream& operator<<(std::ostream& os, const ValuePoint& vp)
+ {
+ switch(vp) {
+ case ValuePoint::upper_left :
+ os << "upper_left";
+ break;
+ case ValuePoint::upper_right :
+ os << "upper_right";
+ break;
+ case ValuePoint::lower_left :
+ os << "lower_left";
+ break;
+ case ValuePoint::lower_right :
+ os << "lower_right";
+ break;
+ case ValuePoint::center:
+ os << "center";
+ break;
+ default:
+ os << "FORGOTTEN ValuePoint";
+ }
+ return os;
+ }
+
+ const std::vector<ValuePoint> k_all_vps = {ValuePoint::center, ValuePoint::lower_left, ValuePoint::upper_left,
+ ValuePoint::upper_right, ValuePoint::lower_right};
+
+ const std::vector<ValuePoint> k_corner_vps = {ValuePoint::lower_left, ValuePoint::upper_left,
+ ValuePoint::upper_right, ValuePoint::lower_right};
+
+ // represents a cell in the dual space with the value
+ // of the weighted bottleneck distance
+ template<class Real_>
+ class CellWithValue {
+ public:
+ using Real = Real_;
+
+ CellWithValue() = default;
+
+ CellWithValue(const CellWithValue&) = default;
+
+ CellWithValue(CellWithValue&&) = default;
+
+ CellWithValue& operator=(const CellWithValue& other)& = default;
+
+ CellWithValue& operator=(CellWithValue&& other) = default;
+
+ CellWithValue(const DualBox<Real>& b, int level)
+ :dual_box_(b), level_(level) { }
+
+ DualBox<Real> dual_box() const { return dual_box_; }
+
+ DualPoint<Real> center() const { return dual_box_.center(); }
+
+ Real value_at(ValuePoint vp) const;
+
+ bool has_value_at(ValuePoint vp) const;
+
+ DualPoint<Real> value_point(ValuePoint vp) const;
+
+ int level() const { return level_; }
+
+ void set_value_at(ValuePoint vp, Real new_value);
+
+ bool has_corner_value() const;
+
+ Real stored_upper_bound() const;
+
+ Real max_corner_value() const;
+
+ Real min_value() const;
+
+ bool has_max_possible_value() const { return has_max_possible_value_; }
+
+ std::vector<CellWithValue> get_refined_cells() const;
+
+ void set_max_possible_value(Real new_upper_bound);
+
+ int num_values() const;
+
+#ifdef MD_DEBUG
+ long long int id { 0 };
+
+ static long long int max_id;
+
+ std::vector<long long int> parent_ids;
+#endif
+
+ private:
+
+ bool has_central_value() const { return central_value_ >= 0; }
+
+ bool has_lower_left_value() const { return lower_left_value_ >= 0; }
+
+ bool has_lower_right_value() const { return lower_right_value_ >= 0; }
+
+ bool has_upper_left_value() const { return upper_left_value_ >= 0; }
+
+ bool has_upper_right_value() const { return upper_right_value_ >= 0; }
+
+
+ DualBox<Real> dual_box_;
+ Real central_value_ {-1.0};
+ Real lower_left_value_ {-1.0};
+ Real lower_right_value_ {-1.0};
+ Real upper_left_value_ {-1.0};
+ Real upper_right_value_ {-1.0};
+
+ Real max_possible_value_ {0.0};
+
+ int level_ {0};
+
+ bool has_max_possible_value_ {false};
+ };
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const CellWithValue<Real>& cell);
+} // namespace md
+
+#include "cell_with_value.hpp"
+
+#endif //MATCHING_DISTANCE_CELL_WITH_VALUE_H
diff --git a/matching/include/cell_with_value.hpp b/matching/include/cell_with_value.hpp
new file mode 100644
index 0000000..4079b1b
--- /dev/null
+++ b/matching/include/cell_with_value.hpp
@@ -0,0 +1,225 @@
+namespace md {
+
+#ifdef MD_DEBUG
+ long long int CellWithValue<Real>::max_id = 0;
+#endif
+
+ template<class Real>
+ Real CellWithValue<Real>::value_at(ValuePoint vp) const
+ {
+ switch(vp) {
+ case ValuePoint::upper_left :
+ return upper_left_value_;
+ case ValuePoint::upper_right :
+ return upper_right_value_;
+ case ValuePoint::lower_left :
+ return lower_left_value_;
+ case ValuePoint::lower_right :
+ return lower_right_value_;
+ case ValuePoint::center:
+ return central_value_;
+ }
+ // to shut up compiler warning
+ return 1.0 / 0.0;
+ }
+
+ template<class Real>
+ bool CellWithValue<Real>::has_value_at(ValuePoint vp) const
+ {
+ switch(vp) {
+ case ValuePoint::upper_left :
+ return upper_left_value_ >= 0;
+ case ValuePoint::upper_right :
+ return upper_right_value_ >= 0;
+ case ValuePoint::lower_left :
+ return lower_left_value_ >= 0;
+ case ValuePoint::lower_right :
+ return lower_right_value_ >= 0;
+ case ValuePoint::center:
+ return central_value_ >= 0;
+ }
+ // to shut up compiler warning
+ return 1.0 / 0.0;
+ }
+
+ template<class Real>
+ DualPoint<Real> CellWithValue<Real>::value_point(md::ValuePoint vp) const
+ {
+ switch(vp) {
+ case ValuePoint::upper_left :
+ return dual_box().upper_left();
+ case ValuePoint::upper_right :
+ return dual_box().upper_right();
+ case ValuePoint::lower_left :
+ return dual_box().lower_left();
+ case ValuePoint::lower_right :
+ return dual_box().lower_right();
+ case ValuePoint::center:
+ return dual_box().center();
+ }
+ // to shut up compiler warning
+ return DualPoint<Real>();
+ }
+
+ template<class Real>
+ bool CellWithValue<Real>::has_corner_value() const
+ {
+ return has_lower_left_value() or has_lower_right_value() or has_upper_left_value()
+ or has_upper_right_value();
+ }
+
+ template<class Real>
+ Real CellWithValue<Real>::stored_upper_bound() const
+ {
+ assert(has_max_possible_value_);
+ return max_possible_value_;
+ }
+
+ template<class Real>
+ Real CellWithValue<Real>::max_corner_value() const
+ {
+ return std::max({lower_left_value_, lower_right_value_, upper_left_value_, upper_right_value_});
+ }
+
+ template<class Real>
+ Real CellWithValue<Real>::min_value() const
+ {
+ Real result = std::numeric_limits<Real>::max();
+ for(auto vp : k_all_vps) {
+ if (not has_value_at(vp)) {
+ continue;
+ }
+ result = std::min(result, value_at(vp));
+ }
+ return result;
+ }
+
+ template<class Real>
+ std::vector<CellWithValue<Real>> CellWithValue<Real>::get_refined_cells() const
+ {
+ std::vector<CellWithValue<Real>> result;
+ result.reserve(4);
+ for(const auto& refined_box : dual_box_.refine()) {
+
+ CellWithValue<Real> refined_cell(refined_box, level() + 1);
+
+#ifdef MD_DEBUG
+ refined_cell.parent_ids = parent_ids;
+ refined_cell.parent_ids.push_back(id);
+ refined_cell.id = ++max_id;
+#endif
+
+ if (refined_box.lower_left() == dual_box_.lower_left()) {
+ // _|_
+ // H|_
+
+ refined_cell.set_value_at(ValuePoint::lower_left, lower_left_value_);
+ refined_cell.set_value_at(ValuePoint::upper_right, central_value_);
+
+ } else if (refined_box.upper_right() == dual_box_.upper_right()) {
+ // _|H
+ // _|_
+
+ refined_cell.set_value_at(ValuePoint::lower_left, central_value_);
+ refined_cell.set_value_at(ValuePoint::upper_right, upper_right_value_);
+
+ } else if (refined_box.lower_right() == dual_box_.lower_right()) {
+ // _|_
+ // _|H
+
+ refined_cell.set_value_at(ValuePoint::lower_right, lower_right_value_);
+ refined_cell.set_value_at(ValuePoint::upper_left, central_value_);
+
+ } else if (refined_box.upper_left() == dual_box_.upper_left()) {
+
+ // H|_
+ // _|_
+
+ refined_cell.set_value_at(ValuePoint::lower_right, central_value_);
+ refined_cell.set_value_at(ValuePoint::upper_left, upper_left_value_);
+ }
+ result.emplace_back(refined_cell);
+ }
+ return result;
+ }
+
+ template<class Real>
+ void CellWithValue<Real>::set_value_at(ValuePoint vp, Real new_value)
+ {
+ if (has_value_at(vp)) {
+ std::cerr << "CellWithValue<Real>: trying to re-assign value, vp = " << vp;
+ }
+
+ switch(vp) {
+ case ValuePoint::upper_left :
+ upper_left_value_ = new_value;
+ break;
+ case ValuePoint::upper_right :
+ upper_right_value_ = new_value;
+ break;
+ case ValuePoint::lower_left :
+ lower_left_value_ = new_value;
+ break;
+ case ValuePoint::lower_right :
+ lower_right_value_ = new_value;
+ break;
+ case ValuePoint::center:
+ central_value_ = new_value;
+ break;
+ }
+ }
+
+ template<class Real>
+ int CellWithValue<Real>::num_values() const
+ {
+ int result = 0;
+ for(ValuePoint vp : k_all_vps) {
+ result += has_value_at(vp);
+ }
+ return result;
+ }
+
+
+ template<class Real>
+ void CellWithValue<Real>::set_max_possible_value(Real new_upper_bound)
+ {
+ assert(new_upper_bound >= central_value_);
+ assert(new_upper_bound >= lower_left_value_);
+ assert(new_upper_bound >= lower_right_value_);
+ assert(new_upper_bound >= upper_left_value_);
+ assert(new_upper_bound >= upper_right_value_);
+ has_max_possible_value_ = true;
+ max_possible_value_ = new_upper_bound;
+ }
+
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const CellWithValue<Real>& cell)
+ {
+ os << "CellWithValue(box = " << cell.dual_box() << ", ";
+
+#ifdef MD_DEBUG
+ os << "id = " << cell.id;
+ if (not cell.parent_ids.empty())
+ os << ", parent_ids = " << container_to_string(cell.parent_ids) << ", ";
+#endif
+
+ for(ValuePoint vp : k_all_vps) {
+ if (cell.has_value_at(vp)) {
+ os << "value = " << cell.value_at(vp);
+ os << ", at " << vp << " " << cell.value_point(vp);
+ }
+ }
+
+ os << ", max_corner_value = ";
+ if (cell.has_max_possible_value()) {
+ os << cell.stored_upper_bound();
+ } else {
+ os << "-";
+ }
+
+ os << ", level = " << cell.level() << ")";
+ return os;
+ }
+
+} // namespace md
diff --git a/matching/include/common_defs.h b/matching/include/common_defs.h
new file mode 100644
index 0000000..8d01325
--- /dev/null
+++ b/matching/include/common_defs.h
@@ -0,0 +1,10 @@
+#ifndef MATCHING_DISTANCE_DEF_DEBUG_H
+#define MATCHING_DISTANCE_DEF_DEBUG_H
+
+//#define MD_EXPERIMENTAL_TIMING
+//#define MD_PRINT_HEAT_MAP
+//#define MD_DEBUG
+//#define MD_DO_CHECKS
+//#define MD_DO_FULL_CHECK
+
+#endif //MATCHING_DISTANCE_DEF_DEBUG_H
diff --git a/matching/include/common_util.h b/matching/include/common_util.h
new file mode 100644
index 0000000..20a151a
--- /dev/null
+++ b/matching/include/common_util.h
@@ -0,0 +1,183 @@
+#ifndef MATCHING_DISTANCE_COMMON_UTIL_H
+#define MATCHING_DISTANCE_COMMON_UTIL_H
+
+#include <cassert>
+#include <vector>
+#include <utility>
+#include <cmath>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <map>
+#include <functional>
+
+#include "common_defs.h"
+#include "phat/helpers/misc.h"
+
+namespace md {
+
+ using Index = phat::index;
+ using IndexVec = std::vector<Index>;
+
+ //static constexpr Real pi = M_PI;
+
+ using Column = std::vector<Index>;
+
+ template<class Real>
+ struct Point {
+ Real x;
+ Real y;
+
+ Point(Real x = 0, Real y = 0)
+ :x(x), y(y) { }
+
+ inline Real norm() const { return sqrt(x * x + y * y); }
+
+ inline void normalize()
+ {
+ Real nor = norm();
+ x /= nor;
+ y /= nor;
+ }
+
+ inline void translate(Real a)
+ {
+ x += a;
+ y += a;
+ }
+
+ inline bool operator==(const Point& v) const
+ {
+ return this->x == v.x && this->y == v.y;
+ }
+
+ // compare both coordinates, as needed in persistence
+ // do not overload operator<, requirements are not satisfied
+ inline bool is_less(const Point& other, bool strict = false) const
+ {
+ if (x <= other.x and y <= other.y) {
+ if (strict) {
+ return x != other.x or y != other.y;
+ }
+ else {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+
+ template<class Real>
+ using PointVec = std::vector<Point<Real>>;
+
+ template<class Real>
+ Point<Real> operator+(const Point<Real>& u, const Point<Real>& v);
+
+ template<class Real>
+ Point<Real> operator-(const Point<Real>& u, const Point<Real>& v);
+
+
+ template<class Real>
+ Point<Real> least_upper_bound(const Point<Real>& u, const Point<Real>& v);
+
+ template<class Real>
+ Point<Real> greatest_lower_bound(const Point<Real>& u, const Point<Real>& v);
+
+ template<class Real>
+ Point<Real> max_point();
+
+ template<class Real>
+ Point<Real> min_point();
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& ostr, const Point<Real>& vec);
+
+ template<class Real>
+ using DiagramPoint = std::pair<Real, Real>;
+
+ template<class Real>
+ using Diagram = std::vector<DiagramPoint<Real>>;
+
+
+ // to keep diagrams in all dimensions
+ // TODO: store in Hera format?
+ template<class Real>
+ class DiagramKeeper {
+ public:
+
+ DiagramKeeper() { };
+
+ void add_point(int dim, Real birth, Real death);
+
+ Diagram<Real> get_diagram(int dim) const;
+
+ void clear() { data_.clear(); }
+
+ private:
+ std::map<int, Diagram<Real>> data_;
+ };
+
+ template<typename C>
+ std::string container_to_string(const C& cont)
+ {
+ std::stringstream ss;
+ ss << "[";
+ int i = 0;
+ for (const auto& x : cont) {
+ i++;
+ ss << x;
+ if (i != (int) cont.size())
+ ss << ", ";
+ }
+ ss << "]";
+ return ss.str();
+ }
+
+ // return true, if s is empty or starts with # (commented out line)
+ // whitespaces in the beginning of s are ignored
+ inline bool ignore_line(const std::string& s)
+ {
+ for(auto c : s) {
+ if (isspace(c))
+ continue;
+ return (c == '#');
+ }
+ return true;
+ }
+
+
+ // split string by delimeter
+ template<typename Out>
+ void split_by_delim(const std::string &s, char delim, Out result) {
+ std::stringstream ss(s);
+ std::string item;
+ while (std::getline(ss, item, delim)) {
+ *(result++) = item;
+ }
+ }
+
+ inline std::vector<std::string> split_by_delim(const std::string &s, char delim) {
+ std::vector<std::string> elems;
+ split_by_delim(s, delim, std::back_inserter(elems));
+ return elems;
+ }
+}
+
+namespace std {
+ template<class Real>
+ struct hash<md::Point<Real>>
+ {
+ std::size_t operator()(const md::Point<Real>& p) const
+ {
+ auto hx = std::hash<decltype(p.x)>()(p.x);
+ auto hy = std::hash<decltype(p.y)>()(p.y);
+ return hx ^ (hy << 1);
+ }
+ };
+};
+
+#include "common_util.hpp"
+
+
+#endif //MATCHING_DISTANCE_COMMON_UTIL_H
diff --git a/matching/include/common_util.hpp b/matching/include/common_util.hpp
new file mode 100644
index 0000000..9c7df37
--- /dev/null
+++ b/matching/include/common_util.hpp
@@ -0,0 +1,93 @@
+#include <vector>
+#include <utility>
+#include <cmath>
+#include <ostream>
+#include <limits>
+#include <algorithm>
+
+#include <common_util.h>
+
+namespace md {
+
+ template<class Real>
+ Point<Real> operator+(const Point<Real>& u, const Point<Real>& v)
+ {
+ return Point<Real>(u.x + v.x, u.y + v.y);
+ }
+
+ template<class Real>
+ Point<Real> operator-(const Point<Real>& u, const Point<Real>& v)
+ {
+ return Point<Real>(u.x - v.x, u.y - v.y);
+ }
+
+ template<class Real>
+ Point<Real> least_upper_bound(const Point<Real>& u, const Point<Real>& v)
+ {
+ return Point<Real>(std::max(u.x, v.x), std::max(u.y, v.y));
+ }
+
+ template<class Real>
+ Point<Real> greatest_lower_bound(const Point<Real>& u, const Point<Real>& v)
+ {
+ return Point<Real>(std::min(u.x, v.x), std::min(u.y, v.y));
+ }
+
+ template<class Real>
+ Point<Real> max_point()
+ {
+ return Point<Real>(std::numeric_limits<Real>::max(), std::numeric_limits<Real>::min());
+ }
+
+ template<class Real>
+ Point<Real> min_point()
+ {
+ return Point<Real>(-std::numeric_limits<Real>::max(), -std::numeric_limits<Real>::min());
+ }
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& ostr, const Point<Real>& vec)
+ {
+ ostr << "(" << vec.x << ", " << vec.y << ")";
+ return ostr;
+ }
+
+ template<class Real>
+ Real l_infty_norm(const Point<Real>& v)
+ {
+ return std::max(std::abs(v.x), std::abs(v.y));
+ }
+
+ template<class Real>
+ Real l_2_norm(const Point<Real>& v)
+ {
+ return v.norm();
+ }
+
+ template<class Real>
+ Real l_2_dist(const Point<Real>& x, const Point<Real>& y)
+ {
+ return l_2_norm(x - y);
+ }
+
+ template<class Real>
+ Real l_infty_dist(const Point<Real>& x, const Point<Real>& y)
+ {
+ return l_infty_norm(x - y);
+ }
+
+ template<class Real>
+ void DiagramKeeper<Real>::add_point(int dim, Real birth, Real death)
+ {
+ data_[dim].emplace_back(birth, death);
+ }
+
+ template<class Real>
+ Diagram<Real> DiagramKeeper<Real>::get_diagram(int dim) const
+ {
+ if (data_.count(dim) == 1)
+ return data_.at(dim);
+ else
+ return Diagram<Real>();
+ }
+}
diff --git a/matching/include/dual_box.h b/matching/include/dual_box.h
new file mode 100644
index 0000000..4bbb639
--- /dev/null
+++ b/matching/include/dual_box.h
@@ -0,0 +1,79 @@
+#ifndef MATCHING_DISTANCE_DUAL_BOX_H
+#define MATCHING_DISTANCE_DUAL_BOX_H
+
+#include <ostream>
+#include <limits>
+#include <vector>
+#include <random>
+
+#include "common_util.h"
+#include "dual_point.h"
+
+namespace md {
+
+
+ template<class Real>
+ class DualBox {
+ public:
+
+ DualBox(DualPoint<Real> ll, DualPoint<Real> ur);
+
+ DualBox() = default;
+ DualBox(const DualBox&) = default;
+ DualBox(DualBox&&) = default;
+
+ DualBox& operator=(const DualBox& other) & = default;
+ DualBox& operator=(DualBox&& other) = default;
+
+
+ DualPoint<Real> center() const { return midpoint(lower_left_, upper_right_); }
+ DualPoint<Real> lower_left() const { return lower_left_; }
+ DualPoint<Real> upper_right() const { return upper_right_; }
+
+ DualPoint<Real> lower_right() const;
+ DualPoint<Real> upper_left() const;
+
+ AxisType axis_type() const { return lower_left_.axis_type(); }
+ AngleType angle_type() const { return lower_left_.angle_type(); }
+
+ Real mu_min() const { return lower_left_.mu(); }
+ Real mu_max() const { return upper_right_.mu(); }
+ Real lambda_min() const { return lower_left_.lambda(); }
+ Real lambda_max() const { return upper_right_.lambda(); }
+
+ // return true, if all lines in dual_box are flat
+ bool is_flat() const { return upper_right_.is_flat(); }
+ bool is_steep() const { return lower_left_.is_steep(); }
+
+ std::vector<DualBox> refine() const;
+ std::vector<DualPoint<Real>> corners() const;
+ std::vector<DualPoint<Real>> critical_points(const Point<Real>& p) const;
+ // sample n points from the box uniformly; for tests
+ std::vector<DualPoint<Real>> random_points(int n) const;
+
+ // return 2 dual points at the boundary
+ // where push changes from horizontal to vertical
+ std::vector<DualPoint<Real>> push_change_points(const Point<Real>& p) const;
+
+ // check that a has same sign, angles are all flat or all steep
+ bool sanity_check() const;
+ bool contains(const DualPoint<Real>& dp) const;
+
+ bool operator==(const DualBox& other) const;
+
+ private:
+ DualPoint<Real> lower_left_;
+ DualPoint<Real> upper_right_;
+ };
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const DualBox<Real>& db)
+ {
+ os << "DualBox(" << db.lower_left() << ", " << db.upper_right() << ")";
+ return os;
+ }
+}
+
+#include "dual_box.hpp"
+
+#endif //MATCHING_DISTANCE_DUAL_BOX_H
diff --git a/matching/include/dual_box.hpp b/matching/include/dual_box.hpp
new file mode 100644
index 0000000..d7e6deb
--- /dev/null
+++ b/matching/include/dual_box.hpp
@@ -0,0 +1,188 @@
+namespace md {
+
+ template<class Real>
+ DualBox<Real>::DualBox(DualPoint<Real> ll, DualPoint<Real> ur)
+ :lower_left_(ll), upper_right_(ur)
+ {
+ }
+
+ template<class Real>
+ std::vector<DualPoint<Real>> DualBox<Real>::corners() const
+ {
+ return {lower_left_,
+ DualPoint<Real>(axis_type(), angle_type(), lower_left_.lambda(), upper_right_.mu()),
+ upper_right_,
+ DualPoint<Real>(axis_type(), angle_type(), upper_right_.lambda(), lower_left_.mu())};
+ }
+
+ template<class Real>
+ std::vector<DualPoint<Real>> DualBox<Real>::push_change_points(const Point<Real>& p) const
+ {
+ std::vector<DualPoint<Real>> result;
+ result.reserve(2);
+
+ bool is_y_type = lower_left_.is_y_type();
+ bool is_flat = lower_left_.is_flat();
+
+ auto mu_from_lambda = [p, is_y_type, is_flat](Real lambda) {
+ bool is_x_type = not is_y_type, is_steep = not is_flat;
+ if (is_y_type && is_flat) {
+ return p.y - lambda * p.x;
+ } else if (is_y_type && is_steep) {
+ return p.y - p.x / lambda;
+ } else if (is_x_type && is_flat) {
+ return p.x - p.y / lambda;
+ } else if (is_x_type && is_steep) {
+ return p.x - lambda * p.y;
+ }
+ // to shut up compiler warning
+ return static_cast<Real>(1.0 / 0.0);
+ };
+
+ auto lambda_from_mu = [p, is_y_type, is_flat](Real mu) {
+ bool is_x_type = not is_y_type, is_steep = not is_flat;
+ if (is_y_type && is_flat) {
+ return (p.y - mu) / p.x;
+ } else if (is_y_type && is_steep) {
+ return p.x / (p.y - mu);
+ } else if (is_x_type && is_flat) {
+ return p.y / (p.x - mu);
+ } else if (is_x_type && is_steep) {
+ return (p.x - mu) / p.y;
+ }
+ // to shut up compiler warning
+ return static_cast<Real>(1.0 / 0.0);
+ };
+
+ // all inequalities below are strict: equality means it is a corner
+ // && critical_points() returns corners anyway
+
+ Real mu_intersect_min = mu_from_lambda(lambda_min());
+
+ if (mu_min() < mu_intersect_min && mu_intersect_min < mu_max())
+ result.emplace_back(axis_type(), angle_type(), lambda_min(), mu_intersect_min);
+
+ Real mu_intersect_max = mu_from_lambda(lambda_max());
+
+ if (mu_max() < mu_intersect_max && mu_intersect_max < mu_max())
+ result.emplace_back(axis_type(), angle_type(), lambda_max(), mu_intersect_max);
+
+ Real lambda_intersect_min = lambda_from_mu(mu_min());
+
+ if (lambda_min() < lambda_intersect_min && lambda_intersect_min < lambda_max())
+ result.emplace_back(axis_type(), angle_type(), lambda_intersect_min, mu_min());
+
+ Real lambda_intersect_max = lambda_from_mu(mu_max());
+ if (lambda_min() < lambda_intersect_max && lambda_intersect_max < lambda_max())
+ result.emplace_back(axis_type(), angle_type(), lambda_intersect_max, mu_max());
+
+ assert(result.size() <= 2);
+
+ if (result.size() > 2) {
+ throw std::runtime_error("push_change_points returned more than 2 points");
+ }
+
+ return result;
+ }
+
+ template<class Real>
+ std::vector<DualPoint<Real>> DualBox<Real>::critical_points(const Point<Real>& /*p*/) const
+ {
+ // maximal difference is attained at corners
+ return corners();
+// std::vector<DualPoint<Real>> result;
+// result.reserve(6);
+// for(auto dp : corners()) result.push_back(dp);
+// for(auto dp : push_change_points(p)) result.push_back(dp);
+// return result;
+ }
+
+ template<class Real>
+ std::vector<DualPoint<Real>> DualBox<Real>::random_points(int n) const
+ {
+ assert(n >= 0);
+ std::mt19937_64 gen(1);
+ std::vector<DualPoint<Real>> result;
+ result.reserve(n);
+ std::uniform_real_distribution<Real> mu_distr(mu_min(), mu_max());
+ std::uniform_real_distribution<Real> lambda_distr(lambda_min(), lambda_max());
+ for(int i = 0; i < n; ++i) {
+ result.emplace_back(axis_type(), angle_type(), lambda_distr(gen), mu_distr(gen));
+ }
+ return result;
+ }
+
+ template<class Real>
+ bool DualBox<Real>::sanity_check() const
+ {
+ lower_left_.sanity_check();
+ upper_right_.sanity_check();
+
+ if (lower_left_.angle_type() != upper_right_.angle_type())
+ throw std::runtime_error("angle types differ");
+
+ if (lower_left_.axis_type() != upper_right_.axis_type())
+ throw std::runtime_error("axis types differ");
+
+ if (lower_left_.lambda() >= upper_right_.lambda())
+ throw std::runtime_error("lambda of lower_left_ greater than lambda of upper_right ");
+
+ if (lower_left_.mu() >= upper_right_.mu())
+ throw std::runtime_error("mu of lower_left_ greater than mu of upper_right ");
+
+ return true;
+ }
+
+ template<class Real>
+ std::vector<DualBox<Real>> DualBox<Real>::refine() const
+ {
+ std::vector<DualBox<Real>> result;
+
+ result.reserve(4);
+
+ Real lambda_middle = (lower_left().lambda() + upper_right().lambda()) / 2.0;
+ Real mu_middle = (lower_left().mu() + upper_right().mu()) / 2.0;
+
+ DualPoint<Real> refinement_center(axis_type(), angle_type(), lambda_middle, mu_middle);
+
+ result.emplace_back(lower_left_, refinement_center);
+
+ result.emplace_back(DualPoint<Real>(axis_type(), angle_type(), lambda_middle, mu_min()),
+ DualPoint<Real>(axis_type(), angle_type(), lambda_max(), mu_middle));
+
+ result.emplace_back(refinement_center, upper_right_);
+
+ result.emplace_back(DualPoint<Real>(axis_type(), angle_type(), lambda_min(), mu_middle),
+ DualPoint<Real>(axis_type(), angle_type(), lambda_middle, mu_max()));
+ return result;
+ }
+
+ template<class Real>
+ bool DualBox<Real>::operator==(const DualBox& other) const
+ {
+ return lower_left() == other.lower_left() &&
+ upper_right() == other.upper_right();
+ }
+
+ template<class Real>
+ bool DualBox<Real>::contains(const DualPoint<Real>& dp) const
+ {
+ return dp.angle_type() == angle_type() && dp.axis_type() == axis_type() &&
+ mu_max() >= dp.mu() &&
+ mu_min() <= dp.mu() &&
+ lambda_min() <= dp.lambda() &&
+ lambda_max() >= dp.lambda();
+ }
+
+ template<class Real>
+ DualPoint<Real> DualBox<Real>::lower_right() const
+ {
+ return DualPoint<Real>(lower_left_.axis_type(), lower_left_.angle_type(), lambda_max(), mu_min());
+ }
+
+ template<class Real>
+ DualPoint<Real> DualBox<Real>::upper_left() const
+ {
+ return DualPoint<Real>(lower_left_.axis_type(), lower_left_.angle_type(), lambda_min(), mu_max());
+ }
+}
diff --git a/matching/include/dual_point.h b/matching/include/dual_point.h
new file mode 100644
index 0000000..8438860
--- /dev/null
+++ b/matching/include/dual_point.h
@@ -0,0 +1,107 @@
+#ifndef MATCHING_DISTANCE_DUAL_POINT_H
+#define MATCHING_DISTANCE_DUAL_POINT_H
+
+#include <vector>
+#include <ostream>
+#include <tuple>
+
+#include "common_util.h"
+#include "box.h"
+
+namespace md {
+
+ enum class AxisType {
+ x_type, y_type
+ };
+ enum class AngleType {
+ flat, steep
+ };
+
+ // class has two flags of AxisType and AngleType.
+ // ATTENTION. == operator is not overloaded,
+ // so, e.g., line y = x has 4 different non-equal representation.
+ // we are unlikely to ever need this, because 4 cases are
+ // always treated separately.
+ template<class Real_>
+ class DualPoint {
+ public:
+ using Real = Real_;
+
+ DualPoint() = default;
+
+ DualPoint(const DualPoint&) = default;
+
+ DualPoint(DualPoint&&) = default;
+
+ DualPoint& operator=(const DualPoint& other)& = default;
+
+ DualPoint& operator=(DualPoint&& other) = default;
+
+ DualPoint(AxisType axis_type, AngleType angle_type, Real lambda, Real mu);
+
+ Real lambda() const { return lambda_; }
+
+ Real mu() const { return mu_; }
+
+ // angle between line and x-axis
+ Real gamma() const;
+
+ bool is_steep() const { return angle_type_ == AngleType::steep; }
+
+ bool is_flat() const { return angle_type_ == AngleType::flat; }
+
+ bool is_x_type() const { return axis_type_ == AxisType::x_type; }
+
+ bool is_y_type() const { return axis_type_ == AxisType::y_type; }
+
+ bool operator<(const DualPoint& rhs) const;
+
+ AxisType axis_type() const { return axis_type_; }
+ AngleType angle_type() const { return angle_type_; }
+
+ // throw exception, if fields are invalid
+ // return true otherwise
+ bool sanity_check() const;
+
+ Real weighted_push(Point<Real> p) const;
+ Point<Real> push(Point<Real> p) const;
+
+ bool is_horizontal() const;
+ bool is_vertical() const;
+
+ bool goes_below(Point<Real> p) const;
+ bool goes_above(Point<Real> p) const;
+
+ bool contains(Point<Real> p) const;
+
+ Real x_slope() const;
+ Real y_slope() const;
+
+ Real x_intercept() const;
+ Real y_intercept() const;
+
+ Real x_from_y(Real y) const;
+ Real y_from_x(Real x) const;
+
+ Real weight() const;
+
+ bool operator==(const DualPoint& other) const;
+
+ private:
+ AxisType axis_type_ {AxisType::y_type};
+ AngleType angle_type_ {AngleType::flat};
+ // both initial values are invalid: lambda must be between 0 and 1
+ Real lambda_ {-1.0};
+ Real mu_ {-1.0};
+ };
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const DualPoint<Real>& dp);
+
+ template<class Real>
+ DualPoint<Real> midpoint(DualPoint<Real> x, DualPoint<Real> y);
+};
+
+#include "dual_point.hpp"
+
+#endif //MATCHING_DISTANCE_DUAL_POINT_H
diff --git a/matching/include/dual_point.hpp b/matching/include/dual_point.hpp
new file mode 100644
index 0000000..04e25f2
--- /dev/null
+++ b/matching/include/dual_point.hpp
@@ -0,0 +1,299 @@
+namespace md {
+
+ inline std::ostream& operator<<(std::ostream& os, const AxisType& at)
+ {
+ if (at == AxisType::x_type)
+ os << "x-type";
+ else
+ os << "y-type";
+ return os;
+ }
+
+ inline std::ostream& operator<<(std::ostream& os, const AngleType& at)
+ {
+ if (at == AngleType::flat)
+ os << "flat";
+ else
+ os << "steep";
+ return os;
+ }
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const DualPoint<Real>& dp)
+ {
+ os << "Line(" << dp.axis_type() << ", ";
+ os << dp.angle_type() << ", ";
+ os << dp.lambda() << ", ";
+ os << dp.mu() << ", equation: ";
+ if (not dp.is_vertical()) {
+ os << "y = " << dp.y_slope() << " x + " << dp.y_intercept();
+ } else {
+ os << "x = " << dp.x_intercept();
+ }
+ os << " )";
+ return os;
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::operator<(const DualPoint<Real>& rhs) const
+ {
+ return std::tie(axis_type_, angle_type_, lambda_, mu_)
+ < std::tie(rhs.axis_type_, rhs.angle_type_, rhs.lambda_, rhs.mu_);
+ }
+
+ template<class Real>
+ DualPoint<Real>::DualPoint(AxisType axis_type, AngleType angle_type, Real lambda, Real mu)
+ :
+ axis_type_(axis_type),
+ angle_type_(angle_type),
+ lambda_(lambda),
+ mu_(mu)
+ {
+ assert(sanity_check());
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::sanity_check() const
+ {
+ if (lambda_ < 0.0)
+ throw std::runtime_error("Invalid line, negative lambda");
+ if (lambda_ > 1.0)
+ throw std::runtime_error("Invalid line, lambda > 1");
+ if (mu_ < 0.0)
+ throw std::runtime_error("Invalid line, negative mu");
+ return true;
+ }
+
+ template<class Real>
+ Real DualPoint<Real>::gamma() const
+ {
+ if (is_steep())
+ return atan(Real(1.0) / lambda_);
+ else
+ return atan(lambda_);
+ }
+
+ template<class Real>
+ DualPoint<Real> midpoint(DualPoint<Real> x, DualPoint<Real> y)
+ {
+ assert(x.angle_type() == y.angle_type() and x.axis_type() == y.axis_type());
+ Real lambda_mid = (x.lambda() + y.lambda()) / 2;
+ Real mu_mid = (x.mu() + y.mu()) / 2;
+ return DualPoint<Real>(x.axis_type(), x.angle_type(), lambda_mid, mu_mid);
+
+ }
+
+ // return k in the line equation y = kx + b
+ template<class Real>
+ Real DualPoint<Real>::y_slope() const
+ {
+ if (is_flat())
+ return lambda();
+ else
+ return Real(1.0) / lambda();
+ }
+
+ // return k in the line equation x = ky + b
+ template<class Real>
+ Real DualPoint<Real>::x_slope() const
+ {
+ if (is_flat())
+ return Real(1.0) / lambda();
+ else
+ return lambda();
+ }
+
+ // return b in the line equation y = kx + b
+ template<class Real>
+ Real DualPoint<Real>::y_intercept() const
+ {
+ if (is_y_type()) {
+ return mu();
+ } else {
+ // x = x_slope * y + mu = x_slope * (y + mu / x_slope)
+ // x-intercept is -mu/x_slope = -mu * y_slope
+ return -mu() * y_slope();
+ }
+ }
+
+ // return k in the line equation x = ky + b
+ template<class Real>
+ Real DualPoint<Real>::x_intercept() const
+ {
+ if (is_x_type()) {
+ return mu();
+ } else {
+ // y = y_slope * x + mu = y_slope (x + mu / y_slope)
+ // x_intercept is -mu/y_slope = -mu * x_slope
+ return -mu() * x_slope();
+ }
+ }
+
+ template<class Real>
+ Real DualPoint<Real>::x_from_y(Real y) const
+ {
+ if (is_horizontal())
+ throw std::runtime_error("x_from_y called on horizontal line");
+ else
+ return x_slope() * y + x_intercept();
+ }
+
+ template<class Real>
+ Real DualPoint<Real>::y_from_x(Real x) const
+ {
+ if (is_vertical())
+ throw std::runtime_error("x_from_y called on horizontal line");
+ else
+ return y_slope() * x + y_intercept();
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::is_horizontal() const
+ {
+ return is_flat() and lambda() == 0;
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::is_vertical() const
+ {
+ return is_steep() and lambda() == 0;
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::contains(Point<Real> p) const
+ {
+ if (is_vertical())
+ return p.x == x_from_y(p.y);
+ else
+ return p.y == y_from_x(p.x);
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::goes_below(Point<Real> p) const
+ {
+ if (is_vertical())
+ return p.x <= x_from_y(p.y);
+ else
+ return p.y >= y_from_x(p.x);
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::goes_above(Point<Real> p) const
+ {
+ if (is_vertical())
+ return p.x >= x_from_y(p.y);
+ else
+ return p.y <= y_from_x(p.x);
+ }
+
+ template<class Real>
+ Point<Real> DualPoint<Real>::push(Point<Real> p) const
+ {
+ Point<Real> result;
+ // if line is below p, we push horizontally
+ bool horizontal_push = goes_below(p);
+ if (is_x_type()) {
+ if (is_flat()) {
+ if (horizontal_push) {
+ result.x = p.y / lambda() + mu();
+ result.y = p.y;
+ } else {
+ // vertical push
+ result.x = p.x;
+ result.y = lambda() * (p.x - mu());
+ }
+ } else {
+ // steep
+ if (horizontal_push) {
+ result.x = lambda() * p.y + mu();
+ result.y = p.y;
+ } else {
+ // vertical push
+ result.x = p.x;
+ result.y = (p.x - mu()) / lambda();
+ }
+ }
+ } else {
+ // y-type
+ if (is_flat()) {
+ if (horizontal_push) {
+ result.x = (p.y - mu()) / lambda();
+ result.y = p.y;
+ } else {
+ // vertical push
+ result.x = p.x;
+ result.y = lambda() * p.x + mu();
+ }
+ } else {
+ // steep
+ if (horizontal_push) {
+ result.x = (p.y - mu()) * lambda();
+ result.y = p.y;
+ } else {
+ // vertical push
+ result.x = p.x;
+ result.y = p.x / lambda() + mu();
+ }
+ }
+ }
+ return result;
+ }
+
+ template<class Real>
+ Real DualPoint<Real>::weighted_push(Point<Real> p) const
+ {
+ // if line is below p, we push horizontally
+ bool horizontal_push = goes_below(p);
+ if (is_x_type()) {
+ if (is_flat()) {
+ if (horizontal_push) {
+ return p.y;
+ } else {
+ // vertical push
+ return lambda() * (p.x - mu());
+ }
+ } else {
+ // steep
+ if (horizontal_push) {
+ return lambda() * p.y;
+ } else {
+ // vertical push
+ return (p.x - mu());
+ }
+ }
+ } else {
+ // y-type
+ if (is_flat()) {
+ if (horizontal_push) {
+ return p.y - mu();
+ } else {
+ // vertical push
+ return lambda() * p.x;
+ }
+ } else {
+ // steep
+ if (horizontal_push) {
+ return lambda() * (p.y - mu());
+ } else {
+ // vertical push
+ return p.x;
+ }
+ }
+ }
+ }
+
+ template<class Real>
+ bool DualPoint<Real>::operator==(const DualPoint<Real>& other) const
+ {
+ return axis_type() == other.axis_type() and
+ angle_type() == other.angle_type() and
+ mu() == other.mu() and
+ lambda() == other.lambda();
+ }
+
+ template<class Real>
+ Real DualPoint<Real>::weight() const
+ {
+ return lambda_ / sqrt(1 + lambda_ * lambda_);
+ }
+} // namespace md
diff --git a/matching/include/matching_distance.h b/matching/include/matching_distance.h
new file mode 100644
index 0000000..618330d
--- /dev/null
+++ b/matching/include/matching_distance.h
@@ -0,0 +1,290 @@
+#pragma once
+
+#include <vector>
+#include <limits>
+#include <utility>
+#include <ostream>
+#include <chrono>
+#include <tuple>
+#include <algorithm>
+
+
+#include "common_defs.h"
+#include "cell_with_value.h"
+#include "box.h"
+#include "dual_point.h"
+#include "dual_box.h"
+#include "persistence_module.h"
+#include "bifiltration.h"
+#include "bottleneck.h"
+
+namespace md {
+
+#ifdef MD_PRINT_HEAT_MAP
+ template<class Real>
+ using HeatMap = std::map<DualPoint<Real>, Real>;
+
+ template<class Real>
+ using HeatMaps = std::map<int, HeatMap<Real>>;
+#endif
+
+ enum class BoundStrategy {
+ bruteforce,
+ local_dual_bound,
+ local_dual_bound_refined,
+ local_dual_bound_for_each_point,
+ local_combined
+ };
+
+ enum class TraverseStrategy {
+ depth_first,
+ breadth_first,
+ breadth_first_value,
+ upper_bound
+ };
+
+ inline std::ostream& operator<<(std::ostream& os, const BoundStrategy& s)
+ {
+ switch(s) {
+ case BoundStrategy::bruteforce :
+ os << "bruteforce";
+ break;
+ case BoundStrategy::local_dual_bound :
+ os << "local_grob";
+ break;
+ case BoundStrategy::local_combined :
+ os << "local_combined";
+ break;
+ case BoundStrategy::local_dual_bound_refined :
+ os << "local_refined";
+ break;
+ case BoundStrategy::local_dual_bound_for_each_point :
+ os << "local_for_each_point";
+ break;
+ default:
+ os << "FORGOTTEN BOUND STRATEGY";
+ }
+ return os;
+ }
+
+ inline std::ostream& operator<<(std::ostream& os, const TraverseStrategy& s)
+ {
+ switch(s) {
+ case TraverseStrategy::depth_first :
+ os << "DFS";
+ break;
+ case TraverseStrategy::breadth_first :
+ os << "BFS";
+ break;
+ case TraverseStrategy::breadth_first_value :
+ os << "BFS-VAL";
+ break;
+ case TraverseStrategy::upper_bound :
+ os << "UB";
+ break;
+ default:
+ os << "FORGOTTEN TRAVERSE STRATEGY";
+ }
+ return os;
+ }
+
+ inline std::istream& operator>>(std::istream& is, TraverseStrategy& s)
+ {
+ std::string ss;
+ is >> ss;
+ if (ss == "DFS") {
+ s = TraverseStrategy::depth_first;
+ } else if (ss == "BFS") {
+ s = TraverseStrategy::breadth_first;
+ } else if (ss == "BFS-VAL") {
+ s = TraverseStrategy::breadth_first_value;
+ } else if (ss == "UB") {
+ s = TraverseStrategy::upper_bound;
+ } else {
+ throw std::runtime_error("UNKNOWN TRAVERSE STRATEGY");
+ }
+ return is;
+ }
+
+
+ inline std::istream& operator>>(std::istream& is, BoundStrategy& s)
+ {
+ std::string ss;
+ is >> ss;
+ if (ss == "bruteforce") {
+ s = BoundStrategy::bruteforce;
+ } else if (ss == "local_grob") {
+ s = BoundStrategy::local_dual_bound;
+ } else if (ss == "local_combined") {
+ s = BoundStrategy::local_combined;
+ } else if (ss == "local_refined") {
+ s = BoundStrategy::local_dual_bound_refined;
+ } else if (ss == "local_for_each_point") {
+ s = BoundStrategy::local_dual_bound_for_each_point;
+ } else {
+ throw std::runtime_error("UNKNOWN BOUND STRATEGY");
+ }
+ return is;
+ }
+
+ inline BoundStrategy bs_from_string(std::string s)
+ {
+ std::stringstream ss(s);
+ BoundStrategy result;
+ ss >> result;
+ return result;
+ }
+
+ inline TraverseStrategy ts_from_string(std::string s)
+ {
+ std::stringstream ss(s);
+ TraverseStrategy result;
+ ss >> result;
+ return result;
+ }
+
+ template<class Real>
+ struct CalculationParams {
+ static constexpr int ALL_DIMENSIONS = -1;
+
+ Real hera_epsilon {0.001}; // relative error in hera call
+ Real delta {0.1}; // relative error for matching distance
+ int max_depth {8}; // maximal number of refinenemnts
+ int initialization_depth {2};
+ int dim {0}; // in which dim to calculate the distance; use ALL_DIMENSIONS to get max over all dims
+ BoundStrategy bound_strategy {BoundStrategy::local_combined};
+ TraverseStrategy traverse_strategy {TraverseStrategy::breadth_first};
+ bool tolerate_max_iter_exceeded {false};
+ Real actual_error {std::numeric_limits<Real>::max()};
+ int actual_max_depth {0};
+ int n_hera_calls {0}; // for experiments only; is set in matching_distance function, input value is ignored
+
+ // stop looping over points immediately, if current point's displacement is too large
+ // to prune the cell
+ // if true, cells are pruned immediately, and bounds may increase
+ // (just return something large enough to not prune the cell)
+ bool stop_asap { true };
+
+ // print statistics on each quad-tree level
+ bool print_stats { false };
+
+#ifdef MD_PRINT_HEAT_MAP
+ HeatMaps<Real> heat_maps;
+#endif
+ };
+
+
+ template<class Real_, class DiagramProvider>
+ class DistanceCalculator {
+
+ using Real = Real_;
+ using CellValueVector = std::vector<CellWithValue<Real>>;
+
+ public:
+ DistanceCalculator(const DiagramProvider& a,
+ const DiagramProvider& b,
+ CalculationParams<Real>& params);
+
+ Real distance();
+
+ int get_hera_calls_number() const;
+
+#ifndef MD_TEST_CODE
+ private:
+#endif
+
+ DiagramProvider module_a_;
+ DiagramProvider module_b_;
+
+ CalculationParams<Real>& params_;
+
+ int n_hera_calls_;
+ std::map<int, int> n_hera_calls_per_level_;
+ Real distance_;
+
+ // if calculate_on_intermediate, then weighted distance
+ // will be calculated on centers of each grid in between
+ CellValueVector get_refined_grid(int init_depth, bool calculate_on_intermediate, bool calculate_on_last = true);
+
+ CellValueVector get_initial_dual_grid(Real& lower_bound);
+
+#ifdef MD_PRINT_HEAT_MAP
+ void heatmap_in_dimension(int dim, int depth);
+#endif
+
+ Real get_max_x(int module) const;
+
+ Real get_max_y(int module) const;
+
+ void set_cell_central_value(CellWithValue<Real>& dual_cell);
+
+ Real get_distance();
+
+ Real get_distance_pq();
+
+ Real get_max_possible_value(const CellWithValue<Real>* first_cell_ptr, int n_cells);
+
+ Real get_upper_bound(const CellWithValue<Real>& dual_cell, Real good_enough_upper_bound) const;
+
+ Real get_single_dgm_bound(const CellWithValue<Real>& dual_cell, ValuePoint vp, int module,
+ Real good_enough_value) const;
+
+ // this bound depends only on dual box
+ Real get_local_dual_bound(int module, const DualBox<Real>& dual_box) const;
+
+ Real get_local_dual_bound(const DualBox<Real>& dual_box) const;
+
+ // this bound depends only on dual box, is more accurate
+ Real get_local_refined_bound(int module, const DualBox<Real>& dual_box) const;
+
+ Real get_local_refined_bound(const DualBox<Real>& dual_box) const;
+
+ Real get_good_enough_upper_bound(Real lower_bound) const;
+
+ Real get_max_displacement_single_point(const CellWithValue<Real>& dual_cell, ValuePoint value_point,
+ const Point<Real>& p) const;
+
+ void check_upper_bound(const CellWithValue<Real>& dual_cell) const;
+
+ Real distance_on_line(DualPoint<Real> line);
+ Real distance_on_line_const(DualPoint<Real> line) const;
+
+ Real current_error(Real lower_bound, Real upper_bound);
+ };
+
+ template<class Real>
+ Real matching_distance(const Bifiltration<Real>& bif_a, const Bifiltration<Real>& bif_b,
+ CalculationParams<Real>& params);
+
+ template<class Real>
+ Real matching_distance(const ModulePresentation<Real>& mod_a, const ModulePresentation<Real>& mod_b,
+ CalculationParams<Real>& params);
+
+ // for upper bound experiment
+ struct UbExperimentRecord {
+ double error;
+ double lower_bound;
+ double upper_bound;
+ CellWithValue<double> cell;
+ long long int time;
+ long long int n_hera_calls;
+ };
+
+ inline std::ostream& operator<<(std::ostream& os, const UbExperimentRecord& r)
+ {
+ os << r.time << "\t" << r.n_hera_calls << "\t" << r.error << "\t" << r.lower_bound << "\t" << r.upper_bound;
+ return os;
+ }
+
+
+ template<class K, class V>
+ void print_map(const std::map<K, V>& dic)
+ {
+ for(const auto kv : dic) {
+ std::cout << kv.first << " -> " << kv.second << "\n";
+ }
+ }
+
+} // namespace md
+
+#include "matching_distance.hpp"
diff --git a/matching/include/matching_distance.hpp b/matching/include/matching_distance.hpp
new file mode 100644
index 0000000..f7f44a5
--- /dev/null
+++ b/matching/include/matching_distance.hpp
@@ -0,0 +1,722 @@
+namespace md {
+
+ template<class R, class T>
+ void DistanceCalculator<R, T>::check_upper_bound(const CellWithValue<R>& dual_cell) const
+ {
+ const int n_samples_lambda = 100;
+ const int n_samples_mu = 100;
+ DualBox<R> db = dual_cell.dual_box();
+ R min_lambda = db.lambda_min();
+ R max_lambda = db.lambda_max();
+ R min_mu = db.mu_min();
+ R max_mu = db.mu_max();
+
+ R h_lambda = (max_lambda - min_lambda) / n_samples_lambda;
+ R h_mu = (max_mu - min_mu) / n_samples_mu;
+ for(int i = 1; i < n_samples_lambda; ++i) {
+ for(int j = 1; j < n_samples_mu; ++j) {
+ R lambda = min_lambda + i * h_lambda;
+ R mu = min_mu + j * h_mu;
+ DualPoint<R> l(db.axis_type(), db.angle_type(), lambda, mu);
+ R other_result = distance_on_line_const(l);
+ R diff = fabs(dual_cell.stored_upper_bound() - other_result);
+ if (other_result > dual_cell.stored_upper_bound()) {
+ throw std::runtime_error("Wrong delta estimate");
+ }
+ }
+ }
+ }
+
+ // for all lines l, l' inside dual box,
+ // find the upper bound on the difference of weighted pushes of p
+ template<class R, class T>
+ R
+ DistanceCalculator<R, T>::get_max_displacement_single_point(const CellWithValue<R>& dual_cell, ValuePoint vp,
+ const Point<R>& p) const
+ {
+ assert(p.x >= 0 && p.y >= 0);
+
+#ifdef MD_DEBUG
+ std::vector<long long int> debug_ids = {3, 13, 54, 218, 350, 382, 484, 795, 2040, 8415, 44076};
+ bool debug = false; // std::find(debug_ids.begin(), debug_ids.end(), dual_cell.id) != debug_ids.end();
+#endif
+ DualPoint<R> line = dual_cell.value_point(vp);
+ const R base_value = line.weighted_push(p);
+
+ R result = 0.0;
+ for(DualPoint<R> dp : dual_cell.dual_box().critical_points(p)) {
+ R dp_value = dp.weighted_push(p);
+ result = std::max(result, fabs(base_value - dp_value));
+ }
+
+#ifdef MD_DO_FULL_CHECK
+ auto db = dual_cell.dual_box();
+ std::uniform_real_distribution<R> dlambda(db.lambda_min(), db.lambda_max());
+ std::uniform_real_distribution<R> dmu(db.mu_min(), db.mu_max());
+ std::mt19937 gen(1);
+ for(int i = 0; i < 1000; ++i) {
+ R lambda = dlambda(gen);
+ R mu = dmu(gen);
+ DualPoint<R> dp_random { db.axis_type(), db.angle_type(), lambda, mu };
+ R dp_value = dp_random.weighted_push(p);
+ if (fabs(base_value - dp_value) > result) {
+ throw std::runtime_error("error in get_max_displacement_single_value");
+ }
+ }
+#endif
+
+ return result;
+ }
+
+ template<class R, class T>
+ typename DistanceCalculator<R, T>::CellValueVector DistanceCalculator<R, T>::get_initial_dual_grid(R& lower_bound)
+ {
+ CellValueVector result = get_refined_grid(params_.initialization_depth, false, true);
+
+ lower_bound = -1;
+ for(const auto& dc : result) {
+ lower_bound = std::max(lower_bound, dc.max_corner_value());
+ }
+
+ assert(lower_bound >= 0);
+
+ for(auto& dual_cell : result) {
+ R good_enough_ub = get_good_enough_upper_bound(lower_bound);
+ R max_value_on_cell = get_upper_bound(dual_cell, good_enough_ub);
+ dual_cell.set_max_possible_value(max_value_on_cell);
+
+#ifdef MD_DO_FULL_CHECK
+ check_upper_bound(dual_cell);
+#endif
+ }
+
+ return result;
+ }
+
+ template<class R, class T>
+ typename DistanceCalculator<R, T>::CellValueVector
+ DistanceCalculator<R, T>::get_refined_grid(int init_depth, bool calculate_on_intermediate, bool calculate_on_last)
+ {
+ const R y_max = std::max(module_a_.max_y(), module_b_.max_y());
+ const R x_max = std::max(module_a_.max_x(), module_b_.max_x());
+
+ const R lambda_min = 0;
+ const R lambda_max = 1;
+
+ const R mu_min = 0;
+
+ DualBox<R> x_flat(DualPoint<R>(AxisType::x_type, AngleType::flat, lambda_min, mu_min),
+ DualPoint<R>(AxisType::x_type, AngleType::flat, lambda_max, x_max));
+
+ DualBox<R> x_steep(DualPoint<R>(AxisType::x_type, AngleType::steep, lambda_min, mu_min),
+ DualPoint<R>(AxisType::x_type, AngleType::steep, lambda_max, x_max));
+
+ DualBox<R> y_flat(DualPoint<R>(AxisType::y_type, AngleType::flat, lambda_min, mu_min),
+ DualPoint<R>(AxisType::y_type, AngleType::flat, lambda_max, y_max));
+
+ DualBox<R> y_steep(DualPoint<R>(AxisType::y_type, AngleType::steep, lambda_min, mu_min),
+ DualPoint<R>(AxisType::y_type, AngleType::steep, lambda_max, y_max));
+
+ CellWithValue<R> x_flat_cell(x_flat, 0);
+ CellWithValue<R> x_steep_cell(x_steep, 0);
+ CellWithValue<R> y_flat_cell(y_flat, 0);
+ CellWithValue<R> y_steep_cell(y_steep, 0);
+
+ if (init_depth == 0) {
+ DualPoint<R> diagonal_x_flat(AxisType::x_type, AngleType::flat, 1, 0);
+
+ R diagonal_value = distance_on_line(diagonal_x_flat);
+ n_hera_calls_per_level_[0]++;
+
+ x_flat_cell.set_value_at(ValuePoint::lower_right, diagonal_value);
+ y_flat_cell.set_value_at(ValuePoint::lower_right, diagonal_value);
+ x_steep_cell.set_value_at(ValuePoint::lower_right, diagonal_value);
+ y_steep_cell.set_value_at(ValuePoint::lower_right, diagonal_value);
+ }
+
+#ifdef MD_DEBUG
+ x_flat_cell.id = 1;
+ x_steep_cell.id = 2;
+ y_flat_cell.id = 3;
+ y_steep_cell.id = 4;
+ CellWithValue<R>::max_id = 4;
+#endif
+
+ CellValueVector result {x_flat_cell, x_steep_cell, y_flat_cell, y_steep_cell};
+
+ if (init_depth == 0) {
+ return result;
+ }
+
+ CellValueVector refined_result;
+
+ for(int i = 1; i <= init_depth; ++i) {
+ refined_result.clear();
+ for(const auto& dual_cell : result) {
+ for(auto refined_cell : dual_cell.get_refined_cells()) {
+ // we calculate for init_dept - 1, not init_depth,
+ // because we want the cells to have value at a corner
+ if ((i == init_depth - 1 and calculate_on_last) or calculate_on_intermediate)
+ set_cell_central_value(refined_cell);
+ refined_result.push_back(refined_cell);
+ }
+ }
+ result = std::move(refined_result);
+ }
+ return result;
+ }
+
+ template<class R, class T>
+ DistanceCalculator<R, T>::DistanceCalculator(const T& a,
+ const T& b,
+ CalculationParams<R>& params)
+ :
+ module_a_(a),
+ module_b_(b),
+ params_(params)
+ {
+ // make all coordinates non-negative
+ auto min_coord = std::min(module_a_.minimal_coordinate(),
+ module_b_.minimal_coordinate());
+ if (min_coord < 0) {
+ module_a_.translate(-min_coord);
+ module_b_.translate(-min_coord);
+ }
+
+ assert(std::min({module_a_.min_x(), module_b_.min_x(), module_a_.min_y(),
+ module_b_.min_y()}) >= 0);
+
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_max_x(int module) const
+ {
+ return (module == 0) ? module_a_.max_x() : module_b_.max_x();
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_max_y(int module) const
+ {
+ return (module == 0) ? module_a_.max_y() : module_b_.max_y();
+ }
+
+ template<class R, class T>
+ R
+ DistanceCalculator<R, T>::get_local_refined_bound(const DualBox<R>& dual_box) const
+ {
+ return get_local_refined_bound(0, dual_box) + get_local_refined_bound(1, dual_box);
+ }
+
+ template<class R, class T>
+ R
+ DistanceCalculator<R, T>::get_local_refined_bound(int module, const DualBox<R>& dual_box) const
+ {
+ R d_lambda = dual_box.lambda_max() - dual_box.lambda_min();
+ R d_mu = dual_box.mu_max() - dual_box.mu_min();
+ R result;
+ if (dual_box.axis_type() == AxisType::x_type) {
+ if (dual_box.is_flat()) {
+ result = dual_box.lambda_max() * d_mu + (get_max_x(module) - dual_box.mu_min()) * d_lambda;
+ } else {
+ result = d_mu + get_max_y(module) * d_lambda;
+ }
+ } else {
+ // y-type
+ if (dual_box.is_flat()) {
+ result = d_mu + get_max_x(module) * d_lambda;
+ } else {
+ // steep
+ result = dual_box.lambda_max() * d_mu + (get_max_y(module) - dual_box.mu_min()) * d_lambda;
+ }
+ }
+ return result;
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_local_dual_bound(int module, const DualBox<R>& dual_box) const
+ {
+ R dlambda = dual_box.lambda_max() - dual_box.lambda_min();
+ R dmu = dual_box.mu_max() - dual_box.mu_min();
+
+ if (dual_box.is_flat()) {
+ return get_max_x(module) * dlambda + dmu;
+ } else {
+ return get_max_y(module) * dlambda + dmu;
+ }
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_local_dual_bound(const DualBox<R>& dual_box) const
+ {
+ return get_local_dual_bound(0, dual_box) + get_local_dual_bound(1, dual_box);
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_upper_bound(const CellWithValue<R>& dual_cell, R good_enough_ub) const
+ {
+ assert(good_enough_ub >= 0);
+
+ switch(params_.bound_strategy) {
+ case BoundStrategy::bruteforce:
+ return std::numeric_limits<R>::max();
+
+ case BoundStrategy::local_dual_bound:
+ return dual_cell.min_value() + get_local_dual_bound(dual_cell.dual_box());
+
+ case BoundStrategy::local_dual_bound_refined:
+ return dual_cell.min_value() + get_local_refined_bound(dual_cell.dual_box());
+
+ case BoundStrategy::local_combined: {
+ R cheap_upper_bound = dual_cell.min_value() + get_local_refined_bound(dual_cell.dual_box());
+ if (cheap_upper_bound < good_enough_ub) {
+ return cheap_upper_bound;
+ } else {
+ [[fallthrough]];
+ }
+ }
+
+ case BoundStrategy::local_dual_bound_for_each_point: {
+ R result = std::numeric_limits<R>::max();
+ for(ValuePoint vp : k_corner_vps) {
+ if (not dual_cell.has_value_at(vp)) {
+ continue;
+ }
+
+ R base_value = dual_cell.value_at(vp);
+ R bound_dgm_a = get_single_dgm_bound(dual_cell, vp, 0, good_enough_ub);
+
+ if (params_.stop_asap and bound_dgm_a + base_value >= good_enough_ub) {
+ // we want to return a valid upper bound, not just something that will prevent discarding the cell
+ // and we don't want to compute pushes for points in second bifiltration.
+ // so just return a constant time bound
+ return dual_cell.min_value() + get_local_refined_bound(dual_cell.dual_box());
+ }
+
+ R bound_dgm_b = get_single_dgm_bound(dual_cell, vp, 1,
+ std::max(R(0), good_enough_ub - bound_dgm_a));
+
+ result = std::min(result, base_value + bound_dgm_a + bound_dgm_b);
+
+ if (params_.stop_asap and result < good_enough_ub) {
+ break;
+ }
+ }
+ return result;
+ }
+ }
+ // to suppress compiler warning
+ return std::numeric_limits<R>::max();
+ }
+
+ // find maximal displacement of weighted points of m for all lines in dual_box
+ template<class R, class T>
+ R
+ DistanceCalculator<R, T>::get_single_dgm_bound(const CellWithValue<R>& dual_cell,
+ ValuePoint vp,
+ int module,
+ R good_enough_value) const
+ {
+ R result = 0;
+ Point<R> max_point;
+
+ const T& m = (module == 0) ? module_a_ : module_b_;
+ for(const auto& position : m.positions()) {
+ R x = get_max_displacement_single_point(dual_cell, vp, position);
+
+ if (x > result) {
+ result = x;
+ max_point = position;
+ }
+
+ if (params_.stop_asap and result > good_enough_value) {
+ // we want to return a valid upper bound,
+ // now we just see it is worse than we need, but it may be even more
+ // just return a valid upper bound
+ result = get_local_refined_bound(dual_cell.dual_box());
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::distance()
+ {
+ return get_distance_pq();
+ }
+
+ // calculate weighted bottleneneck distance between slices on line
+ // increments hera calls counter
+ template<class R, class T>
+ R DistanceCalculator<R, T>::distance_on_line(DualPoint<R> line)
+ {
+ ++n_hera_calls_;
+ R result = distance_on_line_const(line);
+ return result;
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::distance_on_line_const(DualPoint<R> line) const
+ {
+ // TODO: think about this - how to call Hera
+ auto dgm_a = module_a_.weighted_slice_diagram(line);
+ auto dgm_b = module_b_.weighted_slice_diagram(line);
+ R result;
+ if (params_.hera_epsilon > static_cast<R>(0)) {
+ result = hera::bottleneckDistApprox(dgm_a, dgm_b, params_.hera_epsilon) / ( params_.hera_epsilon + 1);
+ } else {
+ result = hera::bottleneckDistExact(dgm_a, dgm_b);
+ }
+ return result;
+ }
+
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_good_enough_upper_bound(R lower_bound) const
+ {
+ R result;
+ // in upper_bound strategy we only prune cells if they cannot improve the lower bound,
+ // otherwise the experiment is supposed to run indefinitely
+ if (params_.traverse_strategy == TraverseStrategy::upper_bound) {
+ result = lower_bound;
+ } else {
+ result = (1.0 + params_.delta) * lower_bound;
+ }
+ return result;
+ }
+
+ // helper function
+ // calculate weighted bt distance on cell center,
+ // assign distance value to cell, keep it in heat_map, and return
+ template<class R, class T>
+ void DistanceCalculator<R, T>::set_cell_central_value(CellWithValue<R>& dual_cell)
+ {
+ DualPoint<R> central_line {dual_cell.center()};
+
+ R new_value = distance_on_line(central_line);
+ n_hera_calls_per_level_[dual_cell.level() + 1]++;
+ dual_cell.set_value_at(ValuePoint::center, new_value);
+ params_.actual_max_depth = std::max(params_.actual_max_depth, dual_cell.level() + 1);
+
+#ifdef PRINT_HEAT_MAP
+ if (params_.bound_strategy == BoundStrategy::bruteforce) {
+ if (dual_cell.level() > params_.initialization_depth + 1
+ and params_.heat_maps[dual_cell.level()].count(dual_cell.center()) > 0) {
+ auto existing = params_.heat_maps[dual_cell.level()].find(dual_cell.center());
+ }
+ assert(dual_cell.level() <= params_.initialization_depth + 1
+ or params_.heat_maps[dual_cell.level()].count(dual_cell.center()) == 0);
+ params_.heat_maps[dual_cell.level()][dual_cell.center()] = new_value;
+ }
+#endif
+ }
+
+ // quick-and-dirty hack to efficiently traverse priority queue with dual cells
+ // returns maximal possible value on all cells in queue
+ // assumes that the underlying container is vector!
+ // cell_ptr: pointer to the first element in queue
+ // n_cells: queue size
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_max_possible_value(const CellWithValue<R>* cell_ptr, int n_cells)
+ {
+ R result = (n_cells > 0) ? cell_ptr->stored_upper_bound() : 0;
+ for(int i = 0; i < n_cells; ++i, ++cell_ptr) {
+ result = std::max(result, cell_ptr->stored_upper_bound());
+ }
+ return result;
+ }
+
+ // helper function:
+ // return current error from lower and upper bounds
+ // and save it in params_ (hence not const)
+ template<class R, class T>
+ R DistanceCalculator<R, T>::current_error(R lower_bound, R upper_bound)
+ {
+ R current_error = (lower_bound > 0.0) ? (upper_bound - lower_bound) / lower_bound
+ : std::numeric_limits<R>::max();
+ params_.actual_error = current_error;
+
+ return current_error;
+ }
+
+ // return matching distance
+ // use priority queue to store dual cells
+ // comparison function depends on the strategies in params_
+ // ressets hera calls counter
+ template<class R, class T>
+ R DistanceCalculator<R, T>::get_distance_pq()
+ {
+ std::map<int, long> n_cells_considered;
+ std::map<int, long> n_cells_pushed_into_queue;
+ long int n_too_deep_cells = 0;
+ std::map<int, long> n_cells_discarded;
+ std::map<int, long> n_cells_pruned;
+
+ std::chrono::high_resolution_clock timer;
+ auto start_time = timer.now();
+
+ n_hera_calls_ = 0;
+ n_hera_calls_per_level_.clear();
+
+
+ // if cell is too deep and is not pushed into queue,
+ // we still need to take its max value into account;
+ // the max over such cells is stored in max_result_on_too_fine_cells
+ R upper_bound_on_deep_cells = -1;
+
+ // user-defined less lambda function
+ // to regulate priority queue depending on strategy
+ auto dual_cell_less = [this](const CellWithValue<R>& a, const CellWithValue<R>& b) {
+
+ int a_level = a.level();
+ int b_level = b.level();
+ R a_value = a.max_corner_value();
+ R b_value = b.max_corner_value();
+ R a_ub = a.stored_upper_bound();
+ R b_ub = b.stored_upper_bound();
+ if (this->params_.traverse_strategy == TraverseStrategy::upper_bound and
+ (not a.has_max_possible_value() or not b.has_max_possible_value())) {
+ throw std::runtime_error("no upper bound on cell");
+ }
+ DualPoint<R> a_lower_left = a.dual_box().lower_left();
+ DualPoint<R> b_lower_left = b.dual_box().lower_left();
+
+ switch(this->params_.traverse_strategy) {
+ // in both breadth_first searches we want coarser cells
+ // to be processed first. Cells with smaller level must be larger,
+ // hence the minus in front of level
+ case TraverseStrategy::breadth_first:
+ return std::make_tuple(-a_level, a_lower_left)
+ < std::make_tuple(-b_level, b_lower_left);
+ case TraverseStrategy::breadth_first_value:
+ return std::make_tuple(-a_level, a_value, a_lower_left)
+ < std::make_tuple(-b_level, b_value, b_lower_left);
+ case TraverseStrategy::depth_first:
+ return std::make_tuple(a_value, a_level, a_lower_left)
+ < std::make_tuple(b_value, b_level, b_lower_left);
+ case TraverseStrategy::upper_bound:
+ return std::make_tuple(a_ub, a_level, a_lower_left)
+ < std::make_tuple(b_ub, b_level, b_lower_left);
+ default:
+ throw std::runtime_error("Forgotten case");
+ }
+ };
+
+ std::priority_queue<CellWithValue<R>, CellValueVector, decltype(dual_cell_less)> dual_cells_queue(
+ dual_cell_less);
+
+ // weighted bt distance on the center of current cell
+ R lower_bound = std::numeric_limits<R>::min();
+
+ // init pq and lower bound
+ for(auto& init_cell : get_initial_dual_grid(lower_bound)) {
+ dual_cells_queue.push(init_cell);
+ }
+
+ R upper_bound = get_max_possible_value(&dual_cells_queue.top(), dual_cells_queue.size());
+
+ std::vector<UbExperimentRecord> ub_experiment_results;
+
+ while(not dual_cells_queue.empty()) {
+
+ CellWithValue<R> dual_cell = dual_cells_queue.top();
+ dual_cells_queue.pop();
+ assert(dual_cell.has_corner_value()
+ and dual_cell.has_max_possible_value()
+ and dual_cell.max_corner_value() <= upper_bound);
+
+ n_cells_considered[dual_cell.level()]++;
+
+ bool discard_cell = false;
+
+ if (not params_.stop_asap) {
+ // if stop_asap is on, it is safer to never discard a cell
+ if (params_.bound_strategy == BoundStrategy::bruteforce) {
+ discard_cell = false;
+ } else if (params_.traverse_strategy == TraverseStrategy::upper_bound) {
+ discard_cell = (dual_cell.stored_upper_bound() <= lower_bound);
+ } else {
+ discard_cell = (dual_cell.stored_upper_bound() <= (1.0 + params_.delta) * lower_bound);
+ }
+ }
+
+ if (discard_cell) {
+ n_cells_discarded[dual_cell.level()]++;
+ continue;
+ }
+
+ // until now, dual_cell knows its value in one of its corners
+ // new_value will be the weighted distance at its center
+ set_cell_central_value(dual_cell);
+ R new_value = dual_cell.value_at(ValuePoint::center);
+ lower_bound = std::max(new_value, lower_bound);
+
+ assert(upper_bound >= lower_bound);
+
+ if (current_error(lower_bound, upper_bound) < params_.delta) {
+ break;
+ }
+
+ // refine cell and push 4 smaller cells into queue
+ for(auto refined_cell : dual_cell.get_refined_cells()) {
+
+ if (refined_cell.num_values() == 0)
+ throw std::runtime_error("no value on cell");
+
+ // if delta is smaller than good_enough_value, it allows to prune cell
+ R good_enough_ub = get_good_enough_upper_bound(lower_bound);
+
+ // upper bound of the parent holds for refined_cell
+ // and can sometimes be smaller!
+ R upper_bound_on_refined_cell = std::min(dual_cell.stored_upper_bound(),
+ get_upper_bound(refined_cell, good_enough_ub));
+
+ refined_cell.set_max_possible_value(upper_bound_on_refined_cell);
+
+#ifdef MD_DO_FULL_CHECK
+ check_upper_bound(refined_cell);
+#endif
+
+ bool prune_cell = false;
+
+ if (refined_cell.level() <= params_.max_depth) {
+ // cell might be added to queue; if it is not added, its maximal value can be safely ignored
+ if (params_.traverse_strategy == TraverseStrategy::upper_bound) {
+ prune_cell = (refined_cell.stored_upper_bound() <= lower_bound);
+ } else if (params_.bound_strategy != BoundStrategy::bruteforce) {
+ prune_cell = (refined_cell.stored_upper_bound() <= (1.0 + params_.delta) * lower_bound);
+ }
+ if (prune_cell)
+ n_cells_pruned[refined_cell.level()]++;
+// prune_cell = (max_result_on_refined_cell <= lower_bound);
+ } else {
+ // cell is too deep, it won't be added to queue
+ // we must memorize maximal value on this cell, because we won't see it anymore
+ prune_cell = true;
+ if (refined_cell.stored_upper_bound() > (1 + params_.delta) * lower_bound) {
+ n_too_deep_cells++;
+ }
+ upper_bound_on_deep_cells = std::max(upper_bound_on_deep_cells, refined_cell.stored_upper_bound());
+ }
+
+ if (not prune_cell) {
+ n_cells_pushed_into_queue[refined_cell.level()]++;
+ dual_cells_queue.push(refined_cell);
+ }
+ } // end loop over refined cells
+
+ if (dual_cells_queue.empty())
+ upper_bound = std::max(upper_bound, upper_bound_on_deep_cells);
+ else
+ upper_bound = std::max(upper_bound_on_deep_cells,
+ get_max_possible_value(&dual_cells_queue.top(), dual_cells_queue.size()));
+
+ if (params_.traverse_strategy == TraverseStrategy::upper_bound) {
+ upper_bound = dual_cells_queue.top().stored_upper_bound();
+
+ if (get_hera_calls_number() < 20 || get_hera_calls_number() % 20 == 0) {
+ auto elapsed = timer.now() - start_time;
+ UbExperimentRecord ub_exp_record;
+
+ ub_exp_record.error = current_error(lower_bound, upper_bound);
+ ub_exp_record.lower_bound = lower_bound;
+ ub_exp_record.upper_bound = upper_bound;
+ ub_exp_record.cell = dual_cells_queue.top();
+ ub_exp_record.n_hera_calls = n_hera_calls_;
+ ub_exp_record.time = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+
+#ifdef MD_DO_CHECKS
+ if (ub_experiment_results.size() > 0) {
+ auto prev = ub_experiment_results.back();
+ if (upper_bound > prev.upper_bound) {
+ throw std::runtime_error("die");
+ }
+
+ if (lower_bound < prev.lower_bound) {
+ throw std::runtime_error("die");
+ }
+ }
+#endif
+
+ ub_experiment_results.emplace_back(ub_exp_record);
+
+ std::cerr << "[UB_EXPERIMENT]\t" << ub_exp_record << "\n";
+ }
+ }
+
+ assert(upper_bound >= lower_bound);
+
+ if (current_error(lower_bound, upper_bound) < params_.delta) {
+ break;
+ }
+ }
+
+ params_.actual_error = current_error(lower_bound, upper_bound);
+
+ if (n_too_deep_cells > 0) {
+ std::cerr << "Warning: error not guaranteed, there were too deep cells.";
+ std::cerr << " Increase max_depth or delta, actual error = " << params_.actual_error << std::endl;
+ }
+ // otherwise actual_error in params can be larger than delta,
+ // but this is OK
+
+ if (params_.print_stats) {
+ std::cout << "EXIT STATS, cells considered:\n";
+ print_map(n_cells_considered);
+ std::cout << "EXIT STATS, cells discarded:\n";
+ print_map(n_cells_discarded);
+ std::cout << "EXIT STATS, cells pruned:\n";
+ print_map(n_cells_pruned);
+ std::cout << "EXIT STATS, cells pushed:\n";
+ print_map(n_cells_pushed_into_queue);
+ std::cout << "EXIT STATS, hera calls:\n";
+ print_map(n_hera_calls_per_level_);
+ std::cout << "EXIT STATS, too deep cells with high value: " << n_too_deep_cells << "\n";
+ }
+
+ return lower_bound;
+ }
+
+ template<class R, class T>
+ int DistanceCalculator<R, T>::get_hera_calls_number() const
+ {
+ return n_hera_calls_;
+ }
+
+ template<class R>
+ R matching_distance(const Bifiltration<R>& bif_a, const Bifiltration<R>& bif_b,
+ CalculationParams<R>& params)
+ {
+ R result;
+ // compute distance only in one dimension
+ if (params.dim != CalculationParams<R>::ALL_DIMENSIONS) {
+ BifiltrationProxy<R> bifp_a(bif_a, params.dim);
+ BifiltrationProxy<R> bifp_b(bif_b, params.dim);
+ DistanceCalculator<R, BifiltrationProxy<R>> runner(bifp_a, bifp_b, params);
+ result = runner.distance();
+ params.n_hera_calls = runner.get_hera_calls_number();
+ } else {
+ // compute distance in all dimensions, return maximal
+ result = -1;
+ for(int dim = 0; dim < std::max(bif_a.maximal_dim(), bif_b.maximal_dim()); ++dim) {
+ BifiltrationProxy<R> bifp_a(bif_a, params.dim);
+ BifiltrationProxy<R> bifp_b(bif_a, params.dim);
+ DistanceCalculator<R, BifiltrationProxy<R>> runner(bifp_a, bifp_b, params);
+ result = std::max(result, runner.distance());
+ params.n_hera_calls += runner.get_hera_calls_number();
+ }
+ }
+ return result;
+ }
+
+
+ template<class R>
+ R matching_distance(const ModulePresentation<R>& mod_a, const ModulePresentation<R>& mod_b,
+ CalculationParams<R>& params)
+ {
+ DistanceCalculator<R, ModulePresentation<R>> runner(mod_a, mod_b, params);
+ R result = runner.distance();
+ params.n_hera_calls = runner.get_hera_calls_number();
+ return result;
+ }
+} // namespace md
diff --git a/matching/include/opts/opts.h b/matching/include/opts/opts.h
new file mode 100644
index 0000000..1a9bbf7
--- /dev/null
+++ b/matching/include/opts/opts.h
@@ -0,0 +1,499 @@
+/**
+ * Author: Dmitriy Morozov <dmitriy@mrzv.org>
+ * The interface is heavily influenced by GetOptPP (https://code.google.com/p/getoptpp/).
+ * The parsing logic is from ProgramOptions.hxx (https://github.com/Fytch/ProgramOptions.hxx).
+ *
+ * History:
+ * - 2015-06-01: added Traits<...>::type_string() for long, unsigned long
+ * - ...
+ * - 2018-04-27: replace parsing logic with the one from ProgramOptions.hxx to
+ * make the parser compliant with [GNU Program Argument Syntax
+ * Conventions](https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html)
+ * - 2018-05-11: add dashed_non_option(), to accept arguments that are negative numbers
+ */
+
+#ifndef OPTS_OPTS_H
+#define OPTS_OPTS_H
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <memory>
+#include <cctype>
+#include <functional>
+
+namespace opts {
+
+// Converters
+template<class T>
+struct Converter
+{
+ Converter() {}
+ static
+ bool convert(const std::string& val, T& res)
+ {
+ std::istringstream iss(val);
+ iss >> res;
+ return !iss.fail() && iss.eof();
+ }
+};
+
+// Type
+template<class T>
+struct Traits
+{
+ static std::string type_string() { return "UNKNOWN TYPE"; }
+};
+
+template<>
+struct Traits<int>
+{
+ static std::string type_string() { return "INT"; }
+};
+
+template<>
+struct Traits<short int>
+{
+ static std::string type_string() { return "SHORT INT"; }
+};
+
+template<>
+struct Traits<long>
+{
+ static std::string type_string() { return "LONG"; }
+};
+
+template<>
+struct Traits<unsigned>
+{
+ static std::string type_string() { return "UNSIGNED INT"; }
+};
+
+template<>
+struct Traits<short unsigned>
+{
+ static std::string type_string() { return "SHORT UNSIGNED INT"; }
+};
+
+template<>
+struct Traits<unsigned long>
+{
+ static std::string type_string() { return "UNSIGNED LONG"; }
+};
+
+template<>
+struct Traits<float>
+{
+ static std::string type_string() { return "FLOAT"; }
+};
+
+template<>
+struct Traits<double>
+{
+ static std::string type_string() { return "DOUBLE"; }
+};
+
+template<>
+struct Traits<std::string>
+{
+ static std::string type_string() { return "STRING"; }
+};
+
+
+struct BasicOption
+{
+ using IsShort = std::function<bool(char)>;
+
+ BasicOption(char s_,
+ std::string l_,
+ std::string default_,
+ std::string type_,
+ std::string help_):
+ s(s_), l(l_), d(default_), t(type_), help(help_) {}
+ virtual ~BasicOption() {}
+
+ int long_size() const { return l.size() + 1 + t.size(); }
+
+ void output(std::ostream& out, int max_long) const
+ {
+ out << " ";
+ if (s)
+ out << '-' << s << ", ";
+ else
+ out << " ";
+
+ out << "--" << l << ' ';
+
+ if (!t.empty())
+ out << t;
+
+ for (int i = long_size(); i < max_long; ++i)
+ out << ' ';
+
+ out << " " << help;
+
+ if (!d.empty())
+ {
+ out << " [default: " << d << "]";
+ }
+ out << '\n';
+ }
+
+ virtual bool flag() const { return false; }
+ virtual bool parse(int argc, char** argv, int& i, int j, IsShort is_short);
+ virtual bool set(std::string arg) =0;
+
+ char s;
+ std::string l;
+ std::string d;
+ std::string t;
+ std::string help;
+};
+
+// Option
+template<class T>
+struct OptionContainer: public BasicOption
+{
+ OptionContainer(char s_,
+ const std::string& l_,
+ T& var_,
+ const std::string& help_,
+ const std::string& type_ = Traits<T>::type_string()):
+ BasicOption(s_, l_, default_value(var_), type_, help_),
+ var(&var_) {}
+
+ static
+ std::string default_value(const T& def)
+ {
+ std::ostringstream oss;
+ oss << def;
+ return oss.str();
+ }
+
+ bool set(std::string s) override { return Converter<T>::convert(s, *var); }
+
+ T* var;
+};
+
+template<>
+struct OptionContainer<bool>: public BasicOption
+{
+ OptionContainer(char s_,
+ const std::string& l_,
+ bool& var_,
+ const std::string& help_):
+ BasicOption(s_, l_, "", "", help_),
+ var(&var_) { *var = false; }
+
+ bool parse(int, char**, int&, int, IsShort) override { *var = true; return true; }
+ bool set(std::string) override { return true; }
+ bool flag() const override { return true; }
+
+ bool* var;
+};
+
+template<class T>
+struct OptionContainer< std::vector<T> >: public BasicOption
+{
+ OptionContainer(char s_,
+ const std::string& l_,
+ std::vector<T>& var_,
+ const std::string& help_,
+ const std::string& type_ = "SEQUENCE"):
+ BasicOption(s_, l_, default_value(var_), type_, help_),
+ var(&var_), first(true) { }
+
+ static
+ std::string default_value(const std::vector<T>& def)
+ {
+ std::ostringstream oss;
+ oss << "(";
+ if (def.size())
+ oss << def[0];
+ for (size_t i = 1; i < def.size(); ++i)
+ oss << ", " << def[i];
+ oss << ")";
+ return oss.str();
+ }
+
+ bool set(std::string s) override
+ {
+ if (first)
+ {
+ var->clear();
+ first = false;
+ }
+
+ T x;
+ bool result = Converter<T>::convert(s,x);
+ var->emplace_back(std::move(x));
+ return result;
+ }
+
+ std::vector<T>* var;
+ mutable bool first;
+};
+
+
+template<class T>
+std::unique_ptr<BasicOption>
+Option(char s, const std::string& l, T& var, const std::string& help) { return std::unique_ptr<BasicOption>{new OptionContainer<T>(s, l, var, help)}; }
+
+template<class T>
+std::unique_ptr<BasicOption>
+Option(char s, const std::string& l, T& var,
+ const std::string& type, const std::string& help) { return std::unique_ptr<BasicOption>{new OptionContainer<T>(s, l, var, help, type)}; }
+
+template<class T>
+std::unique_ptr<BasicOption>
+Option(const std::string& l, T& var, const std::string& help) { return std::unique_ptr<BasicOption>{new OptionContainer<T>(0, l, var, help)}; }
+
+template<class T>
+std::unique_ptr<BasicOption>
+Option(const std::string& l, T& var,
+ const std::string& type, const std::string& help) { return std::unique_ptr<BasicOption>{new OptionContainer<T>(0, l, var, help, type)}; }
+
+// PosOption
+template<class T>
+struct PosOptionContainer
+{
+ PosOptionContainer(T& var_):
+ var(&var_) {}
+
+ bool parse(std::list<std::string>& args) const
+ {
+ if (args.empty())
+ return false;
+
+ bool result = Converter<T>::convert(args.front(), *var);
+ if (!result)
+ std::cerr << "error: failed to parse " << args.front() << '\n';
+ args.pop_front();
+ return result;
+ }
+
+ T* var;
+};
+
+template<class T>
+PosOptionContainer<T>
+PosOption(T& var) { return PosOptionContainer<T>(var); }
+
+
+// Options
+struct Options
+{
+ Options():
+ failed(false) {}
+
+ inline
+ Options& operator>>(std::unique_ptr<BasicOption> opt);
+ template<class T>
+ Options& operator>>(const PosOptionContainer<T>& poc);
+
+ operator bool() { return !failed; }
+
+
+ friend
+ std::ostream&
+ operator<<(std::ostream& out, const Options& ops)
+ {
+ int max_long = 0;
+ for (auto& cur : ops.options)
+ {
+ int cur_long = cur->long_size();
+ if (cur_long > max_long)
+ max_long = cur_long;
+ }
+
+ out << "Options:\n";
+ for (auto& cur : ops.options)
+ cur->output(out, max_long);
+
+ return out;
+ }
+
+ bool parse(int argc, char** argv);
+
+ void unrecognized_option(std::string arg) const
+ {
+ std::cerr << "error: unrecognized option " << arg << '\n';
+ }
+
+ static bool dashed_non_option(char* arg, BasicOption::IsShort is_short)
+ {
+ return arg[ 0 ] == '-'
+ && (std::isdigit(arg[ 1 ]) || arg[ 1 ] == '.')
+ && !is_short(arg[ 1 ]);
+ }
+
+ private:
+ std::list<std::string> args;
+ std::list<std::unique_ptr<BasicOption>> options;
+ bool failed;
+};
+
+bool
+BasicOption::parse(int argc, char** argv, int& i, int j, IsShort is_short)
+{
+ char* argument;
+ char* cur_arg = argv[i];
+ // -v...
+ if (argv[i][j] == '\0')
+ {
+ // -v data
+ if (i + 1 < argc && (argv[i+1][0] != '-' || Options::dashed_non_option(argv[i+1], is_short)))
+ {
+ ++i;
+ argument = argv[i];
+ } else
+ {
+ std::cerr << "error: cannot find the argument; ignoring " << argv[i] << '\n';
+ return false;
+ }
+ } else if (argv[i][j] == '=')
+ {
+ // -v=data
+ argument = &argv[i][j+1];
+ } else if( j == 2 ) { // only for short options
+ // -vdata
+ argument = &argv[i][j];
+ } else
+ {
+ std::cerr << "error: unexpected character \'" << argv[i][j] << "\' ignoring " << argv[i] << '\n';
+ return false;
+ }
+ bool result = set(argument);
+ if (!result)
+ std::cerr << "error: failed to parse " << argument << " in " << cur_arg << '\n';
+ return result;
+}
+
+bool
+Options::parse(int argc, char** argv)
+{
+ std::map<char, BasicOption*> short_opts;
+ std::map<std::string, BasicOption*> long_opts;
+
+ for (auto& opt : options)
+ {
+ if (opt->s)
+ short_opts[opt->s] = opt.get();
+
+ long_opts[opt->l] = opt.get();
+ }
+
+ auto is_short = [&short_opts](char c) -> bool { return short_opts.find(c) != short_opts.end(); };
+
+ for (int i = 1; i < argc; ++i)
+ {
+ if( argv[ i ][ 0 ] == '\0' )
+ continue;
+ if( argv[ i ][ 0 ] != '-' || dashed_non_option(argv[i], is_short))
+ args.push_back(argv[i]);
+ else
+ {
+ // -...
+ if( argv[ i ][ 1 ] == '\0' )
+ {
+ // -
+ args.push_back(argv[i]);
+ } else if( argv[ i ][ 1 ] == '-' )
+ {
+ if( argv[ i ][ 2 ] == '\0' )
+ {
+ // --
+ while( ++i < argc )
+ args.push_back(argv[i]);
+ } else {
+ // --...
+ char* first = &argv[ i ][ 2 ];
+ char* last = first;
+ for(; *last != '=' && *last != '\0'; ++last);
+ if (first == last)
+ {
+ failed = true;
+ unrecognized_option(argv[i]);
+ } else
+ {
+ auto opt_it = long_opts.find(std::string{first,last});
+ if (opt_it == long_opts.end())
+ {
+ failed = true;
+ unrecognized_option(argv[i]);
+ } else
+ {
+ failed |= !opt_it->second->parse(argc, argv, i, last - argv[i], is_short);
+ }
+ }
+ }
+ } else
+ {
+ // -f...
+ auto opt_it = short_opts.find(argv[i][1]);
+ if (opt_it == short_opts.end())
+ {
+ failed = true;
+ unrecognized_option(argv[i]);
+ } else if (opt_it->second->flag())
+ {
+ opt_it->second->parse(argc, argv, i, 0, is_short); // arguments are meaningless; just sets the flag
+
+ // -fgh
+ char c;
+ for(int j = 1; (c = argv[i][j]) != '\0'; ++j)
+ {
+ if (!std::isprint(c) || c == '-')
+ {
+ failed = true;
+ std::cerr << "error: invalid character\'" << c << " ignoring " << &argv[i][j] << '\n';
+ break;
+ }
+ opt_it = short_opts.find(c);
+ if (opt_it == short_opts.end())
+ {
+ failed = true;
+ unrecognized_option("-" + std::string(1, c));
+ continue;
+ }
+ if (!opt_it->second->flag())
+ {
+ failed = true;
+ std::cerr << "error: non-void options not allowed in option packs; ignoring " << c << '\n';
+ continue;
+ }
+ opt_it->second->parse(argc, argv, i, 0, is_short); // arguments are meaningless; just sets the flag
+ }
+ } else
+ {
+ failed |= !opt_it->second->parse(argc, argv, i, 2, is_short);
+ }
+ }
+ }
+ }
+
+ return !failed;
+}
+
+Options&
+Options::operator>>(std::unique_ptr<BasicOption> opt)
+{
+ options.emplace_back(std::move(opt));
+ return *this;
+}
+
+template<class T>
+Options&
+Options::operator>>(const PosOptionContainer<T>& poc)
+{
+ if (!failed)
+ failed = !poc.parse(args);
+ return *this;
+}
+
+}
+
+#endif
diff --git a/matching/include/persistence_module.h b/matching/include/persistence_module.h
new file mode 100644
index 0000000..b68c21e
--- /dev/null
+++ b/matching/include/persistence_module.h
@@ -0,0 +1,111 @@
+#ifndef MATCHING_DISTANCE_PERSISTENCE_MODULE_H
+#define MATCHING_DISTANCE_PERSISTENCE_MODULE_H
+
+#include <cassert>
+#include <vector>
+#include <utility>
+#include <string>
+#include <numeric>
+#include <algorithm>
+#include <unordered_set>
+
+#include "phat/boundary_matrix.h"
+#include "phat/compute_persistence_pairs.h"
+
+#include "common_util.h"
+#include "dual_point.h"
+#include "box.h"
+
+namespace md {
+
+ /* ModulePresentation contains only information needed for matching
+ * distance computation over Z/2.
+ * Generators are represented as points (critical values),
+ * id i of generator g_i = its index in * vector generators_.
+ *
+ * Relations are represented by struct Relation, which has two members:
+ * position_ is a point at which relation appears,
+ * components_ contains indices of generators that sum to zero:
+ * if components_ = [i, ..., j], then the relation is g_i +...+ g_j = 0.
+ *
+ * ModulePresentation has member positions_ that contains all
+ * distinct positions of generators and relations;
+ * this member simplifies computing local linear bound.
+ */
+
+
+ template<class Real>
+ class ModulePresentation {
+ public:
+
+ using RealVec = std::vector<Real>;
+
+ enum Format { rivet_firep };
+
+ struct Relation {
+ Point<Real> position_;
+ IndexVec components_;
+
+ Relation() {}
+ Relation(const Point<Real>& _pos, const IndexVec& _components) : position_(_pos), components_(_components) {}
+
+ Real get_x() const { return position_.x; }
+ Real get_y() const { return position_.y; }
+ };
+
+ using RelVec = std::vector<Relation>;
+
+ ModulePresentation() {}
+
+ ModulePresentation(const PointVec<Real>& _generators, const RelVec& _relations);
+
+ Diagram<Real> weighted_slice_diagram(const DualPoint<Real>& line) const;
+
+ // translate all points by vector (a,a)
+ void translate(Real a);
+
+ // return minimal value of x- and y-coordinates
+ Real minimal_coordinate() const { return std::min(min_x(), min_y()); }
+
+ // return box that contains all positions of all simplices
+ Box<Real> bounding_box() const;
+
+ Real max_x() const { return max_x_; }
+
+ Real max_y() const { return max_y_; }
+
+ Real min_x() const { return min_x_; }
+
+ Real min_y() const { return min_y_; }
+
+ PointVec<Real> positions() const;
+
+#ifndef MD_TEST_CODE
+ private:
+#endif
+
+ PointVec<Real> generators_;
+ std::vector<Relation> relations_;
+ PointVec<Real> positions_;
+
+
+ Real max_x_ { std::numeric_limits<Real>::max() };
+ Real max_y_ { std::numeric_limits<Real>::max() };
+ Real min_x_ { -std::numeric_limits<Real>::max() };
+ Real min_y_ { -std::numeric_limits<Real>::max() };
+ Box<Real> bounding_box_;
+
+ void init_boundaries();
+
+ void project_generators(const DualPoint<Real>& slice, IndexVec& sorted_indices, RealVec& projections) const;
+ void project_relations(const DualPoint<Real>& slice, IndexVec& sorted_indices, RealVec& projections) const;
+
+ void get_slice_projection_matrix(const DualPoint<Real>& slice, phat::boundary_matrix<>& phat_matrix,
+ RealVec& gen_projections, RealVec& rel_projections) const;
+
+ };
+} // namespace md
+
+#include "persistence_module.hpp"
+
+#endif //MATCHING_DISTANCE_PERSISTENCE_MODULE_H
diff --git a/matching/include/persistence_module.hpp b/matching/include/persistence_module.hpp
new file mode 100644
index 0000000..7479e02
--- /dev/null
+++ b/matching/include/persistence_module.hpp
@@ -0,0 +1,192 @@
+namespace md {
+
+ /**
+ *
+ * @param values vector of length n
+ * @return [a_1,...,a_n] such that
+ * 1) values[a_1] <= values[a_2] <= ... <= values[a_n]
+ * 2) a_1,...,a_n is a permutation of 1,..,n
+ */
+
+ template<class T>
+ IndexVec get_sorted_indices(const std::vector<T>& values)
+ {
+ IndexVec result(values.size());
+ std::iota(result.begin(), result.end(), 0);
+ std::sort(result.begin(), result.end(),
+ [&values](size_t a, size_t b) { return values[a] < values[b]; });
+ return result;
+ }
+
+ // helper function to initialize const member positions_ in ModulePresentation
+ template<class Real>
+ PointVec<Real> concat_gen_and_rel_positions(const PointVec<Real>& generators,
+ const typename ModulePresentation<Real>::RelVec& relations)
+ {
+ std::unordered_set<Point<Real>> ps(generators.begin(), generators.end());
+ for(const auto& rel : relations) {
+ ps.insert(rel.position_);
+ }
+ return PointVec<Real>(ps.begin(), ps.end());
+ }
+
+
+ template<class Real>
+ void ModulePresentation<Real>::init_boundaries()
+ {
+ max_x_ = -std::numeric_limits<Real>::max();
+ max_y_ = -std::numeric_limits<Real>::max();
+ min_x_ = std::numeric_limits<Real>::max();
+ min_y_ = std::numeric_limits<Real>::max();
+
+ for(const auto& gen : positions_) {
+ min_x_ = std::min(gen.x, min_x_);
+ min_y_ = std::min(gen.y, min_y_);
+ max_x_ = std::max(gen.x, max_x_);
+ max_y_ = std::max(gen.y, max_y_);
+ }
+
+ bounding_box_ = Box<Real>(Point<Real>(min_x_, min_y_), Point<Real>(max_x_, max_y_));
+ }
+
+
+ template<class Real>
+ ModulePresentation<Real>::ModulePresentation(const PointVec<Real>& _generators, const RelVec& _relations) :
+ generators_(_generators),
+ relations_(_relations)
+ {
+ positions_ = concat_gen_and_rel_positions(generators_, relations_);
+ init_boundaries();
+ }
+
+ template<class Real>
+ void ModulePresentation<Real>::translate(Real a)
+ {
+ for(auto& g : generators_) {
+ g.translate(a);
+ }
+
+ for(auto& r : relations_) {
+ r.position_.translate(a);
+ }
+
+ positions_ = concat_gen_and_rel_positions(generators_, relations_);
+ init_boundaries();
+ }
+
+
+ /**
+ *
+ * @param slice line on which generators are projected
+ * @param sorted_indices [a_1,...,a_n] s.t. wpush(generator[a_1]) <= wpush(generator[a_2]) <= ..
+ * @param projections sorted weighted pushes of generators
+ */
+
+ template<class Real>
+ void ModulePresentation<Real>::project_generators(const DualPoint<Real>& slice,
+ IndexVec& sorted_indices, RealVec& projections) const
+ {
+ size_t num_gens = generators_.size();
+
+ RealVec gen_values;
+ gen_values.reserve(num_gens);
+ for(const auto& pos : generators_) {
+ gen_values.push_back(slice.weighted_push(pos));
+ }
+ sorted_indices = get_sorted_indices(gen_values);
+ projections.clear();
+ projections.reserve(num_gens);
+ for(auto i : sorted_indices) {
+ projections.push_back(gen_values[i]);
+ }
+ }
+
+ template<class Real>
+ void ModulePresentation<Real>::project_relations(const DualPoint<Real>& slice, IndexVec& sorted_rel_indices,
+ RealVec& projections) const
+ {
+
+ size_t num_rels = relations_.size();
+
+ RealVec rel_values;
+ rel_values.reserve(num_rels);
+ for(const auto& rel : relations_) {
+ rel_values.push_back(slice.weighted_push(rel.position_));
+ }
+
+ sorted_rel_indices = get_sorted_indices(rel_values);
+
+ projections.clear();
+ projections.reserve(num_rels);
+ for(auto i : sorted_rel_indices) {
+ projections.push_back(rel_values[i]);
+ }
+ }
+
+
+ template<class Real>
+ void ModulePresentation<Real>::get_slice_projection_matrix(const DualPoint<Real>& slice,
+ phat::boundary_matrix<>& phat_matrix,
+ RealVec& gen_projections, RealVec& rel_projections) const
+ {
+ IndexVec sorted_gen_indices, sorted_rel_indices;
+
+ project_generators(slice, sorted_gen_indices, gen_projections);
+ project_relations(slice, sorted_rel_indices, rel_projections);
+
+ phat_matrix.set_num_cols(relations_.size());
+
+ for(Index i = 0; i < (Index) relations_.size(); i++) {
+ IndexVec current_relation = relations_[sorted_rel_indices[i]].components_;
+ for(auto& j : current_relation) {
+ j = sorted_gen_indices[j];
+ }
+ std::sort(current_relation.begin(), current_relation.end());
+ // modules do not have dimension, set all to 0
+ phat_matrix.set_dim(i, 0);
+ phat_matrix.set_col(i, current_relation);
+ }
+ }
+
+
+ template<class Real>
+ Diagram<Real> ModulePresentation<Real>::weighted_slice_diagram(const DualPoint<Real>& slice) const
+ {
+ RealVec gen_projections, rel_projections;
+ phat::boundary_matrix<> phat_matrix;
+
+ get_slice_projection_matrix(slice, phat_matrix, gen_projections, rel_projections);
+
+ phat::persistence_pairs phat_persistence_pairs;
+ phat::compute_persistence_pairs<phat::twist_reduction>(phat_persistence_pairs, phat_matrix);
+
+ Diagram<Real> dgm;
+
+ constexpr Real real_inf = std::numeric_limits<Real>::infinity();
+
+ for(Index i = 0; i < (Index) phat_persistence_pairs.get_num_pairs(); i++) {
+ std::pair<phat::index, phat::index> new_pair = phat_persistence_pairs.get_pair(i);
+ bool is_finite_pair = new_pair.second != phat::k_infinity_index;
+ Real birth = gen_projections.at(new_pair.first);
+ Real death = is_finite_pair ? rel_projections.at(new_pair.second) : real_inf;
+ if (birth != death) {
+ dgm.emplace_back(birth, death);
+ }
+ }
+
+ return dgm;
+ }
+
+ template<class Real>
+ PointVec<Real> ModulePresentation<Real>::positions() const
+ {
+ return positions_;
+ }
+
+ template<class Real>
+ Box<Real> ModulePresentation<Real>::bounding_box() const
+ {
+ return bounding_box_;
+ }
+
+} // namespace md
diff --git a/matching/include/phat/algorithms/chunk_reduction.h b/matching/include/phat/algorithms/chunk_reduction.h
new file mode 100644
index 0000000..1797023
--- /dev/null
+++ b/matching/include/phat/algorithms/chunk_reduction.h
@@ -0,0 +1,223 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/boundary_matrix.h>
+
+namespace phat {
+ class chunk_reduction {
+ public:
+ enum column_type { GLOBAL
+ , LOCAL_POSITIVE
+ , LOCAL_NEGATIVE };
+
+ public:
+ template< typename Representation >
+ void operator() ( boundary_matrix< Representation >& boundary_matrix ) {
+
+
+ const index nr_columns = boundary_matrix.get_num_cols();
+ if( omp_get_max_threads( ) > nr_columns )
+ omp_set_num_threads( 1 );
+
+ const dimension max_dim = boundary_matrix.get_max_dim();
+
+ std::vector< index > lowest_one_lookup( nr_columns, -1 );
+ std::vector < column_type > column_type( nr_columns, GLOBAL );
+ std::vector< char > is_active( nr_columns, false );
+
+ const index chunk_size = omp_get_max_threads() == 1 ? (index)sqrt( (double)nr_columns ) : nr_columns / omp_get_max_threads();
+
+ std::vector< index > chunk_boundaries;
+ for( index cur_boundary = 0; cur_boundary < nr_columns; cur_boundary += chunk_size )
+ chunk_boundaries.push_back( cur_boundary );
+ chunk_boundaries.push_back( nr_columns );
+
+ for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) {
+ // Phase 1: Reduce chunks locally -- 1st pass
+ #pragma omp parallel for schedule( guided, 1 )
+ for( index chunk_id = 0; chunk_id < (index)chunk_boundaries.size() - 1; chunk_id++ )
+ _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, cur_dim,
+ chunk_boundaries[ chunk_id ], chunk_boundaries[ chunk_id + 1 ], chunk_boundaries[ chunk_id ] );
+ boundary_matrix.sync();
+
+ // Phase 1: Reduce chunks locally -- 2nd pass
+ #pragma omp parallel for schedule( guided, 1 )
+ for( index chunk_id = 1; chunk_id < (index)chunk_boundaries.size( ) - 1; chunk_id++ )
+ _local_chunk_reduction( boundary_matrix, lowest_one_lookup, column_type, cur_dim,
+ chunk_boundaries[ chunk_id ], chunk_boundaries[ chunk_id + 1 ], chunk_boundaries[ chunk_id - 1 ] );
+ boundary_matrix.sync( );
+ }
+
+ // get global columns
+ std::vector< index > global_columns;
+ for( index cur_col_idx = 0; cur_col_idx < nr_columns; cur_col_idx++ )
+ if( column_type[ cur_col_idx ] == GLOBAL )
+ global_columns.push_back( cur_col_idx );
+
+ // get active columns
+ #pragma omp parallel for
+ for( index idx = 0; idx < (index)global_columns.size(); idx++ )
+ is_active[ global_columns[ idx ] ] = true;
+ _get_active_columns( boundary_matrix, lowest_one_lookup, column_type, global_columns, is_active );
+
+ // Phase 2+3: Simplify columns and reduce them
+ for( dimension cur_dim = max_dim; cur_dim >= 1; cur_dim-- ) {
+ // Phase 2: Simplify columns
+ std::vector< index > temp_col;
+ #pragma omp parallel for schedule( guided, 1 ), private( temp_col )
+ for( index idx = 0; idx < (index)global_columns.size(); idx++ )
+ if( boundary_matrix.get_dim( global_columns[ idx ] ) == cur_dim )
+ _global_column_simplification( global_columns[ idx ], boundary_matrix, lowest_one_lookup, column_type, is_active, temp_col );
+ boundary_matrix.sync();
+
+ // Phase 3: Reduce columns
+ for( index idx = 0; idx < (index)global_columns.size(); idx++ ) {
+ index cur_col = global_columns[ idx ];
+ if( boundary_matrix.get_dim( cur_col ) == cur_dim && column_type[ cur_col ] == GLOBAL ) {
+ index lowest_one = boundary_matrix.get_max_index( cur_col );
+ while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) {
+ boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col );
+ lowest_one = boundary_matrix.get_max_index( cur_col );
+ }
+ if( lowest_one != -1 ) {
+ lowest_one_lookup[ lowest_one ] = cur_col;
+ boundary_matrix.clear( lowest_one );
+ }
+ boundary_matrix.finalize( cur_col );
+ }
+ }
+ }
+
+ boundary_matrix.sync();
+ }
+
+ protected:
+ template< typename Representation >
+ void _local_chunk_reduction( boundary_matrix< Representation >& boundary_matrix
+ , std::vector<index>& lowest_one_lookup
+ , std::vector< column_type >& column_type
+ , const dimension cur_dim
+ , const index chunk_begin
+ , const index chunk_end
+ , const index row_begin ) {
+
+ for( index cur_col = chunk_begin; cur_col < chunk_end; cur_col++ ) {
+ if( column_type[ cur_col ] == GLOBAL && boundary_matrix.get_dim( cur_col ) == cur_dim ) {
+ index lowest_one = boundary_matrix.get_max_index( cur_col );
+ while( lowest_one != -1 && lowest_one >= row_begin && lowest_one_lookup[ lowest_one ] != -1 ) {
+ boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col );
+ lowest_one = boundary_matrix.get_max_index( cur_col );
+ }
+ if( lowest_one >= row_begin ) {
+ lowest_one_lookup[ lowest_one ] = cur_col;
+ column_type[ cur_col ] = LOCAL_NEGATIVE;
+ column_type[ lowest_one ] = LOCAL_POSITIVE;
+ boundary_matrix.clear( lowest_one );
+ boundary_matrix.finalize( cur_col );
+ }
+ }
+ }
+ }
+
+ template< typename Representation >
+ void _get_active_columns( const boundary_matrix< Representation >& boundary_matrix
+ , const std::vector< index >& lowest_one_lookup
+ , const std::vector< column_type >& column_type
+ , const std::vector< index >& global_columns
+ , std::vector< char >& is_active ) {
+
+ const index nr_columns = boundary_matrix.get_num_cols();
+ std::vector< char > finished( nr_columns, false );
+
+ std::vector< std::pair < index, index > > stack;
+ std::vector< index > cur_col_values;
+ #pragma omp parallel for schedule( guided, 1 ), private( stack, cur_col_values )
+ for( index idx = 0; idx < (index)global_columns.size(); idx++ ) {
+ bool pop_next = false;
+ index start_col = global_columns[ idx ];
+ stack.push_back( std::pair< index, index >( start_col, -1 ) );
+ while( !stack.empty() ) {
+ index cur_col = stack.back().first;
+ index prev_col = stack.back().second;
+ if( pop_next ) {
+ stack.pop_back();
+ pop_next = false;
+ if( prev_col != -1 ) {
+ if( is_active[ cur_col ] ) {
+ is_active[ prev_col ] = true;
+ }
+ if( prev_col == stack.back().first ) {
+ finished[ prev_col ] = true;
+ pop_next = true;
+ }
+ }
+ } else {
+ pop_next = true;
+ boundary_matrix.get_col( cur_col, cur_col_values );
+ for( index idx = 0; idx < (index) cur_col_values.size(); idx++ ) {
+ index cur_row = cur_col_values[ idx ];
+ if( ( column_type[ cur_row ] == GLOBAL ) ) {
+ is_active[ cur_col ] = true;
+ } else if( column_type[ cur_row ] == LOCAL_POSITIVE ) {
+ index next_col = lowest_one_lookup[ cur_row ];
+ if( next_col != cur_col && !finished[ cur_col ] ) {
+ stack.push_back( std::make_pair( next_col, cur_col ) );
+ pop_next = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ template< typename Representation >
+ void _global_column_simplification( const index col_idx
+ , boundary_matrix< Representation >& boundary_matrix
+ , const std::vector< index >& lowest_one_lookup
+ , const std::vector< column_type >& column_type
+ , const std::vector< char >& is_active
+ , std::vector< index >& temp_col )
+ {
+ temp_col.clear();
+ while( !boundary_matrix.is_empty( col_idx ) ) {
+ index cur_row = boundary_matrix.get_max_index( col_idx );
+ switch( column_type[ cur_row ] ) {
+ case GLOBAL:
+ temp_col.push_back( cur_row );
+ boundary_matrix.remove_max( col_idx );
+ break;
+ case LOCAL_NEGATIVE:
+ boundary_matrix.remove_max( col_idx );
+ break;
+ case LOCAL_POSITIVE:
+ if( is_active[ lowest_one_lookup[ cur_row ] ] )
+ boundary_matrix.add_to( lowest_one_lookup[ cur_row ], col_idx );
+ else
+ boundary_matrix.remove_max( col_idx );
+ break;
+ }
+ }
+ std::reverse( temp_col.begin(), temp_col.end() );
+ boundary_matrix.set_col( col_idx, temp_col );
+ }
+ };
+}
diff --git a/matching/include/phat/algorithms/row_reduction.h b/matching/include/phat/algorithms/row_reduction.h
new file mode 100644
index 0000000..cdd1a8f
--- /dev/null
+++ b/matching/include/phat/algorithms/row_reduction.h
@@ -0,0 +1,56 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/boundary_matrix.h>
+
+namespace phat {
+ class row_reduction {
+ public:
+ template< typename Representation >
+ void operator() ( boundary_matrix< Representation >& boundary_matrix ) {
+
+ const index nr_columns = boundary_matrix.get_num_cols();
+ std::vector< std::vector< index > > lowest_one_lookup( nr_columns );
+
+ for( index cur_col = nr_columns - 1; cur_col >= 0; cur_col-- ) {
+ if( !boundary_matrix.is_empty( cur_col ) )
+ lowest_one_lookup[ boundary_matrix.get_max_index( cur_col ) ].push_back( cur_col );
+
+ if( !lowest_one_lookup[ cur_col ].empty() ) {
+ boundary_matrix.clear( cur_col );
+ boundary_matrix.finalize( cur_col );
+ std::vector< index >& cols_with_cur_lowest = lowest_one_lookup[ cur_col ];
+ index source = *min_element( cols_with_cur_lowest.begin(), cols_with_cur_lowest.end() );
+ for( index idx = 0; idx < (index)cols_with_cur_lowest.size(); idx++ ) {
+ index target = cols_with_cur_lowest[ idx ];
+ if( target != source && !boundary_matrix.is_empty( target ) ) {
+ boundary_matrix.add_to( source, target );
+ if( !boundary_matrix.is_empty( target ) ) {
+ index lowest_one_of_target = boundary_matrix.get_max_index( target );
+ lowest_one_lookup[ lowest_one_of_target ].push_back( target );
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+} \ No newline at end of file
diff --git a/matching/include/phat/algorithms/spectral_sequence_reduction.h b/matching/include/phat/algorithms/spectral_sequence_reduction.h
new file mode 100644
index 0000000..bf442e6
--- /dev/null
+++ b/matching/include/phat/algorithms/spectral_sequence_reduction.h
@@ -0,0 +1,80 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/boundary_matrix.h>
+
+namespace phat {
+ class spectral_sequence_reduction {
+ public:
+ template< typename Representation >
+ void operator () ( boundary_matrix< Representation >& boundary_matrix ) {
+
+ const index nr_columns = boundary_matrix.get_num_cols();
+ std::vector< index > lowest_one_lookup( nr_columns, -1 );
+
+ //const index num_stripes = (index) sqrt( (double)nr_columns );
+ const index num_stripes = omp_get_max_threads();
+
+ index block_size = ( nr_columns % num_stripes == 0 ) ? nr_columns / num_stripes : block_size = nr_columns / num_stripes + 1;
+
+ std::vector< std::vector< index > > unreduced_cols_cur_pass( num_stripes );
+ std::vector< std::vector< index > > unreduced_cols_next_pass( num_stripes );
+
+ for( index cur_dim = boundary_matrix.get_max_dim(); cur_dim >= 1 ; cur_dim-- ) {
+ #pragma omp parallel for schedule( guided, 1 )
+ for( index cur_stripe = 0; cur_stripe < num_stripes; cur_stripe++ ) {
+ index col_begin = cur_stripe * block_size;
+ index col_end = std::min( (cur_stripe+1) * block_size, nr_columns );
+ for( index cur_col = col_begin; cur_col < col_end; cur_col++ )
+ if( boundary_matrix.get_dim( cur_col ) == cur_dim && boundary_matrix.get_max_index( cur_col ) != -1 )
+ unreduced_cols_cur_pass[ cur_stripe ].push_back( cur_col );
+ }
+ for( index cur_pass = 0; cur_pass < num_stripes; cur_pass++ ) {
+ boundary_matrix.sync();
+ #pragma omp parallel for schedule( guided, 1 )
+ for( int cur_stripe = 0; cur_stripe < num_stripes; cur_stripe++ ) {
+ index row_begin = (cur_stripe - cur_pass) * block_size;
+ index row_end = row_begin + block_size;
+ unreduced_cols_next_pass[ cur_stripe ].clear();
+ for( index idx = 0; idx < (index)unreduced_cols_cur_pass[ cur_stripe ].size(); idx++ ) {
+ index cur_col = unreduced_cols_cur_pass[ cur_stripe ][ idx ];
+ index lowest_one = boundary_matrix.get_max_index( cur_col );
+ while( lowest_one != -1 && lowest_one >= row_begin && lowest_one < row_end && lowest_one_lookup[ lowest_one ] != -1 ) {
+ boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col );
+ lowest_one = boundary_matrix.get_max_index( cur_col );
+ }
+ if( lowest_one != -1 ) {
+ if( lowest_one >= row_begin && lowest_one < row_end ) {
+ lowest_one_lookup[ lowest_one ] = cur_col;
+ boundary_matrix.clear( lowest_one );
+ boundary_matrix.finalize( cur_col );
+ } else {
+ unreduced_cols_next_pass[ cur_stripe ].push_back( cur_col );
+ }
+ }
+ }
+ unreduced_cols_next_pass[ cur_stripe ].swap( unreduced_cols_cur_pass[ cur_stripe ] );
+ }
+ }
+ }
+ }
+ };
+}
diff --git a/matching/include/phat/algorithms/standard_reduction.h b/matching/include/phat/algorithms/standard_reduction.h
new file mode 100644
index 0000000..e490a5e
--- /dev/null
+++ b/matching/include/phat/algorithms/standard_reduction.h
@@ -0,0 +1,47 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/boundary_matrix.h>
+
+namespace phat {
+ class standard_reduction {
+ public:
+ template< typename Representation >
+ void operator() ( boundary_matrix< Representation >& boundary_matrix ) {
+
+ const index nr_columns = boundary_matrix.get_num_cols();
+ std::vector< index > lowest_one_lookup( nr_columns, -1 );
+
+ for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) {
+ index lowest_one = boundary_matrix.get_max_index( cur_col );
+ while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) {
+ boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col );
+ lowest_one = boundary_matrix.get_max_index( cur_col );
+ }
+ if( lowest_one != -1 ) {
+ lowest_one_lookup[ lowest_one ] = cur_col;
+ }
+ boundary_matrix.finalize( cur_col );
+ }
+ }
+ };
+}
+
diff --git a/matching/include/phat/algorithms/twist_reduction.h b/matching/include/phat/algorithms/twist_reduction.h
new file mode 100644
index 0000000..2357df0
--- /dev/null
+++ b/matching/include/phat/algorithms/twist_reduction.h
@@ -0,0 +1,51 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/boundary_matrix.h>
+
+namespace phat {
+ class twist_reduction {
+ public:
+ template< typename Representation >
+ void operator () ( boundary_matrix< Representation >& boundary_matrix ) {
+
+ const index nr_columns = boundary_matrix.get_num_cols();
+ std::vector< index > lowest_one_lookup( nr_columns, -1 );
+
+ for( index cur_dim = boundary_matrix.get_max_dim(); cur_dim >= 1 ; cur_dim-- ) {
+ for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) {
+ if( boundary_matrix.get_dim( cur_col ) == cur_dim ) {
+ index lowest_one = boundary_matrix.get_max_index( cur_col );
+ while( lowest_one != -1 && lowest_one_lookup[ lowest_one ] != -1 ) {
+ boundary_matrix.add_to( lowest_one_lookup[ lowest_one ], cur_col );
+ lowest_one = boundary_matrix.get_max_index( cur_col );
+ }
+ if( lowest_one != -1 ) {
+ lowest_one_lookup[ lowest_one ] = cur_col;
+ boundary_matrix.clear( lowest_one );
+ }
+ boundary_matrix.finalize( cur_col );
+ }
+ }
+ }
+ }
+ };
+}
diff --git a/matching/include/phat/boundary_matrix.h b/matching/include/phat/boundary_matrix.h
new file mode 100644
index 0000000..10c66cc
--- /dev/null
+++ b/matching/include/phat/boundary_matrix.h
@@ -0,0 +1,343 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/representations/bit_tree_pivot_column.h>
+
+// interface class for the main data structure -- implementations of the interface can be found in ./representations
+namespace phat {
+ template< class Representation = bit_tree_pivot_column >
+ class boundary_matrix
+ {
+
+ protected:
+ Representation rep;
+
+ // interface functions -- actual implementation and complexity depends on chosen @Representation template
+ public:
+ // get overall number of columns in boundary_matrix
+ index get_num_cols() const { return rep._get_num_cols(); }
+
+ // set overall number of columns in boundary_matrix
+ void set_num_cols( index nr_of_columns ) { rep._set_num_cols( nr_of_columns ); }
+
+ // get dimension of given index
+ dimension get_dim( index idx ) const { return rep._get_dim( idx ); }
+
+ // set dimension of given index
+ void set_dim( index idx, dimension dim ) { rep._set_dim( idx, dim ); }
+
+ // replaces content of @col with boundary of given index
+ void get_col( index idx, column& col ) const { col.clear(); rep._get_col( idx, col ); }
+
+ // set column @idx to the values contained in @col
+ void set_col( index idx, const column& col ) { rep._set_col( idx, col ); }
+
+ // true iff boundary of given column is empty
+ bool is_empty( index idx ) const { return rep._is_empty( idx ); }
+
+ // largest index of given column (new name for lowestOne()) -- NOT thread-safe
+ index get_max_index( index idx ) const { return rep._get_max_index( idx ); }
+
+ // removes maximal index from given column
+ void remove_max( index idx ) { rep._remove_max( idx ); }
+
+ // adds column @source to column @target'
+ void add_to( index source, index target ) { rep._add_to( source, target ); }
+
+ // clears given column
+ void clear( index idx ) { rep._clear( idx ); }
+
+ // finalizes given column
+ void finalize( index idx ) { rep._finalize( idx ); }
+
+ // syncronizes all internal data structures -- has to be called before and after any multithreaded access!
+ void sync() { rep._sync(); }
+
+ // info functions -- independent of chosen 'Representation'
+ public:
+ // maximal dimension
+ dimension get_max_dim() const {
+ dimension cur_max_dim = 0;
+ for( index idx = 0; idx < get_num_cols(); idx++ )
+ cur_max_dim = get_dim( idx ) > cur_max_dim ? get_dim( idx ) : cur_max_dim;
+ return cur_max_dim;
+ }
+
+ // number of nonzero rows for given column @idx
+ index get_num_rows( index idx ) const {
+ column cur_col;
+ get_col( idx, cur_col );
+ return cur_col.size();
+ }
+
+ // maximal number of nonzero rows of all columns
+ index get_max_col_entries() const {
+ index max_col_entries = -1;
+ const index nr_of_columns = get_num_cols();
+ for( index idx = 0; idx < nr_of_columns; idx++ )
+ max_col_entries = get_num_rows( idx ) > max_col_entries ? get_num_rows( idx ) : max_col_entries;
+ return max_col_entries;
+ }
+
+ // maximal number of nonzero cols of all rows
+ index get_max_row_entries() const {
+ size_t max_row_entries = 0;
+ const index nr_of_columns = get_num_cols();
+ std::vector< std::vector< index > > transposed_matrix( nr_of_columns );
+ column temp_col;
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) {
+ get_col( cur_col, temp_col );
+ for( index idx = 0; idx < (index)temp_col.size(); idx++)
+ transposed_matrix[ temp_col[ idx ] ].push_back( cur_col );
+ }
+ for( index idx = 0; idx < nr_of_columns; idx++ )
+ max_row_entries = transposed_matrix[ idx ].size() > max_row_entries ? transposed_matrix[ idx ].size() : max_row_entries;
+ return max_row_entries;
+ }
+
+ // overall number of entries in the matrix
+ index get_num_entries() const {
+ index number_of_nonzero_entries = 0;
+ const index nr_of_columns = get_num_cols();
+ for( index idx = 0; idx < nr_of_columns; idx++ )
+ number_of_nonzero_entries += get_num_rows( idx );
+ return number_of_nonzero_entries;
+ }
+
+ // operators / constructors
+ public:
+ boundary_matrix() {};
+
+ template< class OtherRepresentation >
+ boundary_matrix( const boundary_matrix< OtherRepresentation >& other ) {
+ *this = other;
+ }
+
+ template< typename OtherRepresentation >
+ bool operator==( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const {
+ const index number_of_columns = this->get_num_cols();
+
+ if( number_of_columns != other_boundary_matrix.get_num_cols() )
+ return false;
+
+ column temp_col;
+ column other_temp_col;
+ for( index idx = 0; idx < number_of_columns; idx++ ) {
+ this->get_col( idx, temp_col );
+ other_boundary_matrix.get_col( idx, other_temp_col );
+ if( temp_col != other_temp_col || this->get_dim( idx ) != other_boundary_matrix.get_dim( idx ) )
+ return false;
+ }
+ return true;
+ }
+
+ template< typename OtherRepresentation >
+ bool operator!=( const boundary_matrix< OtherRepresentation >& other_boundary_matrix ) const {
+ return !( *this == other_boundary_matrix );
+ }
+
+ template< typename OtherRepresentation >
+ boundary_matrix< Representation >& operator=( const boundary_matrix< OtherRepresentation >& other )
+ {
+ const index nr_of_columns = other.get_num_cols();
+ this->set_num_cols( nr_of_columns );
+ column temp_col;
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) {
+ this->set_dim( cur_col, other.get_dim( cur_col ) );
+ other.get_col( cur_col, temp_col );
+ this->set_col( cur_col, temp_col );
+ }
+
+ // by convention, always return *this
+ return *this;
+ }
+
+ // I/O -- independent of chosen 'Representation'
+ public:
+
+ // initializes boundary_matrix from (vector<vector>, vector) pair -- untested
+ template< typename index_type, typename dimemsion_type >
+ void load_vector_vector( const std::vector< std::vector< index_type > >& input_matrix, const std::vector< dimemsion_type >& input_dims ) {
+ const index nr_of_columns = (index)input_matrix.size();
+ this->set_num_cols( nr_of_columns );
+ column temp_col;
+ #pragma omp parallel for private( temp_col )
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) {
+ this->set_dim( cur_col, (dimension)input_dims[ cur_col ] );
+
+ index num_rows = input_matrix[ cur_col ].size();
+ temp_col.resize( num_rows );
+ for( index cur_row = 0; cur_row < num_rows; cur_row++ )
+ temp_col[ cur_row ] = (index)input_matrix[ cur_col ][ cur_row ];
+ this->set_col( cur_col, temp_col );
+ }
+ }
+
+ template< typename index_type, typename dimemsion_type >
+ void save_vector_vector( std::vector< std::vector< index_type > >& output_matrix, std::vector< dimemsion_type >& output_dims ) {
+ const index nr_of_columns = get_num_cols();
+ output_matrix.resize( nr_of_columns );
+ output_dims.resize( nr_of_columns );
+ column temp_col;
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) {
+ output_dims[ cur_col ] = (dimemsion_type)get_dim( cur_col );
+ get_col( cur_col, temp_col );
+ index num_rows = temp_col.size();
+ output_matrix[ cur_col ].clear();
+ output_matrix[ cur_col ].resize( num_rows );
+ for( index cur_row = 0; cur_row < num_rows; cur_row++ )
+ output_matrix[ cur_col ][ cur_row ] = (index_type)temp_col[ cur_row ];
+ }
+ }
+
+
+ // Loads the boundary_matrix from given file in ascii format
+ // Format: each line represents a column, first number is dimension, other numbers are the content of the column.
+ // Ignores empty lines and lines starting with a '#'.
+ bool load_ascii( std::string filename ) {
+ // first count number of columns:
+ std::string cur_line;
+ std::ifstream dummy( filename .c_str() );
+ if( dummy.fail() )
+ return false;
+
+ index number_of_columns = 0;
+ while( getline( dummy, cur_line ) ) {
+ cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1);
+ if( cur_line != "" && cur_line[ 0 ] != '#' )
+ number_of_columns++;
+
+ }
+ this->set_num_cols( number_of_columns );
+ dummy.close();
+
+ std::ifstream input_stream( filename.c_str() );
+ if( input_stream.fail() )
+ return false;
+
+ column temp_col;
+ index cur_col = -1;
+ while( getline( input_stream, cur_line ) ) {
+ cur_line.erase(cur_line.find_last_not_of(" \t\n\r\f\v") + 1);
+ if( cur_line != "" && cur_line[ 0 ] != '#' ) {
+ cur_col++;
+ std::stringstream ss( cur_line );
+
+ int64_t temp_dim;
+ ss >> temp_dim;
+ this->set_dim( cur_col, (dimension) temp_dim );
+
+ int64_t temp_index;
+ temp_col.clear();
+ while( ss.good() ) {
+ ss >> temp_index;
+ temp_col.push_back( (index)temp_index );
+ }
+ std::sort( temp_col.begin(), temp_col.end() );
+ this->set_col( cur_col, temp_col );
+ }
+ }
+
+ input_stream.close();
+ return true;
+ }
+
+ // Saves the boundary_matrix to given file in ascii format
+ // Format: each line represents a column, first number is dimension, other numbers are the content of the column
+ bool save_ascii( std::string filename ) {
+ std::ofstream output_stream( filename.c_str() );
+ if( output_stream.fail() )
+ return false;
+
+ const index nr_columns = this->get_num_cols();
+ column tempCol;
+ for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) {
+ output_stream << (int64_t)this->get_dim( cur_col );
+ this->get_col( cur_col, tempCol );
+ for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size(); cur_row_idx++ )
+ output_stream << " " << tempCol[ cur_row_idx ];
+ output_stream << std::endl;
+ }
+
+ output_stream.close();
+ return true;
+ }
+
+ // Loads boundary_matrix from given file
+ // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ...
+ bool load_binary( std::string filename )
+ {
+ std::ifstream input_stream( filename.c_str( ), std::ios_base::binary | std::ios_base::in );
+ if( input_stream.fail( ) )
+ return false;
+
+ int64_t nr_columns;
+ input_stream.read( (char*)&nr_columns, sizeof( int64_t ) );
+ this->set_num_cols( (index)nr_columns );
+
+ column temp_col;
+ for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) {
+ int64_t cur_dim;
+ input_stream.read( (char*)&cur_dim, sizeof( int64_t ) );
+ this->set_dim( cur_col, (dimension)cur_dim );
+ int64_t nr_rows;
+ input_stream.read( (char*)&nr_rows, sizeof( int64_t ) );
+ temp_col.resize( ( std::size_t )nr_rows );
+ for( index idx = 0; idx < nr_rows; idx++ ) {
+ int64_t cur_row;
+ input_stream.read( (char*)&cur_row, sizeof( int64_t ) );
+ temp_col[ idx ] = (index)cur_row;
+ }
+ this->set_col( cur_col, temp_col );
+ }
+
+ input_stream.close( );
+ return true;
+ }
+
+ // Saves the boundary_matrix to given file in binary format
+ // Format: nr_columns % dim1 % N1 % row1 row2 % ...% rowN1 % dim2 % N2 % ...
+ bool save_binary( std::string filename )
+ {
+ std::ofstream output_stream( filename.c_str( ), std::ios_base::binary | std::ios_base::out );
+ if( output_stream.fail( ) )
+ return false;
+
+ const int64_t nr_columns = this->get_num_cols( );
+ output_stream.write( (char*)&nr_columns, sizeof( int64_t ) );
+ column tempCol;
+ for( index cur_col = 0; cur_col < nr_columns; cur_col++ ) {
+ int64_t cur_dim = this->get_dim( cur_col );
+ output_stream.write( (char*)&cur_dim, sizeof( int64_t ) );
+ this->get_col( cur_col, tempCol );
+ int64_t cur_nr_rows = tempCol.size( );
+ output_stream.write( (char*)&cur_nr_rows, sizeof( int64_t ) );
+ for( index cur_row_idx = 0; cur_row_idx < (index)tempCol.size( ); cur_row_idx++ ) {
+ int64_t cur_row = tempCol[ cur_row_idx ];
+ output_stream.write( (char*)&cur_row, sizeof( int64_t ) );
+ }
+ }
+
+ output_stream.close( );
+ return true;
+ }
+ };
+}
diff --git a/matching/include/phat/compute_persistence_pairs.h b/matching/include/phat/compute_persistence_pairs.h
new file mode 100644
index 0000000..06f5372
--- /dev/null
+++ b/matching/include/phat/compute_persistence_pairs.h
@@ -0,0 +1,137 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/persistence_pairs.h>
+#include <phat/boundary_matrix.h>
+#include <phat/helpers/dualize.h>
+#include <phat/algorithms/twist_reduction.h>
+
+namespace phat {
+ // Extracts persistence pairs in separate dimensions from a reduced
+ // boundary matrix representing ``double`` filtration. The pairs
+ // give persistent relative homology of the pair of filtrations.
+ // TODO: Use it with standard reduction algorithm (no template option).
+ template< typename ReductionAlgorithm, typename Representation >
+ void compute_relative_persistence_pairs(std::vector<persistence_pairs>& pairs, boundary_matrix<Representation>& boundary_matrix, const std::map<int, int>& L) {
+ ReductionAlgorithm reduce;
+ reduce(boundary_matrix);
+ std::map<int, bool> free;
+ std::map<int, int> invL;
+ for (std::map<int, int>::const_iterator it = L.begin(); it != L.end(); ++it) { invL[it->second] = it->first; }
+ for (std::vector<persistence_pairs>::iterator it = pairs.begin(); it != pairs.end(); ++it) { it->clear(); }
+ for (index idx = 0; idx < boundary_matrix.get_num_cols(); ++idx) {
+ int dimension = boundary_matrix.get_dim(idx);
+ if (L.find(idx) != L.end()) { ++dimension; }
+ free[idx] = true;
+ if (!boundary_matrix.is_empty(idx)) {
+ index birth = boundary_matrix.get_max_index(idx);
+ index death = idx;
+ pairs[dimension-1].append_pair(birth, death);
+ free[birth] = false;
+ free[death] = false;
+ } else {
+ // This is an L-simplex and a (dimension+1)-dimensional cycle
+ if (L.find(idx) != L.end()) {
+ assert(dimension < pairs.size());
+ pairs[dimension].append_pair(idx, -1);
+ }
+ }
+ }
+ for (std::map<int, bool>::iterator it = free.begin(); it != free.end(); ++it) {
+ if (it->second) {
+ int dimension = boundary_matrix.get_dim(it->first);
+ if (invL.find(it->first) == invL.end() && L.find(it->first) == L.end()) {
+ assert(dimension < pairs.size());
+ pairs[dimension].append_pair(it->first, -1);
+ }
+ }
+ }
+ }
+
+ // Extracts persistence pairs in separate dimensions; expects a d-dimensional vector of persistent_pairs
+ template< typename ReductionAlgorithm, typename Representation >
+ void compute_persistence_pairs(std::vector<persistence_pairs>& pairs, boundary_matrix<Representation>& boundary_matrix) {
+ ReductionAlgorithm reduce;
+ reduce(boundary_matrix);
+ std::map<int, bool> free;
+ for (std::vector<persistence_pairs>::iterator it = pairs.begin(); it != pairs.end(); ++it) { it->clear(); }
+ for (index idx = 0; idx < boundary_matrix.get_num_cols(); ++idx) {
+ int dimension = boundary_matrix.get_dim(idx);
+ free[idx] = true;
+ if (!boundary_matrix.is_empty(idx)) {
+ index birth = boundary_matrix.get_max_index(idx);
+ index death = idx;
+ pairs[dimension-1].append_pair(birth, death);
+ // Cannot be of the form (a, infinity)
+ free[birth] = false;
+ free[death] = false;
+ }
+ }
+ for (std::map<int, bool>::iterator it = free.begin(); it != free.end(); ++it) {
+ if (it->second) {
+ int dimension = boundary_matrix.get_dim(it->first);
+ pairs[dimension].append_pair(it->first, -1);
+ }
+ }
+ }
+
+ template< typename ReductionAlgorithm, typename Representation >
+ void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) {
+ ReductionAlgorithm reduce;
+ reduce( boundary_matrix );
+ pairs.clear();
+ std::set<index> max_indices;
+ // finite pairs
+ for( index idx = 0; idx < boundary_matrix.get_num_cols(); idx++ ) {
+ if( !boundary_matrix.is_empty( idx ) ) {
+ index birth = boundary_matrix.get_max_index( idx );
+ max_indices.insert(birth);
+ index death = idx;
+ pairs.append_pair( birth, death );
+ }
+ }
+ // infinite pairs: column idx is 0, and row idx does not contain a lowest one
+ for( index idx = 0; idx < boundary_matrix.get_num_cols(); idx++ ) {
+ if(boundary_matrix.is_empty(idx) && max_indices.count(idx) == 0 ) {
+ pairs.append_pair( idx, k_infinity_index);
+ }
+ }
+ }
+
+ template< typename ReductionAlgorithm, typename Representation >
+ void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) {
+
+ dualize( boundary_matrix );
+ compute_persistence_pairs< ReductionAlgorithm >( pairs, boundary_matrix );
+ dualize_persistence_pairs( pairs, boundary_matrix.get_num_cols() );
+ }
+
+ template< typename Representation >
+ void compute_persistence_pairs( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) {
+ phat::compute_persistence_pairs< twist_reduction >( pairs, boundary_matrix );
+ }
+
+
+ template< typename Representation >
+ void compute_persistence_pairs_dualized( persistence_pairs& pairs, boundary_matrix< Representation >& boundary_matrix ) {
+ compute_persistence_pairs_dualized< twist_reduction >( pairs, boundary_matrix );
+ }
+
+}
diff --git a/matching/include/phat/helpers/dualize.h b/matching/include/phat/helpers/dualize.h
new file mode 100644
index 0000000..5731408
--- /dev/null
+++ b/matching/include/phat/helpers/dualize.h
@@ -0,0 +1,74 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/boundary_matrix.h>
+#include <phat/persistence_pairs.h>
+
+
+namespace phat {
+ template< typename Representation >
+ void dualize( boundary_matrix< Representation >& boundary_matrix ) {
+
+ std::vector< dimension > dual_dims;
+ std::vector< std::vector< index > > dual_matrix;
+
+ index nr_of_columns = boundary_matrix.get_num_cols();
+ dual_matrix.resize( nr_of_columns );
+ dual_dims.resize( nr_of_columns );
+
+ std::vector< index > dual_sizes( nr_of_columns, 0 );
+
+ column temp_col;
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) {
+ boundary_matrix.get_col( cur_col, temp_col );
+ for( index idx = 0; idx < (index)temp_col.size(); idx++)
+ dual_sizes[ nr_of_columns - 1 - temp_col[ idx ] ]++;
+ }
+
+ #pragma omp parallel for
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ )
+ dual_matrix[cur_col].reserve(dual_sizes[cur_col]);
+
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ ) {
+ boundary_matrix.get_col( cur_col, temp_col );
+ for( index idx = 0; idx < (index)temp_col.size(); idx++)
+ dual_matrix[ nr_of_columns - 1 - temp_col[ idx ] ].push_back( nr_of_columns - 1 - cur_col );
+ }
+
+ const dimension max_dim = boundary_matrix.get_max_dim();
+ #pragma omp parallel for
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ )
+ dual_dims[ nr_of_columns - 1 - cur_col ] = max_dim - boundary_matrix.get_dim( cur_col );
+
+ #pragma omp parallel for
+ for( index cur_col = 0; cur_col < nr_of_columns; cur_col++ )
+ std::reverse( dual_matrix[ cur_col ].begin(), dual_matrix[ cur_col ].end() );
+
+ boundary_matrix.load_vector_vector( dual_matrix, dual_dims );
+ }
+
+ inline void dualize_persistence_pairs( persistence_pairs& pairs, const index n ) {
+ for (index i = 0; i < pairs.get_num_pairs(); ++i) {
+ std::pair< index, index > pair = pairs.get_pair( i );
+ pairs.set_pair( i , n - 1 - pair.second, n - 1 - pair.first);
+ }
+ }
+}
diff --git a/matching/include/phat/helpers/misc.h b/matching/include/phat/helpers/misc.h
new file mode 100644
index 0000000..5a5c682
--- /dev/null
+++ b/matching/include/phat/helpers/misc.h
@@ -0,0 +1,78 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+// STL includes
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <set>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <queue>
+#include <cassert>
+#include <sstream>
+#include <algorithm>
+#include <iomanip>
+#include <cmath>
+#include <cstdlib>
+#include <iterator>
+#include <limits>
+
+// VS2008 and below unfortunately do not support stdint.h
+#if defined(_MSC_VER)&& _MSC_VER < 1600
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+ typedef __int32 int32_t;
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+#else
+ #include <stdint.h>
+#endif
+
+// basic types. index can be changed to int32_t to save memory on small instances
+namespace phat {
+ typedef int64_t index;
+ typedef int8_t dimension;
+ typedef std::vector< index > column;
+
+ constexpr index k_infinity_index = std::numeric_limits<index>::max();
+}
+
+// OpenMP (proxy) functions
+#if defined _OPENMP
+ #include <omp.h>
+#else
+ #define omp_get_thread_num() 0
+ #define omp_get_max_threads() 1
+ #define omp_get_num_threads() 1
+ inline void omp_set_num_threads( int ) {};
+ #include <time.h>
+ #define omp_get_wtime() (float)clock() / (float)CLOCKS_PER_SEC
+#endif
+
+#include <phat/helpers/thread_local_storage.h>
+
+
+
diff --git a/matching/include/phat/helpers/thread_local_storage.h b/matching/include/phat/helpers/thread_local_storage.h
new file mode 100644
index 0000000..d0b5332
--- /dev/null
+++ b/matching/include/phat/helpers/thread_local_storage.h
@@ -0,0 +1,52 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+
+// should ideally be equal to the cache line size of the CPU
+#define PHAT_TLS_SPACING_FACTOR 64
+
+// ThreadLocalStorage with some spacing to avoid "false sharing" (see wikipedia)
+template< typename T >
+class thread_local_storage
+{
+public:
+
+ thread_local_storage() : per_thread_storage( omp_get_max_threads() * PHAT_TLS_SPACING_FACTOR ) {};
+
+ T& operator()() {
+ return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ];
+ }
+
+ const T& operator()() const {
+ return per_thread_storage[ omp_get_thread_num() * PHAT_TLS_SPACING_FACTOR ];
+ }
+
+ T& operator[]( int tid ) {
+ return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ];
+ }
+
+ const T& operator[]( int tid ) const {
+ return per_thread_storage[ tid * PHAT_TLS_SPACING_FACTOR ];
+ }
+
+protected:
+ std::vector< T > per_thread_storage;
+};
diff --git a/matching/include/phat/persistence_pairs.h b/matching/include/phat/persistence_pairs.h
new file mode 100644
index 0000000..eafc638
--- /dev/null
+++ b/matching/include/phat/persistence_pairs.h
@@ -0,0 +1,155 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+
+namespace phat {
+ class persistence_pairs {
+
+ protected:
+ std::vector< std::pair< index, index > > pairs;
+
+ public:
+ index get_num_pairs() const {
+ return (index)pairs.size();
+ }
+
+ void append_pair( index birth, index death ) {
+ pairs.push_back( std::make_pair( birth, death ) );
+ }
+
+ std::pair< index, index > get_pair( index idx ) const {
+ return pairs[ idx ];
+ }
+
+ void set_pair( index idx, index birth, index death ) {
+ pairs[ idx ] = std::make_pair( birth, death );
+ }
+
+ void clear() {
+ pairs.clear();
+ }
+
+ void sort() {
+ std::sort( pairs.begin(), pairs.end() );
+ }
+
+ // Loads the persistence pairs from given file in asci format
+ // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ...
+ bool load_ascii( std::string filename ) {
+ std::ifstream input_stream( filename.c_str() );
+ if( input_stream.fail() )
+ return false;
+
+ int64_t nr_pairs;
+ input_stream >> nr_pairs;
+ pairs.clear();
+ for( index idx = 0; idx < nr_pairs; idx++ ) {
+ int64_t birth;
+ input_stream >> birth;
+ int64_t death;
+ input_stream >> death;
+ append_pair( (index)birth, (index)death );
+ }
+
+ input_stream.close();
+ return true;
+ }
+
+ // Saves the persistence pairs to given file in binary format
+ // Format: nr_pairs % newline % birth1 % death1 % newline % birth2 % death2 % newline ...
+ bool save_ascii( std::string filename ) {
+ std::ofstream output_stream( filename.c_str() );
+ if( output_stream.fail() )
+ return false;
+
+ this->sort();
+ output_stream << get_num_pairs() << std::endl;
+ for( std::size_t idx = 0; idx < pairs.size(); idx++ ) {
+ output_stream << pairs[idx].first << " " << pairs[idx].second << std::endl;
+ }
+
+ output_stream.close();
+ return true;
+ }
+
+ // Loads the persistence pairs from given file in binary format
+ // Format: nr_pairs % birth1 % death1 % birth2 % death2 ...
+ bool load_binary( std::string filename ) {
+ std::ifstream input_stream( filename.c_str(), std::ios_base::binary | std::ios_base::in );
+ if( input_stream.fail() )
+ return false;
+
+ int64_t nr_pairs;
+ input_stream.read( (char*)&nr_pairs, sizeof( int64_t ) );
+ for( index idx = 0; idx < nr_pairs; idx++ ) {
+ int64_t birth;
+ input_stream.read( (char*)&birth, sizeof( int64_t ) );
+ int64_t death;
+ input_stream.read( (char*)&death, sizeof( int64_t ) );
+ append_pair( (index)birth, (index)death );
+ }
+
+ input_stream.close();
+ return true;
+ }
+
+ // Saves the persistence pairs to given file in binary format
+ // Format: nr_pairs % birth1 % death1 % birth2 % death2 ...
+ bool save_binary( std::string filename ) {
+ std::ofstream output_stream( filename.c_str(), std::ios_base::binary | std::ios_base::out );
+ if( output_stream.fail() )
+ return false;
+
+ this->sort();
+ int64_t nr_pairs = get_num_pairs();
+ output_stream.write( (char*)&nr_pairs, sizeof( int64_t ) );
+ for( std::size_t idx = 0; idx < pairs.size(); idx++ ) {
+ int64_t birth = pairs[ idx ].first;
+ output_stream.write( (char*)&birth, sizeof( int64_t ) );
+ int64_t death = pairs[ idx ].second;
+ output_stream.write( (char*)&death, sizeof( int64_t ) );
+ }
+
+ output_stream.close();
+ return true;
+ }
+
+ bool operator==( persistence_pairs& other_pairs ) {
+ this->sort();
+ other_pairs.sort();
+ if( pairs.size() != (std::size_t)other_pairs.get_num_pairs() )
+ return false;
+
+ for( index idx = 0; idx < (index)pairs.size(); idx++ )
+ if( get_pair( idx ) != other_pairs.get_pair( idx ) )
+ return false;
+
+ return true;
+ }
+
+ bool operator!=( persistence_pairs& other_pairs ) {
+ return !( *this == other_pairs );
+ }
+ };
+
+
+
+}
diff --git a/matching/include/phat/representations/abstract_pivot_column.h b/matching/include/phat/representations/abstract_pivot_column.h
new file mode 100644
index 0000000..e16d7a5
--- /dev/null
+++ b/matching/include/phat/representations/abstract_pivot_column.h
@@ -0,0 +1,102 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/representations/vector_vector.h>
+
+namespace phat {
+
+ // Note: We could even make the rep generic in the underlying Const representation
+ // But I cannot imagine that anything else than vector<vector<index>> would
+ // make sense
+ template< typename PivotColumn >
+ class abstract_pivot_column : public vector_vector {
+
+ protected:
+ typedef vector_vector Base;
+ typedef PivotColumn pivot_col;
+
+ // For parallization purposes, it could be more than one full column
+ mutable thread_local_storage< pivot_col > pivot_cols;
+ mutable thread_local_storage< index > idx_of_pivot_cols;
+
+ pivot_col& get_pivot_col() const {
+ return pivot_cols();
+ }
+
+ bool is_pivot_col( index idx ) const {
+ return idx_of_pivot_cols() == idx;
+ }
+
+ void release_pivot_col() {
+ index idx = idx_of_pivot_cols();
+ if( idx != -1 ) {
+ this->matrix[ idx ].clear();
+ pivot_cols().get_col_and_clear( this->matrix[ idx ] );
+ }
+ idx_of_pivot_cols() = -1;
+ }
+
+ void make_pivot_col( index idx ) {
+ release_pivot_col();
+ idx_of_pivot_cols() = idx;
+ get_pivot_col().add_col( matrix[ idx ] );
+ }
+
+ public:
+
+ void _set_num_cols( index nr_of_cols ) {
+ #pragma omp parallel for
+ for( int tid = 0; tid < omp_get_num_threads(); tid++ ) {
+ pivot_cols[ tid ].init( nr_of_cols );
+ idx_of_pivot_cols[ tid ] = -1;
+ }
+ Base::_set_num_cols( nr_of_cols );
+ }
+
+ void _add_to( index source, index target ) {
+ if( !is_pivot_col( target ) )
+ make_pivot_col( target );
+ get_pivot_col().add_col( matrix[source] );
+ }
+
+ void _sync() {
+ #pragma omp parallel for
+ for( int tid = 0; tid < omp_get_num_threads(); tid++ )
+ release_pivot_col();
+ }
+
+ void _get_col( index idx, column& col ) const { is_pivot_col( idx ) ? get_pivot_col().get_col( col ) : Base::_get_col( idx, col ); }
+
+ bool _is_empty( index idx ) const { return is_pivot_col( idx ) ? get_pivot_col().is_empty() : Base::_is_empty( idx ); }
+
+ index _get_max_index( index idx ) const { return is_pivot_col( idx ) ? get_pivot_col().get_max_index() : Base::_get_max_index( idx ); }
+
+ void _clear( index idx ) { is_pivot_col( idx ) ? get_pivot_col().clear() : Base::_clear( idx ); }
+
+ void _set_col( index idx, const column& col ) { is_pivot_col( idx ) ? get_pivot_col().set_col( col ) : Base::_set_col( idx, col ); }
+
+ void _remove_max( index idx ) { is_pivot_col( idx ) ? get_pivot_col().remove_max() : Base::_remove_max( idx ); }
+
+ void finalize( index idx ) { Base::_finalize( idx ); }
+ };
+}
+
+
diff --git a/matching/include/phat/representations/bit_tree_pivot_column.h b/matching/include/phat/representations/bit_tree_pivot_column.h
new file mode 100644
index 0000000..4d48e88
--- /dev/null
+++ b/matching/include/phat/representations/bit_tree_pivot_column.h
@@ -0,0 +1,165 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Hubert Wagner
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/representations/abstract_pivot_column.h>
+
+namespace phat {
+
+ // This is a bitset indexed with a 64-ary tree. Each node in the index
+ // has 64 bits; i-th bit says that the i-th subtree is non-empty.
+ // Supports practically O(1), inplace, zero-allocation: insert, remove, max_element
+ // and clear in O(number of ones in the bitset).
+ // 'add_index' is still the real bottleneck in practice.
+ class bit_tree_column
+ {
+ protected:
+
+ size_t offset; // data[i + offset] = ith block of the data-bitset
+ typedef uint64_t block_type;
+ std::vector< block_type > data;
+
+
+ size_t debrujin_magic_table[ 64 ];
+
+ enum { block_size_in_bits = 64 };
+ enum { block_shift = 6 };
+
+ // Some magic: http://graphics.stanford.edu/~seander/bithacks.html
+ // Gets the position of the rightmost bit of 'x'. 0 means the most significant bit.
+ // (-x)&x isolates the rightmost bit.
+ // The whole method is much faster than calling log2i, and very comparable to using ScanBitForward/Reverse intrinsic,
+ // which should be one CPU instruction, but is not portable.
+ size_t rightmost_pos( const block_type value ) const {
+ return 64 - 1 - debrujin_magic_table[ ( (value & (-(int64_t)value) ) * 0x07EDD5E59A4E28C2 ) >> 58 ];
+ }
+
+ public:
+
+ void init( index num_cols ) {
+ int64_t n = 1; // in case of overflow
+ int64_t bottom_blocks_needed = ( num_cols + block_size_in_bits - 1 ) / block_size_in_bits;
+ int64_t upper_blocks = 1;
+
+ // How many blocks/nodes of index needed to index the whole bitset?
+ while( n * block_size_in_bits < bottom_blocks_needed ) {
+ n *= block_size_in_bits;
+ upper_blocks += n;
+ }
+
+ offset = upper_blocks;
+ data.resize( upper_blocks + bottom_blocks_needed, 0 );
+
+ std::size_t temp_array[ 64 ] = {
+ 63, 0, 58, 1, 59, 47, 53, 2,
+ 60, 39, 48, 27, 54, 33, 42, 3,
+ 61, 51, 37, 40, 49, 18, 28, 20,
+ 55, 30, 34, 11, 43, 14, 22, 4,
+ 62, 57, 46, 52, 38, 26, 32, 41,
+ 50, 36, 17, 19, 29, 10, 13, 21,
+ 56, 45, 25, 31, 35, 16, 9, 12,
+ 44, 24, 15, 8, 23, 7, 6, 5 };
+
+ std::copy( &temp_array[ 0 ], &temp_array[ 64 ], &debrujin_magic_table[ 0 ] );
+ }
+
+ index get_max_index() const {
+ if( !data[ 0 ] )
+ return -1;
+
+ size_t n = 0;
+ size_t newn = 0;
+ size_t index = 0;
+ while( newn < data.size() ) {
+ n = newn;
+ index = rightmost_pos( data[ n ] );
+ newn = ( n << block_shift ) + index + 1;
+ }
+
+ return ( ( n - offset ) << block_shift ) + index;
+ }
+
+ bool is_empty() const {
+ return data[ 0 ] == 0;
+ }
+
+ void add_index( const size_t entry ) {
+ const block_type ONE = 1;
+ const block_type block_modulo_mask = ( ONE << block_shift ) - 1;
+ size_t index_in_level = entry >> block_shift;
+ size_t address = index_in_level + offset;
+ size_t index_in_block = entry & block_modulo_mask;
+
+ block_type mask = ( ONE << ( block_size_in_bits - index_in_block - 1 ) );
+
+ data[ address ] ^= mask;
+
+ // Check if we reached the root. Also, if anyone else was in this block, we don't need to update the path up.
+ while( address && !( data[ address ] & ~mask ) ) {
+ index_in_block = index_in_level & block_modulo_mask;
+ index_in_level >>= block_shift;
+ --address;
+ address >>= block_shift;
+ mask = ( ONE << ( block_size_in_bits - index_in_block - 1 ) );
+ data[ address ] ^= mask;
+ }
+ }
+
+ void get_col_and_clear( column &out ) {
+ index mx = this->get_max_index();
+ while( mx != -1 ) {
+ out.push_back( mx );
+ add_index( mx );
+ mx = this->get_max_index();
+ }
+
+ std::reverse( out.begin(), out.end() );
+ }
+
+ void add_col(const column &col) {
+ for( size_t i = 0; i < col.size(); ++i )
+ add_index(col[i]);
+ }
+
+ void clear() {
+ index mx = this->get_max_index();
+ while( mx != -1 ) {
+ add_index( mx );
+ mx = this->get_max_index();
+ }
+ }
+
+ void remove_max() {
+ add_index( get_max_index() );
+ }
+
+ void set_col( const column& col ) {
+ clear();
+ add_col( col );
+ }
+
+ void get_col( column& col ) {
+ get_col_and_clear( col );
+ add_col( col );
+ }
+ };
+
+ typedef abstract_pivot_column<bit_tree_column> bit_tree_pivot_column;
+}
diff --git a/matching/include/phat/representations/full_pivot_column.h b/matching/include/phat/representations/full_pivot_column.h
new file mode 100644
index 0000000..c2e9e3c
--- /dev/null
+++ b/matching/include/phat/representations/full_pivot_column.h
@@ -0,0 +1,100 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/representations/abstract_pivot_column.h>
+
+namespace phat {
+ class full_column {
+
+ protected:
+ std::priority_queue< index > history;
+ std::vector< char > is_in_history;
+ std::vector< char > col_bit_field;
+
+ public:
+ void init( const index total_size ) {
+ col_bit_field.resize( total_size, false );
+ is_in_history.resize( total_size, false );
+ }
+
+ void add_col( const column& col ) {
+ for( index idx = 0; idx < (index) col.size(); idx++ ) {
+ add_index( col[ idx ] );
+ }
+ }
+
+ void add_index( const index idx ) {
+ if( !is_in_history[ idx ] ) {
+ history.push( idx );
+ is_in_history[ idx ] = true;
+ }
+
+ col_bit_field[ idx ] = !col_bit_field[ idx ];
+ }
+
+ index get_max_index() {
+ while( history.size() > 0 ) {
+ index topIndex = history.top();
+ if( col_bit_field[ topIndex ] ) {
+ return topIndex;
+ } else {
+ history.pop();
+ is_in_history[ topIndex ] = false;
+ }
+ }
+
+ return -1;
+ }
+
+ void get_col_and_clear( column& col ) {
+ while( !is_empty() ) {
+ col.push_back( get_max_index() );
+ add_index( get_max_index() );
+ }
+ std::reverse( col.begin(), col.end() );
+ }
+
+ bool is_empty() {
+ return (get_max_index() == -1);
+ }
+
+ void clear() {
+ while( !is_empty() )
+ add_index( get_max_index() );
+ }
+
+ void remove_max() {
+ add_index( get_max_index() );
+ }
+
+ void set_col( const column& col ) {
+ clear();
+ add_col( col );
+ }
+
+ void get_col( column& col ) {
+ get_col_and_clear( col );
+ add_col( col );
+ }
+ };
+
+ typedef abstract_pivot_column< full_column > full_pivot_column;
+}
diff --git a/matching/include/phat/representations/heap_pivot_column.h b/matching/include/phat/representations/heap_pivot_column.h
new file mode 100644
index 0000000..33cd07b
--- /dev/null
+++ b/matching/include/phat/representations/heap_pivot_column.h
@@ -0,0 +1,126 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/representations/abstract_pivot_column.h>
+
+namespace phat {
+ class heap_column {
+
+ protected:
+ std::priority_queue< index > data;
+
+ column temp_col;
+ index inserts_since_last_prune;
+
+ void prune()
+ {
+ temp_col.clear( );
+ index max_index = pop_max_index( );
+ while( max_index != -1 ) {
+ temp_col.push_back( max_index );
+ max_index = pop_max_index( );
+ }
+
+ for( index idx = 0; idx < (index)temp_col.size( ); idx++ )
+ data.push( temp_col[ idx ] );
+
+ inserts_since_last_prune = 0;
+ }
+
+ index pop_max_index()
+ {
+ if( data.empty( ) )
+ return -1;
+ else {
+ index max_element = data.top( );
+ data.pop();
+ while( !data.empty( ) && data.top( ) == max_element ) {
+ data.pop( );
+ if( data.empty( ) )
+ return -1;
+ else {
+ max_element = data.top( );
+ data.pop( );
+ }
+ }
+ return max_element;
+ }
+ }
+
+ public:
+ void init( const index total_size ) {
+ inserts_since_last_prune = 0;
+ clear();
+ }
+
+ void add_col( const column& col ) {
+ for( index idx = 0; idx < (index) col.size(); idx++ )
+ data.push( col[ idx ] );
+ inserts_since_last_prune += col.size( );
+ if( 2 * inserts_since_last_prune >( index ) data.size( ) )
+ prune();
+ }
+
+ index get_max_index() {
+ index max_element = pop_max_index( );
+ if( max_element == -1 )
+ return -1;
+ else {
+ data.push( max_element );
+ return max_element;
+ }
+ }
+
+ void get_col_and_clear( column& col ) {
+ col.clear();
+ index max_index = pop_max_index( );
+ while( max_index != -1 ) {
+ col.push_back( max_index );
+ max_index = pop_max_index( );
+ }
+ std::reverse( col.begin(), col.end() );
+ }
+
+ bool is_empty() {
+ return get_max_index() == -1;
+ }
+
+ void clear() {
+ data = std::priority_queue< index >();
+ }
+
+ void remove_max() {
+ pop_max_index();
+ }
+
+ void set_col( const column& col ) {
+ clear();
+ add_col( col );
+ }
+
+ void get_col( column& col ) {
+ get_col_and_clear( col );
+ add_col( col );
+ }
+ };
+
+ typedef abstract_pivot_column< heap_column > heap_pivot_column;
+}
diff --git a/matching/include/phat/representations/sparse_pivot_column.h b/matching/include/phat/representations/sparse_pivot_column.h
new file mode 100644
index 0000000..390fd91
--- /dev/null
+++ b/matching/include/phat/representations/sparse_pivot_column.h
@@ -0,0 +1,79 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+#include <phat/representations/abstract_pivot_column.h>
+
+namespace phat {
+ class sparse_column {
+
+ protected:
+ std::set< index > data;
+
+ void add_index( const index idx ) {
+ std::pair< std::set< index >::iterator, bool > result = data.insert( idx );
+ if( result.second == false )
+ data.erase( result.first );
+ }
+
+ public:
+ void init( const index total_size ) {
+ data.clear();
+ }
+
+ void add_col( const column& col ) {
+ for( index idx = 0; idx < (index) col.size(); idx++ )
+ add_index( col[ idx ] );
+ }
+
+ index get_max_index() {
+ return data.empty() ? -1 : *data.rbegin();
+ }
+
+ void get_col_and_clear( column& col ) {
+ col.assign( data.begin(), data.end() );
+ data.clear();
+ }
+
+ bool is_empty() {
+ return data.empty();
+ }
+
+ void clear() {
+ data.clear();
+ }
+
+ void remove_max() {
+ add_index( get_max_index() );
+ }
+
+ void set_col( const column& col ) {
+ clear();
+ add_col( col );
+ }
+
+ void get_col( column& col ) {
+ get_col_and_clear( col );
+ add_col( col );
+ }
+ };
+
+ typedef abstract_pivot_column< sparse_column > sparse_pivot_column;
+}
diff --git a/matching/include/phat/representations/vector_heap.h b/matching/include/phat/representations/vector_heap.h
new file mode 100644
index 0000000..db0420f
--- /dev/null
+++ b/matching/include/phat/representations/vector_heap.h
@@ -0,0 +1,170 @@
+/* Copyright 2013 IST Austria
+Contributed by: Jan Reininghaus
+
+This file is part of PHAT.
+
+PHAT 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.
+
+PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+
+namespace phat {
+ class vector_heap {
+
+ protected:
+ std::vector< dimension > dims;
+ std::vector< column > matrix;
+
+ std::vector< index > inserts_since_last_prune;
+
+ mutable thread_local_storage< column > temp_column_buffer;
+
+ protected:
+ void _prune( index idx )
+ {
+ column& col = matrix[ idx ];
+ column& temp_col = temp_column_buffer();
+ temp_col.clear();
+ index max_index = _pop_max_index( col );
+ while( max_index != -1 ) {
+ temp_col.push_back( max_index );
+ max_index = _pop_max_index( col );
+ }
+ col = temp_col;
+ std::reverse( col.begin( ), col.end( ) );
+ std::make_heap( col.begin( ), col.end( ) );
+ inserts_since_last_prune[ idx ] = 0;
+ }
+
+ index _pop_max_index( index idx )
+ {
+ return _pop_max_index( matrix[ idx ] );
+ }
+
+ index _pop_max_index( column& col ) const
+ {
+ if( col.empty( ) )
+ return -1;
+ else {
+ index max_element = col.front( );
+ std::pop_heap( col.begin( ), col.end( ) );
+ col.pop_back( );
+ while( !col.empty( ) && col.front( ) == max_element ) {
+ std::pop_heap( col.begin( ), col.end( ) );
+ col.pop_back( );
+ if( col.empty( ) )
+ return -1;
+ else {
+ max_element = col.front( );
+ std::pop_heap( col.begin( ), col.end( ) );
+ col.pop_back( );
+ }
+ }
+ return max_element;
+ }
+ }
+
+ public:
+ // overall number of cells in boundary_matrix
+ index _get_num_cols( ) const
+ {
+ return (index)matrix.size( );
+ }
+ void _set_num_cols( index nr_of_columns )
+ {
+ dims.resize( nr_of_columns );
+ matrix.resize( nr_of_columns );
+ inserts_since_last_prune.assign( nr_of_columns, 0 );
+ }
+
+ // dimension of given index
+ dimension _get_dim( index idx ) const
+ {
+ return dims[ idx ];
+ }
+ void _set_dim( index idx, dimension dim )
+ {
+ dims[ idx ] = dim;
+ }
+
+ // replaces(!) content of 'col' with boundary of given index
+ void _get_col( index idx, column& col ) const
+ {
+ temp_column_buffer( ) = matrix[ idx ];
+
+ index max_index = _pop_max_index( temp_column_buffer() );
+ while( max_index != -1 ) {
+ col.push_back( max_index );
+ max_index = _pop_max_index( temp_column_buffer( ) );
+ }
+ std::reverse( col.begin( ), col.end( ) );
+ }
+ void _set_col( index idx, const column& col )
+ {
+ matrix[ idx ] = col;
+ std::make_heap( matrix[ idx ].begin( ), matrix[ idx ].end( ) );
+ }
+
+ // true iff boundary of given idx is empty
+ bool _is_empty( index idx ) const
+ {
+ return _get_max_index( idx ) == -1;
+ }
+
+ // largest row index of given column idx (new name for lowestOne())
+ index _get_max_index( index idx ) const
+ {
+ column& col = const_cast< column& >( matrix[ idx ] );
+ index max_element = _pop_max_index( col );
+ col.push_back( max_element );
+ std::push_heap( col.begin( ), col.end( ) );
+ return max_element;
+ }
+
+ // removes the maximal index of a column
+ void _remove_max( index idx )
+ {
+ _pop_max_index( idx );
+ }
+
+ // clears given column
+ void _clear( index idx )
+ {
+ matrix[ idx ].clear( );
+ }
+
+ // syncronizes all data structures (essential for openmp stuff)
+ void _sync( ) {}
+
+ // adds column 'source' to column 'target'
+ void _add_to( index source, index target )
+ {
+ for( index idx = 0; idx < (index)matrix[ source ].size( ); idx++ ) {
+ matrix[ target ].push_back( matrix[ source ][ idx ] );
+ std::push_heap( matrix[ target ].begin(), matrix[ target ].end() );
+ }
+ inserts_since_last_prune[ target ] += matrix[ source ].size();
+
+ if( 2 * inserts_since_last_prune[ target ] > ( index )matrix[ target ].size() )
+ _prune( target );
+ }
+
+ // finalizes given column
+ void _finalize( index idx ) {
+ _prune( idx );
+ }
+
+ };
+}
diff --git a/matching/include/phat/representations/vector_list.h b/matching/include/phat/representations/vector_list.h
new file mode 100644
index 0000000..ca0b5b8
--- /dev/null
+++ b/matching/include/phat/representations/vector_list.h
@@ -0,0 +1,101 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+
+namespace phat {
+ class vector_list {
+
+ protected:
+ std::vector< dimension > dims;
+ std::vector< std::list< index > > matrix;
+
+ public:
+ // overall number of cells in boundary_matrix
+ index _get_num_cols() const {
+ return (index)matrix.size();
+ }
+ void _set_num_cols( index nr_of_columns ) {
+ dims.resize( nr_of_columns );
+ matrix.resize( nr_of_columns );
+ }
+
+ // dimension of given index
+ dimension _get_dim( index idx ) const {
+ return dims[ idx ];
+ }
+ void _set_dim( index idx, dimension dim ) {
+ dims[ idx ] = dim;
+ }
+
+ // replaces(!) content of 'col' with boundary of given index
+ void _get_col( index idx, column& col ) const {
+ col.clear();
+ col.reserve( matrix[idx].size() );
+ std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) );
+ }
+
+ void _set_col( index idx, const column& col ) {
+ matrix[ idx ].clear();
+ matrix[ idx ].resize( col.size() );
+ std::copy (col.begin(), col.end(), matrix[ idx ].begin() );
+ }
+
+ // true iff boundary of given idx is empty
+ bool _is_empty( index idx ) const {
+ return matrix[ idx ].empty();
+ }
+
+ // largest row index of given column idx (new name for lowestOne())
+ index _get_max_index( index idx ) const {
+ return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin();
+ }
+
+ // removes the maximal index of a column
+ void _remove_max( index idx ) {
+ std::list< index >::iterator it = matrix[ idx ].end();
+ it--;
+ matrix[ idx ].erase( it );
+ }
+
+ // clears given column
+ void _clear( index idx ) {
+ matrix[ idx ].clear();
+ }
+
+ // syncronizes all data structures (essential for openmp stuff)
+ void _sync() {}
+
+ // adds column 'source' to column 'target'
+ void _add_to( index source, index target ) {
+ std::list< index >& source_col = matrix[ source ];
+ std::list< index >& target_col = matrix[ target ];
+ std::list< index > temp_col;
+ target_col.swap( temp_col );
+ std::set_symmetric_difference( temp_col.begin(), temp_col.end(),
+ source_col.begin(), source_col.end(),
+ std::back_inserter( target_col ) );
+ }
+
+ // finalizes given column
+ void _finalize( index idx ) {
+ }
+ };
+}
diff --git a/matching/include/phat/representations/vector_set.h b/matching/include/phat/representations/vector_set.h
new file mode 100644
index 0000000..6878a27
--- /dev/null
+++ b/matching/include/phat/representations/vector_set.h
@@ -0,0 +1,99 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+
+namespace phat {
+ class vector_set {
+
+ protected:
+ std::vector< dimension > dims;
+ std::vector< std::set< index > > matrix;
+
+ public:
+ // overall number of cells in boundary_matrix
+ index _get_num_cols() const {
+ return (index)matrix.size();
+ }
+ void _set_num_cols( index nr_of_columns ) {
+ dims.resize( nr_of_columns );
+ matrix.resize( nr_of_columns );
+ }
+
+ // dimension of given index
+ dimension _get_dim( index idx ) const {
+ return dims[ idx ];
+ }
+ void _set_dim( index idx, dimension dim ) {
+ dims[ idx ] = dim;
+ }
+
+ // replaces(!) content of 'col' with boundary of given index
+ void _get_col( index idx, column& col ) const {
+ col.clear();
+ col.reserve( matrix[idx].size() );
+ std::copy (matrix[idx].begin(), matrix[idx].end(), std::back_inserter(col) );
+ }
+ void _set_col( index idx, const column& col ) {
+ matrix[ idx ].clear();
+ matrix[ idx ].insert( col.begin(), col.end() );
+ }
+
+ // true iff boundary of given idx is empty
+ bool _is_empty( index idx ) const {
+ return matrix[ idx ].empty();
+ }
+
+ // largest row index of given column idx (new name for lowestOne())
+ index _get_max_index( index idx ) const {
+ return matrix[ idx ].empty() ? -1 : *matrix[ idx ].rbegin();
+ }
+
+ // removes the maximal index of a column
+ void _remove_max( index idx ) {
+ std::set< index >::iterator it = matrix[ idx ].end();
+ it--;
+ matrix[ idx ].erase( it );
+ }
+
+ // clears given column
+ void _clear( index idx ) {
+ matrix[ idx ].clear();
+ }
+
+ // syncronizes all data structures (essential for openmp stuff)
+ void _sync() {}
+
+ // adds column 'source' to column 'target'
+ void _add_to( index source, index target ) {
+ for( std::set< index >::iterator it = matrix[ source ].begin(); it != matrix[ source ].end(); it++ ) {
+ std::set< index >& col = matrix[ target ];
+ std::pair< std::set< index >::iterator, bool > result = col.insert( *it );
+ if( !result.second )
+ col.erase( result.first );
+ }
+ }
+
+ // finalizes given column
+ void _finalize( index idx ) {
+ }
+
+ };
+}
diff --git a/matching/include/phat/representations/vector_vector.h b/matching/include/phat/representations/vector_vector.h
new file mode 100644
index 0000000..f111d6b
--- /dev/null
+++ b/matching/include/phat/representations/vector_vector.h
@@ -0,0 +1,107 @@
+/* Copyright 2013 IST Austria
+ Contributed by: Ulrich Bauer, Michael Kerber, Jan Reininghaus
+
+ This file is part of PHAT.
+
+ PHAT 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.
+
+ PHAT 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 PHAT. If not, see <http://www.gnu.org/licenses/>. */
+
+#pragma once
+
+#include <phat/helpers/misc.h>
+
+namespace phat {
+ class vector_vector {
+
+ protected:
+ std::vector< dimension > dims;
+ std::vector< column > matrix;
+
+ thread_local_storage< column > temp_column_buffer;
+
+ public:
+ // overall number of cells in boundary_matrix
+ index _get_num_cols() const {
+ return (index)matrix.size();
+ }
+ void _set_num_cols( index nr_of_columns ) {
+ dims.resize( nr_of_columns );
+ matrix.resize( nr_of_columns );
+ }
+
+ // dimension of given index
+ dimension _get_dim( index idx ) const {
+ return dims[ idx ];
+ }
+ void _set_dim( index idx, dimension dim ) {
+ dims[ idx ] = dim;
+ }
+
+ // replaces(!) content of 'col' with boundary of given index
+ void _get_col( index idx, column& col ) const {
+ col = matrix[ idx ];
+ }
+ void _set_col( index idx, const column& col ) {
+ matrix[ idx ] = col;
+ }
+
+ // true iff boundary of given idx is empty
+ bool _is_empty( index idx ) const {
+ return matrix[ idx ].empty();
+ }
+
+ // largest row index of given column idx (new name for lowestOne())
+ index _get_max_index( index idx ) const {
+ return matrix[ idx ].empty() ? -1 : matrix[ idx ].back();
+ }
+
+ // removes the maximal index of a column
+ void _remove_max( index idx ) {
+ matrix[ idx ].pop_back();
+ }
+
+ // clears given column
+ void _clear( index idx ) {
+ matrix[ idx ].clear();
+ }
+
+ // syncronizes all data structures (essential for openmp stuff)
+ void _sync() {}
+
+ // adds column 'source' to column 'target'
+ void _add_to( index source, index target ) {
+ column& source_col = matrix[ source ];
+ column& target_col = matrix[ target ];
+ column& temp_col = temp_column_buffer();
+
+
+ size_t new_size = source_col.size() + target_col.size();
+
+ if (new_size > temp_col.size()) temp_col.resize(new_size);
+
+ std::vector<index>::iterator col_end = std::set_symmetric_difference( target_col.begin(), target_col.end(),
+ source_col.begin(), source_col.end(),
+ temp_col.begin() );
+ temp_col.erase(col_end, temp_col.end());
+
+
+ target_col.swap(temp_col);
+ }
+
+ // finalizes given column
+ void _finalize( index idx ) {
+ column& col = matrix[ idx ];
+ column(col.begin(), col.end()).swap(col);
+ }
+ };
+}
diff --git a/matching/include/simplex.h b/matching/include/simplex.h
new file mode 100644
index 0000000..75bbcae
--- /dev/null
+++ b/matching/include/simplex.h
@@ -0,0 +1,163 @@
+#ifndef MATCHING_DISTANCE_SIMPLEX_H
+#define MATCHING_DISTANCE_SIMPLEX_H
+
+#include <algorithm>
+#include <vector>
+#include <ostream>
+
+#include "common_util.h"
+
+namespace md {
+
+ template<class Real>
+ class Bifiltration;
+
+ enum class BifiltrationFormat {
+ phat_like, rivet
+ };
+
+ class AbstractSimplex {
+ private:
+ std::vector<int> vertices_;
+ public:
+
+ // this member is for convenience only;
+ // abstract simplices are identified by their set of vertices
+ mutable int id {-1};
+
+ decltype(auto) begin() { return vertices_.begin(); }
+
+ decltype(auto) end() { return vertices_.end(); }
+
+ decltype(auto) begin() const { return vertices_.begin(); }
+
+ decltype(auto) end() const { return vertices_.end(); }
+
+ decltype(auto) cbegin() const { return vertices_.cbegin(); }
+
+ decltype(auto) cend() const { return vertices_.cend(); }
+
+ int dim() const { return vertices_.size() - 1; }
+
+ void push_back(int v)
+ {
+ vertices_.push_back(v);
+ std::sort(vertices_.begin(), vertices_.end());
+ }
+
+ AbstractSimplex() { }
+
+ AbstractSimplex(std::vector<int> vertices, bool sort = true)
+ :vertices_(vertices)
+ {
+ if (sort)
+ std::sort(vertices_.begin(), vertices_.end());
+ }
+
+
+ template<class Iter>
+ AbstractSimplex(Iter beg_iter, Iter end_iter, bool sort = true)
+ :
+ vertices_(beg_iter, end_iter)
+ {
+ if (sort)
+ std::sort(vertices_.begin(), end());
+ }
+
+ std::vector<AbstractSimplex> facets() const
+ {
+ std::vector<AbstractSimplex> result;
+ for (int i = 0; i < static_cast<int>(vertices_.size()); ++i) {
+ std::vector<int> facet_vertices;
+ facet_vertices.reserve(dim());
+ for (int j = 0; j < static_cast<int>(vertices_.size()); ++j) {
+ if (j != i)
+ facet_vertices.push_back(vertices_[j]);
+ }
+ if (!facet_vertices.empty()) {
+ result.emplace_back(facet_vertices, false);
+ }
+ }
+ return result;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const AbstractSimplex& s);
+ // compare by vertices_ only
+ friend bool operator==(const AbstractSimplex& s1, const AbstractSimplex& s2);
+
+ friend bool operator<(const AbstractSimplex&, const AbstractSimplex&);
+ };
+
+ inline std::ostream& operator<<(std::ostream& os, const AbstractSimplex& s)
+ {
+ os << "AbstractSimplex(id = " << s.id << ", vertices_ = " << container_to_string(s.vertices_) << ")";
+ return os;
+ }
+
+ inline bool operator<(const AbstractSimplex& a, const AbstractSimplex& b)
+ {
+ return a.vertices_ < b.vertices_;
+ }
+
+ inline bool operator==(const AbstractSimplex& s1, const AbstractSimplex& s2)
+ {
+ return s1.vertices_ == s2.vertices_;
+ }
+
+ template<class Real>
+ class Simplex {
+ private:
+ Index id_;
+ Point<Real> pos_;
+ int dim_;
+ // in our format we use facet indices,
+ // this is the fastest representation for homology
+ // Rivet format fills vertices_ vector
+ // Simplex alone cannot convert from one representation to the other,
+ // conversion routines are in Bifiltration
+ Column facet_indices_;
+ Column vertices_;
+ Real v {0}; // used when constructed a filtration for a slice
+ public:
+ Simplex(Index _id, std::string s, BifiltrationFormat input_format);
+
+ Simplex(Index _id, Point<Real> birth, int _dim, const Column& _bdry);
+
+ void init_rivet(std::string s);
+
+ void init_phat_like(std::string s);
+
+ Index id() const { return id_; }
+
+ int dim() const { return dim_; }
+
+ Column boundary() const { return facet_indices_; }
+
+ Real value() const { return v; }
+
+ // assumes 1-criticality
+ Point<Real> position() const { return pos_; }
+
+ void set_position(const Point<Real>& new_pos) { pos_ = new_pos; }
+
+ void scale(Real lambda)
+ {
+ pos_.x *= lambda;
+ pos_.y *= lambda;
+ }
+
+ void translate(Real a);
+
+ void set_value(Real new_val) { v = new_val; }
+
+ friend Bifiltration<Real>;
+ };
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const Simplex<Real>& s);
+
+}
+
+#include "simplex.hpp"
+
+#endif //MATCHING_DISTANCE_SIMPLEX_H
diff --git a/matching/include/simplex.hpp b/matching/include/simplex.hpp
new file mode 100644
index 0000000..ce0e30f
--- /dev/null
+++ b/matching/include/simplex.hpp
@@ -0,0 +1,79 @@
+namespace md {
+
+ template<class Real>
+ Simplex<Real>::Simplex(Index id, Point<Real> birth, int dim, const Column& bdry)
+ :
+ id_(id),
+ pos_(birth),
+ dim_(dim),
+ facet_indices_(bdry) { }
+
+ template<class Real>
+ void Simplex<Real>::translate(Real a)
+ {
+ pos_.translate(a);
+ }
+
+ template<class Real>
+ void Simplex<Real>::init_rivet(std::string s)
+ {
+ auto delim_pos = s.find_first_of(";");
+ assert(delim_pos > 0);
+ std::string vertices_str = s.substr(0, delim_pos);
+ std::string pos_str = s.substr(delim_pos + 1);
+ assert(not vertices_str.empty() and not pos_str.empty());
+ // get vertices
+ std::stringstream vertices_ss(vertices_str);
+ int dim = 0;
+ int vertex;
+ while (vertices_ss >> vertex) {
+ dim++;
+ vertices_.push_back(vertex);
+ }
+ //
+ std::sort(vertices_.begin(), vertices_.end());
+ assert(dim > 0);
+
+ std::stringstream pos_ss(pos_str);
+ // TODO: get rid of 1-criticaltiy assumption
+ pos_ss >> pos_.x >> pos_.y;
+ }
+
+ template<class Real>
+ void Simplex<Real>::init_phat_like(std::string s)
+ {
+ facet_indices_.clear();
+ std::stringstream ss(s);
+ ss >> dim_ >> pos_.x >> pos_.y;
+ if (dim_ > 0) {
+ facet_indices_.reserve(dim_ + 1);
+ for (int j = 0; j <= dim_; j++) {
+ Index k;
+ ss >> k;
+ facet_indices_.push_back(k);
+ }
+ }
+ }
+
+ template<class Real>
+ Simplex<Real>::Simplex(Index _id, std::string s, BifiltrationFormat input_format)
+ :id_(_id)
+ {
+ switch (input_format) {
+ case BifiltrationFormat::phat_like :
+ init_phat_like(s);
+ break;
+ case BifiltrationFormat::rivet :
+ init_rivet(s);
+ break;
+ }
+ }
+
+ template<class Real>
+ std::ostream& operator<<(std::ostream& os, const Simplex<Real>& x)
+ {
+ os << "Simplex<Real>(id = " << x.id() << ", dim = " << x.dim();
+ os << ", boundary = " << container_to_string(x.boundary()) << ", pos = " << x.position() << ")";
+ return os;
+ }
+}
diff --git a/matching/tests/prism_1.bif b/matching/tests/prism_1.bif
new file mode 100644
index 0000000..b37e807
--- /dev/null
+++ b/matching/tests/prism_1.bif
@@ -0,0 +1,28 @@
+bifiltration_phat_like
+26
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+1 1 0 1 0
+1 1 0 2 1
+1 0 0 3 1
+1 0 1 5 4
+1 0 0 4 1
+1 0 0 3 0
+1 0 0 5 0
+1 0 0 4 2
+1 0 0 5 2
+1 0 1 4 3
+1 1 0 2 0
+1 0 1 5 3
+2 1 1 13 10 7
+2 1 1 9 14 13
+2 1 1 8 11 6
+2 1 1 15 10 8
+2 1 1 14 12 16
+2 1 1 17 12 11
+2 4 0 7 16 6
+2 0 4 9 17 15
diff --git a/matching/tests/prism_2.bif b/matching/tests/prism_2.bif
new file mode 100644
index 0000000..49885e6
--- /dev/null
+++ b/matching/tests/prism_2.bif
@@ -0,0 +1,29 @@
+bifiltration_phat_like
+27
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+0 0 0
+1 0 0 2 1
+1 0 0 1 0
+1 0 0 5 3
+1 0 0 3 1
+1 0 0 5 4
+1 0 0 2 0
+1 0 0 4 1
+1 0 0 3 2
+1 0 0 5 2
+1 0 0 4 3
+1 0 0 4 2
+1 0 0 3 0
+2 0 0 16 12 6
+2 0 0 10 14 16
+2 0 0 9 17 7
+2 0 0 15 12 9
+2 0 0 13 17 11
+2 0 0 8 14 13
+2 4 0 6 11 7
+2 0 4 10 8 15
+2 3 3 15 16 13
diff --git a/matching/tests/test_bifiltration.cpp b/matching/tests/test_bifiltration.cpp
new file mode 100644
index 0000000..742dab8
--- /dev/null
+++ b/matching/tests/test_bifiltration.cpp
@@ -0,0 +1,36 @@
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+
+#include "common_util.h"
+#include "box.h"
+#include "bifiltration.h"
+
+using namespace md;
+
+//TEST_CASE("Small check", "[bifiltration][dim2]")
+//{
+// Bifiltration bif("/home/narn/code/matching_distance/code/src/tests/test_bifiltration_full_triangle_phat_like.txt", BifiltrationFormat::phat_like);
+// auto simplices = bif.simplices();
+// bif.sanity_check();
+//
+// REQUIRE( simplices.size() == 7 );
+//
+// REQUIRE( simplices[0].dim() == 0 );
+// REQUIRE( simplices[1].dim() == 0 );
+// REQUIRE( simplices[2].dim() == 0 );
+// REQUIRE( simplices[3].dim() == 1 );
+// REQUIRE( simplices[4].dim() == 1 );
+// REQUIRE( simplices[5].dim() == 1 );
+// REQUIRE( simplices[6].dim() == 2);
+//
+// REQUIRE( simplices[0].position() == Point(0, 0));
+// REQUIRE( simplices[1].position() == Point(0, 0));
+// REQUIRE( simplices[2].position() == Point(0, 0));
+// REQUIRE( simplices[3].position() == Point(3, 1));
+// REQUIRE( simplices[6].position() == Point(30, 40));
+//
+// Line line_1(Line::pi / 2.0, 0.0);
+// auto dgm = bif.slice_diagram(line_1);
+//}
diff --git a/matching/tests/test_common.cpp b/matching/tests/test_common.cpp
new file mode 100644
index 0000000..9079a56
--- /dev/null
+++ b/matching/tests/test_common.cpp
@@ -0,0 +1,156 @@
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+#include <string>
+
+#include "common_util.h"
+#include "simplex.h"
+#include "matching_distance.h"
+
+//using namespace md;
+using Real = double;
+using Point = md::Point<Real>;
+using Bifiltration = md::Bifiltration<Real>;
+using BifiltrationProxy = md::BifiltrationProxy<Real>;
+using CalculationParams = md::CalculationParams<Real>;
+using CellWithValue = md::CellWithValue<Real>;
+using DualPoint = md::DualPoint<Real>;
+using DualBox = md::DualBox<Real>;
+using Simplex = md::Simplex<Real>;
+using AbstractSimplex = md::AbstractSimplex;
+using BoundStrategy = md::BoundStrategy;
+using TraverseStrategy = md::TraverseStrategy;
+using AxisType = md::AxisType;
+using AngleType = md::AngleType;
+using ValuePoint = md::ValuePoint;
+using Column = md::Column;
+
+
+TEST_CASE("AbstractSimplex", "[abstract_simplex]")
+{
+ AbstractSimplex as;
+ REQUIRE(as.dim() == -1);
+
+ as.push_back(1);
+ REQUIRE(as.dim() == 0);
+ REQUIRE(as.facets().size() == 0);
+
+ as.push_back(0);
+ REQUIRE(as.dim() == 1);
+ REQUIRE(as.facets().size() == 2);
+ REQUIRE(as.facets()[0].dim() == 0);
+ REQUIRE(as.facets()[1].dim() == 0);
+
+}
+
+TEST_CASE("Vertical line", "[vertical_line]")
+{
+ // line x = 1
+ DualPoint l_vertical(AxisType::x_type, AngleType::steep, 0, 1);
+
+ REQUIRE(l_vertical.is_vertical());
+ REQUIRE(l_vertical.is_steep());
+
+ Point p_1(0.5, 0.5);
+ Point p_2(1.5, 0.5);
+ Point p_3(1.5, 1.5);
+ Point p_4(0.5, 1.5);
+ Point p_5(1, 10);
+
+ REQUIRE(l_vertical.x_from_y(10) == 1);
+ REQUIRE(l_vertical.x_from_y(-10) == 1);
+ REQUIRE(l_vertical.x_from_y(0) == 1);
+
+ REQUIRE(not l_vertical.contains(p_1));
+ REQUIRE(not l_vertical.contains(p_2));
+ REQUIRE(not l_vertical.contains(p_3));
+ REQUIRE(not l_vertical.contains(p_4));
+ REQUIRE(l_vertical.contains(p_5));
+
+ REQUIRE(l_vertical.goes_below(p_1));
+ REQUIRE(not l_vertical.goes_below(p_2));
+ REQUIRE(not l_vertical.goes_below(p_3));
+ REQUIRE(l_vertical.goes_below(p_4));
+
+ REQUIRE(not l_vertical.goes_above(p_1));
+ REQUIRE(l_vertical.goes_above(p_2));
+ REQUIRE(l_vertical.goes_above(p_3));
+ REQUIRE(not l_vertical.goes_above(p_4));
+
+}
+
+TEST_CASE("Horizontal line", "[horizontal_line]")
+{
+ // line y = 1
+ DualPoint l_horizontal(AxisType::y_type, AngleType::flat, 0, 1);
+
+ REQUIRE(l_horizontal.is_horizontal());
+ REQUIRE(l_horizontal.is_flat());
+ REQUIRE(l_horizontal.y_slope() == 0);
+ REQUIRE(l_horizontal.y_intercept() == 1);
+
+ Point p_1(0.5, 0.5);
+ Point p_2(1.5, 0.5);
+ Point p_3(1.5, 1.5);
+ Point p_4(0.5, 1.5);
+ Point p_5(2, 1);
+
+ REQUIRE((not l_horizontal.contains(p_1) and
+ not l_horizontal.contains(p_2) and
+ not l_horizontal.contains(p_3) and
+ not l_horizontal.contains(p_4) and
+ l_horizontal.contains(p_5)));
+
+ REQUIRE(not l_horizontal.goes_below(p_1));
+ REQUIRE(not l_horizontal.goes_below(p_2));
+ REQUIRE(l_horizontal.goes_below(p_3));
+ REQUIRE(l_horizontal.goes_below(p_4));
+ REQUIRE(l_horizontal.goes_below(p_5));
+
+ REQUIRE(l_horizontal.goes_above(p_1));
+ REQUIRE(l_horizontal.goes_above(p_2));
+ REQUIRE(not l_horizontal.goes_above(p_3));
+ REQUIRE(not l_horizontal.goes_above(p_4));
+ REQUIRE(l_horizontal.goes_above(p_5));
+}
+
+TEST_CASE("Flat Line with positive slope", "[flat_line]")
+{
+ // line y = x / 2 + 1
+ DualPoint l_flat(AxisType::y_type, AngleType::flat, 0.5, 1);
+
+ REQUIRE(not l_flat.is_horizontal());
+ REQUIRE(l_flat.is_flat());
+ REQUIRE(l_flat.y_slope() == 0.5);
+ REQUIRE(l_flat.y_intercept() == 1);
+
+ REQUIRE(l_flat.y_from_x(0) == 1);
+ REQUIRE(l_flat.y_from_x(1) == 1.5);
+ REQUIRE(l_flat.y_from_x(2) == 2);
+
+ Point p_1(3, 2);
+ Point p_2(-2, 0.01);
+ Point p_3(0, 1.25);
+ Point p_4(6, 4.5);
+ Point p_5(2, 2);
+
+ REQUIRE((not l_flat.contains(p_1) and
+ not l_flat.contains(p_2) and
+ not l_flat.contains(p_3) and
+ not l_flat.contains(p_4) and
+ l_flat.contains(p_5)));
+
+ REQUIRE(not l_flat.goes_below(p_1));
+ REQUIRE(l_flat.goes_below(p_2));
+ REQUIRE(l_flat.goes_below(p_3));
+ REQUIRE(l_flat.goes_below(p_4));
+ REQUIRE(l_flat.goes_below(p_5));
+
+ REQUIRE(l_flat.goes_above(p_1));
+ REQUIRE(not l_flat.goes_above(p_2));
+ REQUIRE(not l_flat.goes_above(p_3));
+ REQUIRE(not l_flat.goes_above(p_4));
+ REQUIRE(l_flat.goes_above(p_5));
+
+}
diff --git a/matching/tests/test_list.txt b/matching/tests/test_list.txt
new file mode 100644
index 0000000..28ee48b
--- /dev/null
+++ b/matching/tests/test_list.txt
@@ -0,0 +1 @@
+prism_1.bif prism_2.bif 1.0
diff --git a/matching/tests/test_matching_distance.cpp b/matching/tests/test_matching_distance.cpp
new file mode 100644
index 0000000..115c8d9
--- /dev/null
+++ b/matching/tests/test_matching_distance.cpp
@@ -0,0 +1,159 @@
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+#include <string>
+
+#define MD_TEST_CODE
+
+#include "common_util.h"
+#include "simplex.h"
+#include "matching_distance.h"
+
+using Real = double;
+using Point = md::Point<Real>;
+using Bifiltration = md::Bifiltration<Real>;
+using BifiltrationProxy = md::BifiltrationProxy<Real>;
+using CalculationParams = md::CalculationParams<Real>;
+using CellWithValue = md::CellWithValue<Real>;
+using DualPoint = md::DualPoint<Real>;
+using DualBox = md::DualBox<Real>;
+using Simplex = md::Simplex<Real>;
+using AbstractSimplex = md::AbstractSimplex;
+using BoundStrategy = md::BoundStrategy;
+using TraverseStrategy = md::TraverseStrategy;
+using AxisType = md::AxisType;
+using AngleType = md::AngleType;
+using ValuePoint = md::ValuePoint;
+using Column = md::Column;
+
+using md::k_corner_vps;
+
+TEST_CASE("Different bounds", "[bounds]")
+{
+ std::vector<Simplex> simplices;
+ std::vector<Point> points;
+
+ Real max_x = 10;
+ Real max_y = 20;
+
+ int simplex_id = 0;
+ for(int i = 0; i <= max_x; ++i) {
+ for(int j = 0; j <= max_y; ++j) {
+ Point p(i, j);
+ simplices.emplace_back(simplex_id++, p, 0, Column());
+ points.push_back(p);
+ }
+ }
+
+ Bifiltration bif_a(simplices.begin(), simplices.end());
+ Bifiltration bif_b(simplices.begin(), simplices.end());
+
+ CalculationParams params;
+ params.initialization_depth = 2;
+
+ BifiltrationProxy bifp_a(bif_a, params.dim);
+ BifiltrationProxy bifp_b(bif_b, params.dim);
+
+ md::DistanceCalculator<Real, BifiltrationProxy> calc(bifp_a, bifp_b, params);
+
+// REQUIRE(calc.max_x_ == Approx(max_x));
+// REQUIRE(calc.max_y_ == Approx(max_y));
+
+ std::vector<DualBox> boxes;
+
+ for(CellWithValue c : calc.get_refined_grid(5, false, false)) {
+ boxes.push_back(c.dual_box());
+ }
+
+ // fill in boxes and points
+
+ for(DualBox db : boxes) {
+ Real local_bound = calc.get_local_dual_bound(db);
+ Real local_bound_refined = calc.get_local_refined_bound(db);
+ REQUIRE(local_bound >= local_bound_refined);
+ for(Point p : points) {
+ for(ValuePoint vp_a : k_corner_vps) {
+ CellWithValue dual_cell(db, 1);
+ DualPoint corner_a = dual_cell.value_point(vp_a);
+ Real wp_a = corner_a.weighted_push(p);
+ dual_cell.set_value_at(vp_a, wp_a);
+ Real point_bound = calc.get_max_displacement_single_point(dual_cell, vp_a, p);
+ for(ValuePoint vp_b : k_corner_vps) {
+ if (vp_b <= vp_a)
+ continue;
+ DualPoint corner_b = dual_cell.value_point(vp_b);
+ Real wp_b = corner_b.weighted_push(p);
+ Real diff = fabs(wp_a - wp_b);
+ if (not(point_bound <= Approx(local_bound_refined))) {
+ std::cerr << "ERROR point: " << p << ", box = " << db << ", point bound = " << point_bound
+ << ", refined local = " << local_bound_refined << std::endl;
+ calc.get_max_displacement_single_point(dual_cell, vp_a, p);
+ calc.get_local_refined_bound(db);
+ }
+
+ REQUIRE(point_bound <= Approx(local_bound_refined));
+ REQUIRE(diff <= Approx(point_bound));
+ REQUIRE(diff <= Approx(local_bound_refined));
+ }
+
+ for(DualPoint l_random : db.random_points(100)) {
+ Real wp_random = l_random.weighted_push(p);
+ Real diff = fabs(wp_a - wp_random);
+ if (not(diff <= Approx(point_bound))) {
+ if (db.critical_points(p).size() > 4) {
+ std::cerr << "ERROR interesting case" << std::endl;
+ } else {
+ std::cerr << "ERROR boring case" << std::endl;
+ }
+ l_random.weighted_push(p);
+ std::cerr << "ERROR point: " << p << ", box = " << db << ", point bound = " << point_bound
+ << ", refined local = " << local_bound_refined;
+ std::cerr << ", random_dual_point = " << l_random << ", wp_random = " << wp_random
+ << ", diff = " << diff << std::endl;
+ }
+ REQUIRE(diff <= Approx(point_bound));
+ }
+ }
+ }
+ }
+}
+
+TEST_CASE("Bifiltrations from file", "[matching_distance][small_example]")
+{
+ std::string fname_a, fname_b;
+
+ fname_a = "../tests/prism_1.bif";
+ fname_b = "../tests/prism_2.bif";
+
+ Bifiltration bif_a(fname_a);
+ Bifiltration bif_b(fname_b);
+
+ CalculationParams params;
+
+ std::vector<BoundStrategy> bound_strategies {BoundStrategy::local_combined,
+ BoundStrategy::local_dual_bound_refined};
+
+ std::vector<TraverseStrategy> traverse_strategies {TraverseStrategy::breadth_first, TraverseStrategy::depth_first};
+
+ std::vector<double> scaling_factors {10, 1.0};
+
+ for(auto bs : bound_strategies) {
+ for(auto ts : traverse_strategies) {
+ for(double lambda : scaling_factors) {
+ Bifiltration bif_a_copy(bif_a);
+ Bifiltration bif_b_copy(bif_b);
+ bif_a_copy.scale(lambda);
+ bif_b_copy.scale(lambda);
+ params.bound_strategy = bs;
+ params.traverse_strategy = ts;
+ params.max_depth = 7;
+ params.delta = 0.1;
+ params.dim = 1;
+ Real answer = matching_distance(bif_a_copy, bif_b_copy, params);
+ Real correct_answer = lambda * 1.0;
+ REQUIRE(fabs(answer - correct_answer) / correct_answer < params.delta);
+ }
+ }
+ }
+}
diff --git a/matching/tests/test_module.cpp b/matching/tests/test_module.cpp
new file mode 100644
index 0000000..bae1f78
--- /dev/null
+++ b/matching/tests/test_module.cpp
@@ -0,0 +1,109 @@
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+#include <string>
+
+#define MD_TEST_CODE
+
+#include "common_util.h"
+#include "persistence_module.h"
+#include "matching_distance.h"
+
+using Real = double;
+using Point = md::Point<Real>;
+using Bifiltration = md::Bifiltration<Real>;
+using BifiltrationProxy = md::BifiltrationProxy<Real>;
+using CalculationParams = md::CalculationParams<Real>;
+using CellWithValue = md::CellWithValue<Real>;
+using DualPoint = md::DualPoint<Real>;
+using DualBox = md::DualBox<Real>;
+using BoundStrategy = md::BoundStrategy;
+using TraverseStrategy = md::TraverseStrategy;
+using AxisType = md::AxisType;
+using AngleType = md::AngleType;
+using ValuePoint = md::ValuePoint;
+using Column = md::Column;
+using PointVec = md::PointVec<Real>;
+using Module = md::ModulePresentation<Real>;
+using Relation = Module::Relation;
+using RelationVec = Module::RelVec;
+using IndexVec = md::IndexVec;
+
+using md::k_corner_vps;
+
+TEST_CASE("Module projection", "[module][projection]")
+{
+ PointVec gens;
+ gens.emplace_back(1, 1); // A
+ gens.emplace_back(2, 3); // B
+ gens.emplace_back(3, 2); // C
+
+ RelationVec rels;
+
+ Point rel_x_position { 3.98, 2.47 };
+ IndexVec rel_x_components { 0, 2 }; // X: A + C = 0
+
+ Point rel_y_position { 2.5, 4 };
+ IndexVec rel_y_components { 0, 1 }; // Y: A + B = 0
+
+ Point rel_z_position { 5, 5 };
+ IndexVec rel_z_components { 1 }; // Z: B = 0
+
+
+ rels.emplace_back(rel_x_position, rel_x_components);
+ rels.emplace_back(rel_y_position, rel_y_components);
+ rels.emplace_back(rel_z_position, rel_z_components);
+
+ Module module { gens, rels };
+
+ {
+ DualPoint slice_1(AxisType::x_type, AngleType::flat, 6.0 / 7.0, 3.0);
+ std::vector<Real> gen_ps_1, rel_ps_1;
+ phat::boundary_matrix<> matr_1;
+
+ module.get_slice_projection_matrix(slice_1, matr_1, gen_ps_1, rel_ps_1);
+
+ phat::column c_1_0, c_1_1, c_1_2;
+
+ matr_1.get_col(0, c_1_0);
+ matr_1.get_col(1, c_1_1);
+ matr_1.get_col(2, c_1_2);
+
+ phat::column c_1_0_correct { 0, 1};
+ phat::column c_1_1_correct { 0, 2};
+ phat::column c_1_2_correct { 2 };
+
+ REQUIRE(c_1_0 == c_1_0_correct);
+ REQUIRE(c_1_1 == c_1_1_correct);
+ REQUIRE(c_1_2 == c_1_2_correct);
+ }
+
+ {
+
+ DualPoint slice_2(AxisType::y_type, AngleType::flat, 2.0 / 9.0, 5.0);
+ std::vector<Real> gen_ps_2, rel_ps_2;
+ phat::boundary_matrix<> matr_2;
+
+ module.get_slice_projection_matrix(slice_2, matr_2, gen_ps_2, rel_ps_2);
+
+ phat::column c_2_0, c_2_1, c_2_2;
+
+ matr_2.get_col(0, c_2_0);
+ matr_2.get_col(1, c_2_1);
+ matr_2.get_col(2, c_2_2);
+
+ phat::column c_2_0_correct { 0, 1};
+ phat::column c_2_1_correct { 0, 2};
+ phat::column c_2_2_correct { 1 };
+
+ //std::cerr << "gen_ps_2: " << md::container_to_string(gen_ps_2) << std::endl;
+ //std::cerr << "rel_ps_2: " << md::container_to_string(rel_ps_2) << std::endl;
+
+ REQUIRE(c_2_0 == c_2_0_correct);
+ REQUIRE(c_2_1 == c_2_1_correct);
+ REQUIRE(c_2_2 == c_2_2_correct);
+ }
+
+
+}
diff --git a/matching/tests/tests_main.cpp b/matching/tests/tests_main.cpp
new file mode 100644
index 0000000..1c77b13
--- /dev/null
+++ b/matching/tests/tests_main.cpp
@@ -0,0 +1,2 @@
+#define CATCH_CONFIG_MAIN
+#include "catch/catch.hpp"
diff --git a/wasserstein/CMakeLists.txt b/wasserstein/CMakeLists.txt
new file mode 100644
index 0000000..dea4550
--- /dev/null
+++ b/wasserstein/CMakeLists.txt
@@ -0,0 +1,62 @@
+project (wasserstein)
+cmake_minimum_required (VERSION 3.5.1)
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+include (GenerateExportHeader)
+
+include(TestBigEndian)
+test_big_endian(BIG_ENDIAN)
+if(BIG_ENDIAN)
+ add_definitions(-DBIGENDIAN)
+endif()
+
+# Default to Release
+
+if (NOT CMAKE_BUILD_TYPE)
+ set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
+endif (NOT CMAKE_BUILD_TYPE)
+
+# Boost
+find_package (Boost)
+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include
+ SYSTEM ${Boost_INCLUDE_DIR})
+
+if(NOT WIN32)
+ add_definitions(-std=c++14)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -D_GLIBCXX_DEBUG")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 ")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -O2 -g -ggdb")
+endif(NOT WIN32)
+
+file(GLOB WS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp)
+
+#add_library(wasserstein ${WS_SOURCES})
+
+#if (WIN32)
+ #GENERATE_EXPORT_HEADER(wasserstein
+ #BASE_NAME wasserstein
+ #EXPORT_MACRO_NAME wasserstein_EXPORT
+ #EXPORT_FILE_NAME wasserstein_export.h
+ #STATIC_DEFINE wasserstein_BUILT_AS_STATIC)
+#endif(WIN32)
+
+find_package (Threads)
+set (libraries ${libraries} ${CMAKE_THREAD_LIBS_INIT})
+
+add_executable(wasserstein_dist ${CMAKE_CURRENT_SOURCE_DIR}/example/wasserstein_dist.cpp ${WS_HEADERS} include/hera_infinity.h)
+target_link_libraries(wasserstein_dist PUBLIC ${libraries})
+
+add_executable(wasserstein_dist_dipha ${CMAKE_CURRENT_SOURCE_DIR}/example/wasserstein_dist_dipha.cpp ${WS_HEADERS} include/hera_infinity.h)
+target_link_libraries(wasserstein_dist_dipha PUBLIC ${libraries})
+
+# pure geometric version, arbitrary dimension
+add_executable(wasserstein_dist_point_cloud ${CMAKE_CURRENT_SOURCE_DIR}/example/wasserstein_dist_point_cloud.cpp ${WS_HEADERS} include/hera_infinity.h)
+target_link_libraries(wasserstein_dist_point_cloud PUBLIC ${libraries})
+
+# Tests
+add_executable(wasserstein_test ${CMAKE_CURRENT_SOURCE_DIR}/tests/tests_main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_hera_wasserstein.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_hera_wasserstein_pure_geom.cpp include/hera_infinity.h tests/tests_reader.h)
+#add_executable(wasserstein_test EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_hera_wasserstein.cpp)
+target_link_libraries(wasserstein_test PUBLIC ${libraries})
diff --git a/wasserstein/README b/wasserstein/README
new file mode 100644
index 0000000..5228d63
--- /dev/null
+++ b/wasserstein/README
@@ -0,0 +1,100 @@
+This is a program for computing Wasserstein distances between persistence
+diagrams using the geometric version of auction algorithm.
+
+Accompanying paper: M. Kerber, D. Morozov, A. Nigmetov. Geometry Helps To Compare
+Persistence Diagrams (ALENEX 2016, http://www.geometrie.tugraz.at/nigmetov/geom_dist.pdf)
+Bug reports can be sent to "nigmetov EMAIL SIGN tugraz DOT at".
+
+Wasserstein distance $W_{q, p}(X, Y)$ between two persistent diagrams is
+the minimum over all perfect matchings between $X$ and $Y$ ( $y(x)$ is the point of $Y$
+matched to $x \in X$ ) of the following expression:
+$ ( \sum \| x - y(x) \|_p ^ { q } ) ^ { 1 / q} $
+
+# Dependencies
+
+Requires boost 1.58 or higher.
+Your compiler must support C++11.
+
+# Usage:
+
+To use a standalone command-line utility wasserstein_dist:
+
+wasserstein_dist file1 file2 [wasserstein degree] [relative error] [internal norm].
+
+Parameter wasserstein degree corresponds to $q$, when it tends to infinity,
+Wasserstein distance tends to the bottleneck distance.
+
+If two diagrams are equal, then the exact distance 0.0 is printed (the order
+of points in file1 and file2 need not be the same).
+Otherwise the output is an approximation of the exact distance. Precisely:
+if d_exact is the true distance and d_approx is the output, then
+
+ | d_exact - d_approx | / d_exact < relative_error.
+
+Parameter internal_p corresponds to p.
+
+Default values:
+wasserstein_degree = 1.0,
+relative_error = 0.01,
+internal_p = infinity.
+
+Valid values:
+wasserstein_degree must be in $[1.0, \infinity)$,
+relative_error must be positive,
+internal_p must be in $[1.0, \infinity]$ (to explicitly set internal_p to $\infinity$, supply inf).By default wasserstein degree is 1.0, relative error is 0.01, internal norm is l_infinity.
+
+file1 and file2 must contain persistence diagrams in plain text format
+(one point per line, empty lines are ignored, comments can be made with #):
+
+# this is how your input can look like
+x_1 y_1 # two real numbers per line
+...
+# empty lines or comments are ignored
+x_n y_n
+
+To use from your code:
+
+#include "wasserstein.h"
+
+// All classes and functions are in geom_ws namespace
+
+std::vector<std::pair<double, double>> diagram1, diagram2;
+// any container class that supports range-for loops will do.
+// A pair represents a single point,
+// first component = x-coordinate,
+// second component = y-coordinate.
+// ...
+// load your diagrams into diagram1, diagram2 (off-diagonal points).
+// You can use function readDiagramPointSet:
+geom_ws::readDiagramPointSet("diagram1.txt", diagram1);
+geom_ws::readDiagramPointSet("diagram2.txt", diagram1);
+// ...
+// to get the distance:
+double wsDist = geom_ws::wassersteinDist(diagram1, diagram2, q, delta, p);
+// q is wasserstein degree, delta is relative error,
+// p is the internal norm in Wasserstein distance, defaults to infinity
+
+Necessary projections (diagonal points) will be added in the wassersteinDist
+function.
+
+See also code in wasserstein/example/wasserstein_dist.cpp.
+
+# License
+
+See ../license.txt
+
+# Building
+
+CMakeLists.txt in the root directory can be used to make the library (contained
+in wasserstein/src/ directory) and the command-line utility (in wasserstein/example/ directory)
+to compute the distance between two diagrams in txt files.
+
+On Linux/Mac:
+
+mkdir build
+cd build
+cmake ..
+make
+
+On Windows (checked with Visual Studio 2015, Community version)
+use cmake-gui to create the solution in build directory and build it with VS.
diff --git a/wasserstein/example/wasserstein_dist.cpp b/wasserstein/example/wasserstein_dist.cpp
new file mode 100644
index 0000000..cbe83e2
--- /dev/null
+++ b/wasserstein/example/wasserstein_dist.cpp
@@ -0,0 +1,156 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#include <iostream>
+#include <locale>
+#include <iomanip>
+#include <vector>
+
+#include "opts/opts.h"
+
+//#define LOG_AUCTION
+
+//#include "auction_runner_fr.h"
+//#include "auction_runner_fr.hpp"
+
+#include "wasserstein.h"
+
+// any container of pairs of Reals can be used,
+// we use vector in this example.
+
+int main(int argc, char* argv[])
+{
+ using Real = double;
+ using PairVector = std::vector<std::pair<Real, Real>>;
+ PairVector diagramA, diagramB;
+
+ hera::AuctionParams<Real> params;
+ params.max_num_phases = 800;
+
+ opts::Options ops(argc, argv);
+ ops >> opts::Option('q', "degree", params.wasserstein_power, "Wasserstein degree")
+ >> opts::Option('d', "error", params.delta, "Relative error")
+ >> opts::Option('p', "internal-p", params.internal_p, "Internal norm")
+ >> opts::Option("initial-epsilon", params.initial_epsilon, "Initial epsilon")
+ >> opts::Option("epsilon-factor", params.epsilon_common_ratio, "Epsilon factor")
+ >> opts::Option("max-bids-per-round", params.max_bids_per_round, "Maximal number of bids per round")
+ >> opts::Option('m', "max-rounds", params.max_num_phases, "Maximal number of iterations");
+
+
+ bool print_relative_error = ops >> opts::Present('e', "--print-error", "Print real relative error");
+
+ params.tolerate_max_iter_exceeded = ops >> opts::Present('t', "tolerate", "Suppress max-iterations-exceeded error and print the best result.");
+
+ std::string dgm_fname_1, dgm_fname_2;
+ bool dgm_1_given = (ops >> opts::PosOption(dgm_fname_1));
+ bool dgm_2_given = (ops >> opts::PosOption(dgm_fname_2));
+
+ //std::cout << "q = " << params.wasserstein_power << ", delta = " << params.delta << ", p = " << params.internal_p << ", max_round = " << params.max_num_phases << std::endl;
+ //std::cout << "print relative error: " << print_relative_error << std::endl;
+ //std::cout << "dgm1: " << dgm_fname_1 << std::endl;
+ //std::cout << "dgm2: " << dgm_fname_2 << std::endl;
+
+ if (not dgm_1_given or not dgm_2_given) {
+ std::cerr << "Usage: " << argv[0] << " file1 file2 " << std::endl;
+ std::cerr << "compute Wasserstein distance between persistence diagrams in file1 and file2.\n";
+ std::cerr << ops << std::endl;
+ return 1;
+ }
+
+ if (ops >> opts::Present('h', "help", "show help message")) {
+ std::cout << "Usage: " << argv[0] << " file1 file2 " << std::endl;
+ std::cout << "compute Wasserstein distance between persistence diagrams in file1 and file2.\n";
+ std::cout << ops << std::endl;
+ }
+
+ if (!hera::read_diagram_point_set<Real, PairVector>(dgm_fname_1, diagramA)) {
+ std::exit(1);
+ }
+
+ if (!hera::read_diagram_point_set(dgm_fname_2, diagramB)) {
+ std::exit(1);
+ }
+
+ if (params.wasserstein_power < 1.0) {
+ std::cerr << "Wasserstein_degree was \"" << params.wasserstein_power << "\", must be a number >= 1.0. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ if (params.wasserstein_power == 1.0) {
+ hera::remove_duplicates<Real>(diagramA, diagramB);
+ }
+
+ //default relative error: 1%
+ if ( params.delta <= 0.0) {
+ std::cerr << "relative error was \"" << params.delta << "\", must be a number > 0.0. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ // default for internal metric is l_infinity
+ if (std::isinf(params.internal_p)) {
+ params.internal_p = hera::get_infinity<Real>();
+ }
+
+
+ if (not hera::is_p_valid_norm<Real>(params.internal_p)) {
+ std::cerr << "internal-p was \"" << params.internal_p << "\", must be a number >= 1.0 or inf. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ // if you want to specify initial value for epsilon and the factor
+ // for epsilon-scaling
+ if (params.initial_epsilon < 0.0) {
+ std::cerr << "initial-epsilon was \"" << params.initial_epsilon << "\", must be a non-negative number. Cannot proceed." << std::endl;
+ std::exit(1);
+ }
+
+ if (params.epsilon_common_ratio <= 1.0 and params.epsilon_common_ratio != 0.0) {
+ std::cerr << "The 7th argument (epsilon factor) was \"" << params.epsilon_common_ratio << "\", must be a number greater than 1. Cannot proceed." << std::endl;
+ std::exit(1);
+ }
+
+ if (params.max_bids_per_round == 0)
+ params.max_bids_per_round = std::numeric_limits<decltype(params.max_bids_per_round)>::max();
+
+
+ std::string log_filename_prefix = ( 11 <= argc ) ? argv[10] : "";
+
+
+#ifdef LOG_AUCTION
+ spdlog::set_level(spdlog::level::info);
+#endif
+
+ Real res = hera::wasserstein_dist(diagramA, diagramB, params, log_filename_prefix);
+
+ std::cout << std::setprecision(15) << res << std::endl;
+ if (print_relative_error)
+ std::cout << "Relative error: " << params.final_relative_error << std::endl;
+
+ return 0;
+
+}
diff --git a/wasserstein/example/wasserstein_dist_dipha.cpp b/wasserstein/example/wasserstein_dist_dipha.cpp
new file mode 100644
index 0000000..2ed9c2c
--- /dev/null
+++ b/wasserstein/example/wasserstein_dist_dipha.cpp
@@ -0,0 +1,133 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+Copyright (c) 2018, G. Spreemann
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#include <iostream>
+#include <locale>
+#include <iomanip>
+#include <vector>
+
+//#define LOG_AUCTION
+
+//#include "auction_runner_fr.h"
+//#include "auction_runner_fr.hpp"
+
+#include "wasserstein.h"
+
+// any container of pairs of doubles can be used,
+// we use vector in this example.
+
+int main(int argc, char* argv[])
+{
+ using PairVector = std::vector<std::pair<double, double>>;
+ PairVector diagramA, diagramB;
+
+ hera::AuctionParams<double> params;
+
+ if (argc < 4 ) {
+ std::cerr << "Usage: " << argv[0] << " file1 file2 ph_dim [wasserstein_degree] [relative_error] [internal norm] [initial epsilon] [epsilon_factor] [max_bids_per_round] [gamma_threshold][log_filename_prefix]. By default power is 1.0, relative error is 0.01, internal norm is l_infinity, initall epsilon is chosen automatically, epsilon factor is 5.0, Jacobi variant is used (max bids per round is maximal), gamma_threshold = 0.0." << std::endl;
+ return 1;
+ }
+
+ unsigned int dim = std::stoul(argv[3]);
+
+ if (!hera::read_diagram_dipha<double, PairVector>(argv[1], dim, diagramA)) {
+ std::exit(1);
+ }
+
+ if (!hera::read_diagram_dipha<double, PairVector>(argv[2], dim, diagramB)) {
+ std::exit(1);
+ }
+
+ params.wasserstein_power = (5 <= argc) ? atof(argv[4]) : 1.0;
+ if (params.wasserstein_power < 1.0) {
+ std::cerr << "The third argument (wasserstein_degree) was \"" << argv[4] << "\", must be a number >= 1.0. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ if (params.wasserstein_power == 1.0) {
+ hera::remove_duplicates<double>(diagramA, diagramB);
+ }
+
+ //default relative error: 1%
+ params.delta = (6 <= argc) ? atof(argv[5]) : 0.01;
+ if ( params.delta <= 0.0) {
+ std::cerr << "The 4th argument (relative error) was \"" << argv[5] << "\", must be a number > 0.0. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ // default for internal metric is l_infinity
+ params.internal_p = ( 7 <= argc ) ? atof(argv[6]) : hera::get_infinity<double>();
+ if (std::isinf(params.internal_p)) {
+ params.internal_p = hera::get_infinity<double>();
+ }
+
+
+ if (not hera::is_p_valid_norm<double>(params.internal_p)) {
+ std::cerr << "The 6th argument (internal norm) was \"" << argv[6] << "\", must be a number >= 1.0 or inf. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ // if you want to specify initial value for epsilon and the factor
+ // for epsilon-scaling
+ params.initial_epsilon= ( 8 <= argc ) ? atof(argv[7]) : 0.0 ;
+
+ if (params.initial_epsilon < 0.0) {
+ std::cerr << "The 7th argument (initial epsilon) was \"" << argv[7] << "\", must be a non-negative number. Cannot proceed." << std::endl;
+ std::exit(1);
+ }
+
+ params.epsilon_common_ratio = ( 9 <= argc ) ? atof(argv[8]) : 0.0 ;
+ if (params.epsilon_common_ratio <= 1.0 and params.epsilon_common_ratio != 0.0) {
+ std::cerr << "The 8th argument (epsilon factor) was \"" << argv[8] << "\", must be a number greater than 1. Cannot proceed." << std::endl;
+ std::exit(1);
+ }
+
+
+ params.max_bids_per_round = ( 10 <= argc ) ? atoi(argv[9]) : 0;
+ if (params.max_bids_per_round == 0)
+ params.max_bids_per_round = std::numeric_limits<decltype(params.max_bids_per_round)>::max();
+
+
+ params.gamma_threshold = (11 <= argc) ? atof(argv[10]) : 0.0;
+
+ std::string log_filename_prefix = ( 12 <= argc ) ? argv[11] : "";
+
+ params.max_num_phases = 800;
+
+#ifdef LOG_AUCTION
+ spdlog::set_level(spdlog::level::info);
+#endif
+
+ double res = hera::wasserstein_dist(diagramA, diagramB, params, log_filename_prefix);
+
+ std::cout << std::setprecision(15) << res << std::endl;
+
+ return 0;
+
+}
diff --git a/wasserstein/example/wasserstein_dist_point_cloud.cpp b/wasserstein/example/wasserstein_dist_point_cloud.cpp
new file mode 100644
index 0000000..ab7ff4f
--- /dev/null
+++ b/wasserstein/example/wasserstein_dist_point_cloud.cpp
@@ -0,0 +1,175 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#include <iostream>
+#include <locale>
+#include <iomanip>
+#include <vector>
+
+#include "wasserstein_pure_geom.hpp"
+
+int main(int argc, char* argv[])
+{
+
+ //{
+ //int n_points = 3;
+ //int dim = 3;
+ //using Traits = hera::ws::dnn::DynamicPointTraits<double>;
+ //hera::ws::dnn::DynamicPointTraits<double> traits(dim);
+ //hera::ws::dnn::DynamicPointVector<double> dgm_a = traits.container(n_points);
+ //hera::ws::dnn::DynamicPointVector<double> dgm_b = traits.container(n_points);
+
+ //dgm_a[0][0] = 0.0;
+ //dgm_a[0][1] = 0.0;
+ //dgm_a[0][2] = 0.0;
+
+ //dgm_a[1][0] = 1.0;
+ //dgm_a[1][1] = 0.0;
+ //dgm_a[1][2] = 0.0;
+
+ //dgm_a[2][0] = 0.0;
+ //dgm_a[2][1] = 1.0;
+ //dgm_a[2][2] = 1.0;
+
+ //dgm_b[0][0] = 0.0;
+ //dgm_b[0][1] = 0.1;
+ //dgm_b[0][2] = 0.1;
+
+ //dgm_b[1][0] = 1.1;
+ //dgm_b[1][1] = 0.0;
+ //dgm_b[1][2] = 0.0;
+
+ //dgm_b[2][0] = 0.0;
+ //dgm_b[2][1] = 1.1;
+ //dgm_b[2][2] = 0.9;
+
+
+ //hera::AuctionParams<double> params;
+ //params.dim = dim;
+
+
+ //std::cout << hera::ws::wasserstein_cost(dgm_a, dgm_b, params) << std::endl;
+
+ //return 0;
+ //}
+
+
+ using Real = double;
+ using PointVector = hera::ws::dnn::DynamicPointVector<Real>;
+ PointVector set_A, set_B;
+
+ hera::AuctionParams<Real> params;
+
+ if (argc < 3 ) {
+ std::cerr << "Usage: " << argv[0] << " file1 file2 [wasserstein_degree] [relative_error] [internal norm] [initial epsilon] [epsilon_factor] [max_bids_per_round] [gamma_threshold][log_filename_prefix]. By default power is 1.0, relative error is 0.01, internal norm is l_infinity, initall epsilon is chosen automatically, epsilon factor is 5.0, Jacobi variant is used (max bids per round is maximal), gamma_threshold = 0.0." << std::endl;
+ return 1;
+ }
+
+ int dimension_A, dimension_B;
+
+ if (!hera::read_point_cloud<Real>(argv[1], set_A, dimension_A)) {
+ std::exit(1);
+ }
+
+ if (!hera::read_point_cloud(argv[2], set_B, dimension_B)) {
+ std::exit(1);
+ }
+
+ if (dimension_A != dimension_B) {
+ std::cerr << "Dimension mismatch: " << dimension_A << " != " << dimension_B << std::endl;
+ std::exit(1);
+ }
+
+ params.dim = dimension_A;
+
+ params.wasserstein_power = (4 <= argc) ? atof(argv[3]) : 1.0;
+ if (params.wasserstein_power < 1.0) {
+ std::cerr << "The third argument (wasserstein_degree) was \"" << argv[3] << "\", must be a number >= 1.0. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ //if (params.wasserstein_power == 1.0) {
+ // hera::remove_duplicates<double?(set_A, set_B);
+ //}
+
+ //default relative error: 1%
+ params.delta = (5 <= argc) ? atof(argv[4]) : 0.01;
+ if ( params.delta <= 0.0) {
+ std::cerr << "The 4th argument (relative error) was \"" << argv[4] << "\", must be a number > 0.0. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ // default for internal metric is l_infinity
+ params.internal_p = ( 6 <= argc ) ? atof(argv[5]) : hera::get_infinity<Real>();
+ if (std::isinf(params.internal_p)) {
+ params.internal_p = hera::get_infinity<Real>();
+ }
+
+
+ if (not hera::is_p_valid_norm<Real>(params.internal_p)) {
+ std::cerr << "The 5th argument (internal norm) was \"" << argv[5] << "\", must be a number >= 1.0 or inf. Cannot proceed. " << std::endl;
+ std::exit(1);
+ }
+
+ // if you want to specify initial value for epsilon and the factor
+ // for epsilon-scaling
+ params.initial_epsilon= ( 7 <= argc ) ? atof(argv[6]) : 0.0 ;
+
+ if (params.initial_epsilon < 0.0) {
+ std::cerr << "The 6th argument (initial epsilon) was \"" << argv[6] << "\", must be a non-negative number. Cannot proceed." << std::endl;
+ std::exit(1);
+ }
+
+ params.epsilon_common_ratio = ( 8 <= argc ) ? atof(argv[7]) : 0.0 ;
+ if (params.epsilon_common_ratio <= 1.0 and params.epsilon_common_ratio != 0.0) {
+ std::cerr << "The 7th argument (epsilon factor) was \"" << argv[7] << "\", must be a number greater than 1. Cannot proceed." << std::endl;
+ std::exit(1);
+ }
+
+
+ params.max_bids_per_round = ( 9 <= argc ) ? atoi(argv[8]) : 0;
+ if (params.max_bids_per_round == 0)
+ params.max_bids_per_round = std::numeric_limits<decltype(params.max_bids_per_round)>::max();
+
+
+ params.gamma_threshold = (10 <= argc) ? atof(argv[9]) : 0.0;
+
+ std::string log_filename_prefix = ( 11 <= argc ) ? argv[10] : "";
+
+ params.max_num_phases = 800;
+
+#ifdef LOG_AUCTION
+ spdlog::set_level(spdlog::level::critical);
+#endif
+
+ Real res = hera::ws::wasserstein_dist(set_A, set_B, params);
+
+ std::cout << std::setprecision(15) << res << std::endl;
+
+ return 0;
+}
diff --git a/wasserstein/include/auction_oracle.h b/wasserstein/include/auction_oracle.h
new file mode 100644
index 0000000..d285a1f
--- /dev/null
+++ b/wasserstein/include/auction_oracle.h
@@ -0,0 +1,40 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef HERA_AUCTION_ORACLE_H
+#define HERA_AUCTION_ORACLE_H
+
+// all oracle classes are in separate h-hpp files
+// this file comprises all of them
+
+#include "auction_oracle_base.h"
+#include "auction_oracle_kdtree_restricted.h"
+#include "auction_oracle_kdtree_single_diag.h"
+#include "auction_oracle_stupid_sparse_restricted.h"
+
+#endif // HERA_AUCTION_ORACLE_H
diff --git a/wasserstein/include/auction_oracle_base.h b/wasserstein/include/auction_oracle_base.h
new file mode 100644
index 0000000..08eaf00
--- /dev/null
+++ b/wasserstein/include/auction_oracle_base.h
@@ -0,0 +1,85 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_BASE_H
+#define AUCTION_ORACLE_BASE_H
+
+#include <map>
+#include <memory>
+#include <set>
+#include <list>
+
+#include "basic_defs_ws.h"
+
+namespace hera {
+namespace ws {
+
+
+template <class Real>
+struct DebugOptimalBid {
+ DebugOptimalBid() : best_item_idx(k_invalid_index), best_item_value(-666.666), second_best_item_idx(k_invalid_index), second_best_item_value(-666.666) {};
+ IdxType best_item_idx;
+ Real best_item_value;
+ IdxType second_best_item_idx;
+ Real second_best_item_value;
+};
+
+template <class Real = double, class PointContainer_ = std::vector<DiagramPoint<Real>>>
+struct AuctionOracleBase {
+ AuctionOracleBase(const PointContainer_& _bidders, const PointContainer_& _items, const AuctionParams<Real>& params);
+ ~AuctionOracleBase() {}
+ Real get_epsilon() const { return epsilon; };
+ void set_epsilon(Real new_epsilon) { assert(new_epsilon >= 0.0); epsilon = new_epsilon; };
+ const std::vector<Real>& get_prices() const { return prices; }
+ virtual Real get_price(const size_t item_idx) const { return prices[item_idx]; } // TODO make virtual?
+//protected:
+ const PointContainer_& bidders;
+ const PointContainer_& items;
+ const size_t num_bidders_;
+ const size_t num_items_;
+ std::vector<Real> prices;
+ const Real wasserstein_power;
+ Real epsilon;
+ const Real internal_p;
+ unsigned int dim; // used only in pure geometric version, not for persistence diagrams
+ Real get_value_for_bidder(size_t bidder_idx, size_t item_idx) const;
+ Real get_value_for_diagonal_bidder(size_t item_idx) const;
+ Real get_cost_for_diagonal_bidder(size_t item_idx) const;
+};
+
+
+template<class Real>
+std::ostream& operator<< (std::ostream& output, const DebugOptimalBid<Real>& db);
+
+} // ws
+} // hera
+
+
+#include "auction_oracle_base.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_oracle_base.hpp b/wasserstein/include/auction_oracle_base.hpp
new file mode 100644
index 0000000..b74c7fb
--- /dev/null
+++ b/wasserstein/include/auction_oracle_base.hpp
@@ -0,0 +1,97 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_BASE_HPP
+#define AUCTION_ORACLE_BASE_HPP
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "auction_oracle.h"
+
+
+#ifdef FOR_R_TDA
+#undef DEBUG_AUCTION
+#endif
+
+namespace hera {
+namespace ws {
+
+template<class Real, class PointContainer>
+AuctionOracleBase<Real, PointContainer>::AuctionOracleBase(const PointContainer& _bidders,
+ const PointContainer& _items,
+ const AuctionParams<Real>& params) :
+ bidders(_bidders),
+ items(_items),
+ num_bidders_(_bidders.size()),
+ num_items_(_items.size()),
+ prices(items.size(), Real(0.0)),
+ wasserstein_power(params.wasserstein_power),
+ internal_p(params.internal_p),
+ dim(params.dim)
+{
+ assert(bidders.size() == items.size() );
+}
+
+
+template<class Real, class PointContainer>
+Real AuctionOracleBase<Real, PointContainer>::get_value_for_bidder(size_t bidder_idx, size_t item_idx) const
+{
+ return std::pow(dist_lp<Real>(bidders[bidder_idx], items[item_idx], internal_p, dim), wasserstein_power) + get_price(item_idx);
+}
+
+template<class Real, class PointContainer>
+Real AuctionOracleBase<Real, PointContainer>::get_value_for_diagonal_bidder(size_t item_idx) const
+{
+ return get_cost_for_diagonal_bidder(item_idx) + get_price(item_idx);
+}
+
+template<class Real, class PointContainer>
+Real AuctionOracleBase<Real, PointContainer>::get_cost_for_diagonal_bidder(size_t item_idx) const
+{
+ return std::pow(items[item_idx].persistence_lp(internal_p), wasserstein_power);
+}
+
+
+
+template<class Real>
+std::ostream& operator<< (std::ostream& output, const DebugOptimalBid<Real>& db)
+{
+ output << "best_item_value = " << db.best_item_value;
+ output << "; best_item_idx = " << db.best_item_idx;
+ output << "; second_best_item_value = " << db.second_best_item_value;
+ output << "; second_best_item_idx = " << db.second_best_item_idx;
+ return output;
+}
+
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/auction_oracle_kdtree_pure_geom.h b/wasserstein/include/auction_oracle_kdtree_pure_geom.h
new file mode 100644
index 0000000..ebfab3b
--- /dev/null
+++ b/wasserstein/include/auction_oracle_kdtree_pure_geom.h
@@ -0,0 +1,94 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_KDTREE_PURE_GEOM_H
+#define AUCTION_ORACLE_KDTREE_PURE_GEOM_H
+
+
+#include <map>
+#include <memory>
+#include <set>
+
+#include <boost/range/adaptor/transformed.hpp>
+
+namespace ba = boost::adaptors;
+
+#include "basic_defs_ws.h"
+#include "auction_oracle_base.h"
+#include "dnn/geometry/euclidean-dynamic.h"
+#include "dnn/local/kd-tree.h"
+
+namespace hera
+{
+namespace ws
+{
+
+template <class Real_ = double, class PointContainer_ = hera::ws::dnn::DynamicPointVector<Real_>>
+struct AuctionOracleKDTreePureGeom : AuctionOracleBase<Real_, PointContainer_> {
+
+ using Real = Real_;
+ using DynamicPointTraitsR = typename hera::ws::dnn::DynamicPointTraits<Real>;
+ using DiagramPointR = typename DynamicPointTraitsR::PointType;
+ using PointHandleR = typename DynamicPointTraitsR::PointHandle;
+ using PointContainer = PointContainer_;
+ using DebugOptimalBidR = typename ws::DebugOptimalBid<Real>;
+
+ using DynamicPointTraits = hera::ws::dnn::DynamicPointTraits<Real>;
+ using KDTreeR = hera::ws::dnn::KDTree<DynamicPointTraits>;
+
+ AuctionOracleKDTreePureGeom(const PointContainer& bidders, const PointContainer& items, const AuctionParams<Real>& params);
+ ~AuctionOracleKDTreePureGeom();
+
+ // data members
+ // temporarily make everything public
+ DynamicPointTraits traits;
+ Real max_val_;
+ Real weight_adj_const_;
+ std::unique_ptr<KDTreeR> kdtree_;
+ std::vector<size_t> kdtree_items_;
+ // methods
+ void set_price(const IdxType items_idx, const Real new_price);
+ IdxValPair<Real> get_optimal_bid(const IdxType bidder_idx);
+ void adjust_prices();
+ void adjust_prices(const Real delta);
+
+ // debug routines
+ DebugOptimalBidR get_optimal_bid_debug(IdxType bidder_idx) const;
+ void sanity_check();
+
+ std::pair<Real, Real> get_minmax_price() const;
+
+};
+
+} // ws
+} // hera
+
+
+#include "auction_oracle_kdtree_pure_geom.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_oracle_kdtree_pure_geom.hpp b/wasserstein/include/auction_oracle_kdtree_pure_geom.hpp
new file mode 100644
index 0000000..4ee7b45
--- /dev/null
+++ b/wasserstein/include/auction_oracle_kdtree_pure_geom.hpp
@@ -0,0 +1,225 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+#ifndef AUCTION_ORACLE_KDTREE_PURE_GEOM_HPP
+#define AUCTION_ORACLE_KDTREE_PURE_GEOM_HPP
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "auction_oracle_kdtree_restricted.h"
+
+
+#ifdef FOR_R_TDA
+#undef DEBUG_AUCTION
+#endif
+
+namespace hera {
+namespace ws {
+
+
+// *****************************
+// AuctionOracleKDTreePureGeom
+// *****************************
+
+
+
+template <class Real_, class PointContainer_>
+std::ostream& operator<<(std::ostream& output, const AuctionOracleKDTreePureGeom<Real_, PointContainer_>& oracle)
+{
+ output << "Oracle " << &oracle << std::endl;
+ output << "max_val_ = " << oracle.max_val_ << "\n";
+ output << "prices = " << format_container_to_log(oracle.prices) << "\n";
+ output << "end of oracle " << &oracle << std::endl;
+ return output;
+}
+
+
+template<class Real_, class PointContainer_>
+AuctionOracleKDTreePureGeom<Real_, PointContainer_>::AuctionOracleKDTreePureGeom(const PointContainer_& _bidders,
+ const PointContainer_& _items,
+ const AuctionParams<Real_>& params) :
+ AuctionOracleBase<Real_, PointContainer_>(_bidders, _items, params),
+ traits(params.dim)
+{
+
+ traits.internal_p = params.internal_p;
+
+ std::vector<PointHandleR> item_handles(this->num_items_);
+ for(size_t i = 0; i < this->num_items_; ++i) {
+ item_handles[i] = traits.handle(this->items[i]);
+ }
+
+ //kdtree_ = std::unique_ptr<KDTreeR>(new KDTreeR(traits,
+ // this->items | ba::transformed([this](const DiagramPointR& p) { return traits.handle(p); }),
+ // params.wasserstein_power));
+
+ kdtree_ = std::unique_ptr<KDTreeR>(new KDTreeR(traits, item_handles, params.wasserstein_power));
+
+
+ max_val_ = 3*getFurthestDistance3Approx_pg(this->bidders, this->items, params.internal_p, params.dim);
+ max_val_ = std::pow(max_val_, params.wasserstein_power);
+ weight_adj_const_ = max_val_;
+}
+
+
+template<class Real_, class PointContainer_>
+typename AuctionOracleKDTreePureGeom<Real_, PointContainer_>::DebugOptimalBidR
+AuctionOracleKDTreePureGeom<Real_, PointContainer_>::get_optimal_bid_debug(IdxType bidder_idx) const
+{
+ auto bidder = this->bidders[bidder_idx];
+
+ size_t best_item_idx = k_invalid_index;
+ size_t second_best_item_idx = k_invalid_index;
+ Real best_item_value = std::numeric_limits<Real>::max();
+ Real second_best_item_value = std::numeric_limits<Real>::max();
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ auto item = this->items[item_idx];
+ auto item_value = std::pow(traits.distance(bidder, item), this->wasserstein_power) + this->prices[item_idx];
+ if (item_value < best_item_value) {
+ best_item_value = item_value;
+ best_item_idx = item_idx;
+ }
+ }
+
+ assert(best_item_idx != k_invalid_index);
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ auto item = this->items[item_idx];
+ if (item_idx == best_item_idx)
+ continue;
+
+ auto item_value = std::pow(traits.distance(bidder, item), this->wasserstein_power) + this->prices[item_idx];
+ if (item_value < second_best_item_value) {
+ second_best_item_value = item_value;
+ second_best_item_idx = item_idx;
+ }
+ }
+
+ assert(second_best_item_idx != k_invalid_index);
+ assert(second_best_item_value >= best_item_value);
+
+ DebugOptimalBidR result;
+
+ result.best_item_idx = best_item_idx;
+ result.best_item_value = best_item_value;
+ result.second_best_item_idx = second_best_item_idx;
+ result.second_best_item_value = second_best_item_value;
+
+ return result;
+}
+
+
+template<class Real_, class PointContainer_>
+IdxValPair<Real_> AuctionOracleKDTreePureGeom<Real_, PointContainer_>::get_optimal_bid(IdxType bidder_idx)
+{
+ auto two_best_items = kdtree_->findK(this->bidders[bidder_idx], 2);
+ size_t best_item_idx = traits.id(two_best_items[0].p);
+ Real best_item_value = two_best_items[0].d;
+ Real second_best_item_value = two_best_items[1].d;
+
+ IdxValPair<Real> result;
+
+ assert( second_best_item_value >= best_item_value );
+
+ result.first = best_item_idx;
+ result.second = ( second_best_item_value - best_item_value ) + this->prices[best_item_idx] + this->epsilon;
+
+#ifdef DEBUG_KDTREE_RESTR_ORACLE
+ auto bid_debug = get_optimal_bid_debug(bidder_idx);
+ assert(fabs(bid_debug.best_item_value - best_item_value) < 0.000000001);
+ assert(fabs(bid_debug.second_best_item_value - second_best_item_value) < 0.000000001);
+#endif
+
+ return result;
+}
+
+/*
+a_{ij} = d_{ij}
+value_{ij} = a_{ij} + price_j
+*/
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreePureGeom<Real_, PointContainer_>::set_price(IdxType item_idx,
+ Real new_price)
+{
+ assert(this->prices.size() == this->items.size());
+ // adjust_prices decreases prices,
+ // also this variable must be true in reverse phases of FR-auction
+
+ this->prices[item_idx] = new_price;
+ kdtree_->change_weight( traits.handle(this->items[item_idx]), new_price);
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreePureGeom<Real_, PointContainer_>::adjust_prices(Real delta)
+{
+ if (delta == 0.0)
+ return;
+
+ for(auto& p : this->prices) {
+ p -= delta;
+ }
+
+ kdtree_->adjust_weights(delta);
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreePureGeom<Real_, PointContainer_>::adjust_prices()
+{
+ auto pr_begin = this->prices.begin();
+ auto pr_end = this->prices.end();
+ Real min_price = *(std::min_element(pr_begin, pr_end));
+ adjust_prices(min_price);
+}
+
+template<class Real_, class PointContainer_>
+std::pair<Real_, Real_> AuctionOracleKDTreePureGeom<Real_, PointContainer_>::get_minmax_price() const
+{
+ auto r = std::minmax_element(this->prices.begin(), this->prices.end());
+ return std::make_pair(*r.first, *r.second);
+}
+
+template<class Real_, class PointContainer_>
+AuctionOracleKDTreePureGeom<Real_, PointContainer_>::~AuctionOracleKDTreePureGeom()
+{
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreePureGeom<Real_, PointContainer_>::sanity_check()
+{
+}
+
+
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/auction_oracle_kdtree_restricted.h b/wasserstein/include/auction_oracle_kdtree_restricted.h
new file mode 100644
index 0000000..b17089b
--- /dev/null
+++ b/wasserstein/include/auction_oracle_kdtree_restricted.h
@@ -0,0 +1,119 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_KDTREE_RESTRICTED_H
+#define AUCTION_ORACLE_KDTREE_RESTRICTED_H
+
+
+//#define USE_BOOST_HEAP
+
+#include <map>
+#include <memory>
+#include <set>
+
+
+#include "basic_defs_ws.h"
+#include "diagonal_heap.h"
+#include "auction_oracle_base.h"
+#include "dnn/geometry/euclidean-fixed.h"
+#include "dnn/local/kd-tree.h"
+
+namespace hera {
+namespace ws {
+
+template <class Real_ = double, class PointContainer_ = std::vector<DiagramPoint<Real_>>>
+struct AuctionOracleKDTreeRestricted : AuctionOracleBase<Real_, PointContainer_> {
+
+ using PointContainer = PointContainer_;
+ using Real = Real_;
+
+ using LossesHeapR = typename ws::LossesHeapOld<Real>;
+ using LossesHeapRHandle = typename ws::LossesHeapOld<Real>::handle_type;
+ using DiagramPointR = typename ws::DiagramPoint<Real>;
+ using DebugOptimalBidR = typename ws::DebugOptimalBid<Real>;
+
+ using DnnPoint = dnn::Point<2, Real>;
+ using DnnTraits = dnn::PointTraits<DnnPoint>;
+
+ AuctionOracleKDTreeRestricted(const PointContainer& bidders, const PointContainer& items, const AuctionParams<Real>& params);
+ ~AuctionOracleKDTreeRestricted();
+ // data members
+ // temporarily make everything public
+ Real max_val_;
+ Real weight_adj_const_;
+ dnn::KDTree<DnnTraits>* kdtree_;
+ std::vector<DnnPoint> dnn_points_;
+ std::vector<DnnPoint*> dnn_point_handles_;
+ LossesHeapR diag_items_heap_;
+ std::vector<LossesHeapRHandle> diag_heap_handles_;
+ std::vector<size_t> heap_handles_indices_;
+ std::vector<size_t> kdtree_items_;
+ std::vector<size_t> top_diag_indices_;
+ std::vector<size_t> top_diag_lookup_;
+ size_t top_diag_counter_ { 0 };
+ bool best_diagonal_items_computed_ { false };
+ Real best_diagonal_item_value_;
+ size_t second_best_diagonal_item_idx_ { k_invalid_index };
+ Real second_best_diagonal_item_value_ { std::numeric_limits<Real>::max() };
+
+
+ // methods
+ void set_price(const IdxType items_idx, const Real new_price, const bool update_diag = true);
+ IdxValPair<Real> get_optimal_bid(const IdxType bidder_idx);
+ void adjust_prices();
+ void adjust_prices(const Real delta);
+
+ // debug routines
+ DebugOptimalBidR get_optimal_bid_debug(IdxType bidder_idx) const;
+ void sanity_check();
+
+
+ // heap top vector
+ size_t get_heap_top_size() const;
+ void recompute_top_diag_items(bool hard = false);
+ void recompute_second_best_diag();
+ void reset_top_diag_counter();
+ void increment_top_diag_counter();
+ void add_top_diag_index(const size_t item_idx);
+ void remove_top_diag_index(const size_t item_idx);
+ bool is_in_top_diag_indices(const size_t item_idx) const;
+
+ std::pair<Real, Real> get_minmax_price() const;
+
+};
+
+template<class Real>
+std::ostream& operator<< (std::ostream& output, const DebugOptimalBid<Real>& db);
+
+} // ws
+} // hera
+
+
+#include "auction_oracle_kdtree_restricted.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_oracle_kdtree_restricted.hpp b/wasserstein/include/auction_oracle_kdtree_restricted.hpp
new file mode 100644
index 0000000..f0e7ac6
--- /dev/null
+++ b/wasserstein/include/auction_oracle_kdtree_restricted.hpp
@@ -0,0 +1,538 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+#ifndef AUCTION_ORACLE_KDTREE_RESTRICTED_HPP
+#define AUCTION_ORACLE_KDTREE_RESTRICTED_HPP
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "auction_oracle_kdtree_restricted.h"
+
+
+#ifdef FOR_R_TDA
+#undef DEBUG_AUCTION
+#endif
+
+namespace hera {
+namespace ws {
+
+
+// *****************************
+// AuctionOracleKDTreeRestricted
+// *****************************
+
+
+
+template <class Real_, class PointContainer_>
+std::ostream& operator<<(std::ostream& output, const AuctionOracleKDTreeRestricted<Real_, PointContainer_>& oracle)
+{
+ output << "Oracle " << &oracle << std::endl;
+ output << "max_val_ = " << oracle.max_val_ << ", ";
+ output << "best_diagonal_items_computed_ = " << oracle.best_diagonal_items_computed_ << ", ";
+ output << "best_diagonal_item_value_ = " << oracle.best_diagonal_item_value_ << ", ";
+ output << "second_best_diagonal_item_idx_ = " << oracle.second_best_diagonal_item_idx_ << ", ";
+ output << "second_best_diagonal_item_value_ = " << oracle.second_best_diagonal_item_value_ << ", ";
+ output << "prices = " << format_container_to_log(oracle.prices) << "\n";
+ output << "diag_items_heap_ = " << losses_heap_to_string(oracle.diag_items_heap_) << "\n";
+ output << "top_diag_indices_ = " << format_container_to_log(oracle.top_diag_indices_) << "\n";
+ output << "top_diag_counter_ = " << oracle.top_diag_counter_ << "\n";
+ output << "top_diag_lookup_ = " << format_container_to_log(oracle.top_diag_lookup_) << "\n";
+ output << "end of oracle " << &oracle << std::endl;
+ return output;
+}
+
+
+template<class Real_, class PointContainer_>
+AuctionOracleKDTreeRestricted<Real_, PointContainer_>::AuctionOracleKDTreeRestricted(const PointContainer_& _bidders,
+ const PointContainer_& _items,
+ const AuctionParams<Real>& params) :
+ AuctionOracleBase<Real>(_bidders, _items, params),
+ heap_handles_indices_(_items.size(), k_invalid_index),
+ kdtree_items_(_items.size(), k_invalid_index),
+ top_diag_lookup_(_items.size(), k_invalid_index)
+{
+ size_t dnn_item_idx { 0 };
+ size_t true_idx { 0 };
+ dnn_points_.clear();
+ dnn_points_.reserve(this->items.size());
+ // store normal items in kd-tree
+ for(const auto& g : this->items) {
+ if (g.is_normal() ) {
+ kdtree_items_[true_idx] = dnn_item_idx;
+ // index of items is id of dnn-point
+ DnnPoint p(true_idx);
+ p[0] = g.getRealX();
+ p[1] = g.getRealY();
+ dnn_points_.push_back(p);
+ assert(dnn_item_idx == dnn_points_.size() - 1);
+ dnn_item_idx++;
+ }
+ true_idx++;
+ }
+
+ assert(dnn_points_.size() < _items.size() );
+ for(size_t i = 0; i < dnn_points_.size(); ++i) {
+ dnn_point_handles_.push_back(&dnn_points_[i]);
+ }
+ DnnTraits traits;
+ traits.internal_p = params.internal_p;
+ kdtree_ = new dnn::KDTree<DnnTraits>(traits, dnn_point_handles_, params.wasserstein_power);
+
+ size_t handle_idx {0};
+ for(size_t item_idx = 0; item_idx < _items.size(); ++item_idx) {
+ if (this->items[item_idx].is_diagonal()) {
+ heap_handles_indices_[item_idx] = handle_idx++;
+ diag_heap_handles_.push_back(diag_items_heap_.push(std::make_pair(item_idx, 0.0)));
+ }
+ }
+ max_val_ = 3*getFurthestDistance3Approx<>(_bidders, _items, params.internal_p);
+ max_val_ = std::pow(max_val_, params.wasserstein_power);
+ weight_adj_const_ = max_val_;
+}
+
+
+template<class Real_, class PointContainer_>
+bool AuctionOracleKDTreeRestricted<Real_, PointContainer_>::is_in_top_diag_indices(const size_t item_idx) const
+{
+ return top_diag_lookup_[item_idx] != k_invalid_index;
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::add_top_diag_index(const size_t item_idx)
+{
+ assert(find(top_diag_indices_.begin(), top_diag_indices_.end(), item_idx) == top_diag_indices_.end());
+ assert(this->items[item_idx].is_diagonal());
+
+ top_diag_indices_.push_back(item_idx);
+ top_diag_lookup_[item_idx] = top_diag_indices_.size() - 1;
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::remove_top_diag_index(const size_t item_idx)
+{
+ if (top_diag_indices_.size() > 1) {
+ // remove item_idx from top_diag_indices after swapping
+ // it with the last element, update index lookup appropriately
+ auto old_index = top_diag_lookup_[item_idx];
+ auto end_element = top_diag_indices_.back();
+ std::swap(top_diag_indices_[old_index], top_diag_indices_.back());
+ top_diag_lookup_[end_element] = old_index;
+ }
+
+ top_diag_indices_.pop_back();
+ top_diag_lookup_[item_idx] = k_invalid_index;
+ if (top_diag_indices_.size() < 2) {
+ recompute_second_best_diag();
+ }
+ best_diagonal_items_computed_ = not top_diag_indices_.empty();
+ reset_top_diag_counter();
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::increment_top_diag_counter()
+{
+ assert(top_diag_counter_ >= 0 and top_diag_counter_ < top_diag_indices_.size());
+
+ ++top_diag_counter_;
+ if (top_diag_counter_ >= top_diag_indices_.size()) {
+ top_diag_counter_ -= top_diag_indices_.size();
+ }
+
+ assert(top_diag_counter_ >= 0 and top_diag_counter_ < top_diag_indices_.size());
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::reset_top_diag_counter()
+{
+ top_diag_counter_ = 0;
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::recompute_top_diag_items(bool hard)
+{
+ assert(hard or top_diag_indices_.empty());
+
+ if (hard) {
+ std::fill(top_diag_lookup_.begin(), top_diag_lookup_.end(), k_invalid_index);
+ top_diag_indices_.clear();
+ }
+
+ auto top_diag_iter = diag_items_heap_.ordered_begin();
+ best_diagonal_item_value_ = top_diag_iter->second;
+ add_top_diag_index(top_diag_iter->first);
+
+ ++top_diag_iter;
+
+ // traverse the heap while we see the same value
+ while(top_diag_iter != diag_items_heap_.ordered_end()) {
+ if ( top_diag_iter->second != best_diagonal_item_value_) {
+ break;
+ } else {
+ add_top_diag_index(top_diag_iter->first);
+ }
+ ++top_diag_iter;
+ }
+
+ recompute_second_best_diag();
+
+ best_diagonal_items_computed_ = true;
+ reset_top_diag_counter();
+}
+
+template<class Real_, class PointContainer_>
+typename AuctionOracleKDTreeRestricted<Real_, PointContainer_>::DebugOptimalBidR
+AuctionOracleKDTreeRestricted<Real_, PointContainer_>::get_optimal_bid_debug(IdxType bidder_idx) const
+{
+ auto bidder = this->bidders[bidder_idx];
+
+ size_t best_item_idx = k_invalid_index;
+ size_t second_best_item_idx = k_invalid_index;
+ Real best_item_value = std::numeric_limits<Real>::max();
+ Real second_best_item_value = std::numeric_limits<Real>::max();
+
+ for(IdxType item_idx = 0; item_idx < static_cast<IdxType>(this->items.size()); ++item_idx) {
+ auto item = this->items[item_idx];
+ if (item.type != bidder.type and item_idx != bidder_idx)
+ continue;
+ auto item_value = std::pow(dist_lp(bidder, item, this->internal_p, 2), this->wasserstein_power) + this->prices[item_idx];
+ if (item_value < best_item_value) {
+ best_item_value = item_value;
+ best_item_idx = item_idx;
+ }
+ }
+
+ assert(best_item_idx != k_invalid_index);
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ auto item = this->items[item_idx];
+ if (item.type != bidder.type and static_cast<IdxType>(item_idx) != bidder_idx)
+ continue;
+ if (item_idx == best_item_idx)
+ continue;
+ auto item_value = std::pow(dist_lp(bidder, item, this->internal_p, 2), this->wasserstein_power) + this->prices[item_idx];
+ if (item_value < second_best_item_value) {
+ second_best_item_value = item_value;
+ second_best_item_idx = item_idx;
+ }
+ }
+
+ assert(second_best_item_idx != k_invalid_index);
+ assert(second_best_item_value >= best_item_value);
+
+ DebugOptimalBidR result;
+
+ result.best_item_idx = best_item_idx;
+ result.best_item_value = best_item_value;
+ result.second_best_item_idx = second_best_item_idx;
+ result.second_best_item_value = second_best_item_value;
+
+ return result;
+}
+
+
+template<class Real_, class PointContainer_>
+IdxValPair<Real_> AuctionOracleKDTreeRestricted<Real_, PointContainer_>::get_optimal_bid(IdxType bidder_idx)
+{
+ auto bidder = this->bidders[bidder_idx];
+
+ // corresponding point is always considered as a candidate
+ // if bidder is a diagonal point, proj_item is a normal point,
+ // and vice versa.
+
+ size_t best_item_idx { k_invalid_index };
+ size_t second_best_item_idx { k_invalid_index };
+ size_t best_diagonal_item_idx { k_invalid_index };
+ Real best_item_value;
+ Real second_best_item_value;
+
+
+ size_t proj_item_idx = bidder_idx;
+ assert( 0 <= proj_item_idx and proj_item_idx < this->items.size() );
+ assert(this->items[proj_item_idx].type != bidder.type);
+ Real proj_item_value = this->get_value_for_bidder(bidder_idx, proj_item_idx);
+
+ if (bidder.is_diagonal()) {
+ // for diagonal bidder the only normal point has already been added
+ // the other 2 candidates are diagonal items only, get from the heap
+ // with prices
+
+ if (not best_diagonal_items_computed_) {
+ recompute_top_diag_items();
+ }
+
+ best_diagonal_item_idx = top_diag_indices_[top_diag_counter_];
+ increment_top_diag_counter();
+
+ if ( proj_item_value < best_diagonal_item_value_) {
+ best_item_idx = proj_item_idx;
+ best_item_value = proj_item_value;
+ second_best_item_value = best_diagonal_item_value_;
+ second_best_item_idx = best_diagonal_item_idx;
+ } else if (proj_item_value < second_best_diagonal_item_value_) {
+ best_item_idx = best_diagonal_item_idx;
+ best_item_value = best_diagonal_item_value_;
+ second_best_item_value = proj_item_value;
+ second_best_item_idx = proj_item_idx;
+ } else {
+ best_item_idx = best_diagonal_item_idx;
+ best_item_value = best_diagonal_item_value_;
+ second_best_item_value = second_best_diagonal_item_value_;
+ second_best_item_idx = second_best_diagonal_item_idx_;
+ }
+ } else {
+ // for normal bidder get 2 best items among non-diagonal points from
+ // kdtree_
+ DnnPoint bidder_dnn;
+ bidder_dnn[0] = bidder.getRealX();
+ bidder_dnn[1] = bidder.getRealY();
+ auto two_best_items = kdtree_->findK(bidder_dnn, 2);
+ size_t best_normal_item_idx { two_best_items[0].p->id() };
+ Real best_normal_item_value { two_best_items[0].d };
+ // if there is only one off-diagonal point in the second diagram,
+ // kd-tree will not return the second candidate.
+ // Set its value to inf, so it will always lose to the value of the projection
+ Real second_best_normal_item_value { two_best_items.size() == 1 ? std::numeric_limits<Real>::max() : two_best_items[1].d };
+
+ if ( proj_item_value < best_normal_item_value) {
+ best_item_idx = proj_item_idx;
+ best_item_value = proj_item_value;
+ second_best_item_value = best_normal_item_value;
+ } else if (proj_item_value < second_best_normal_item_value) {
+ best_item_idx = best_normal_item_idx;
+ best_item_value = best_normal_item_value;
+ second_best_item_value = proj_item_value;
+ } else {
+ best_item_idx = best_normal_item_idx;
+ best_item_value = best_normal_item_value;
+ second_best_item_value = second_best_normal_item_value;
+ }
+ }
+
+ IdxValPair<Real> result;
+
+ assert( second_best_item_value >= best_item_value );
+
+ result.first = best_item_idx;
+ result.second = ( second_best_item_value - best_item_value ) + this->prices[best_item_idx] + this->epsilon;
+
+#ifdef DEBUG_KDTREE_RESTR_ORACLE
+ auto db = get_optimal_bid_debug(bidder_idx);
+ assert(fabs(db.best_item_value - best_item_value) < 0.000001);
+ assert(fabs(db.second_best_item_value - second_best_item_value) < 0.000001);
+ //std::cout << "bid OK" << std::endl;
+#endif
+
+ return result;
+}
+/*
+a_{ij} = d_{ij}
+value_{ij} = a_{ij} + price_j
+*/
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::recompute_second_best_diag()
+{
+ if (top_diag_indices_.size() > 1) {
+ second_best_diagonal_item_value_ = best_diagonal_item_value_;
+ second_best_diagonal_item_idx_ = top_diag_indices_[0];
+ } else {
+ if (diag_items_heap_.size() == 1) {
+ second_best_diagonal_item_value_ = std::numeric_limits<Real>::max();
+ second_best_diagonal_item_idx_ = k_invalid_index;
+ } else {
+ auto diag_iter = diag_items_heap_.ordered_begin();
+ ++diag_iter;
+ second_best_diagonal_item_value_ = diag_iter->second;
+ second_best_diagonal_item_idx_ = diag_iter->first;
+ }
+ }
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::set_price(IdxType item_idx,
+ Real new_price,
+ const bool update_diag)
+{
+ assert(this->prices.size() == this->items.size());
+ assert( 0 < diag_heap_handles_.size() and diag_heap_handles_.size() <= this->items.size());
+ // adjust_prices decreases prices,
+ // also this variable must be true in reverse phases of FR-auction
+ bool item_goes_down = new_price > this->prices[item_idx];
+
+ this->prices[item_idx] = new_price;
+ if ( this->items[item_idx].is_normal() ) {
+ assert(0 <= item_idx and item_idx < static_cast<IdxType>(kdtree_items_.size()));
+ assert(0 <= kdtree_items_[item_idx] and kdtree_items_[item_idx] < dnn_point_handles_.size());
+ kdtree_->change_weight( dnn_point_handles_[kdtree_items_[item_idx]], new_price);
+ } else {
+ assert(diag_heap_handles_.size() > heap_handles_indices_.at(item_idx));
+ if (item_goes_down) {
+ diag_items_heap_.decrease(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ } else {
+ diag_items_heap_.increase(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ }
+ if (update_diag) {
+ // Update top_diag_indices_ only if necessary:
+ // normal bidders take their projections, which might not be on top
+ // also, set_price is called by adjust_prices, and we may have already
+ // removed the item from top_diag
+ if (is_in_top_diag_indices(item_idx)) {
+ remove_top_diag_index(item_idx);
+ }
+
+ if (item_idx == (IdxType)second_best_diagonal_item_idx_) {
+ recompute_second_best_diag();
+ }
+ }
+ }
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::adjust_prices(Real delta)
+{
+ if (delta == 0.0)
+ return;
+
+ for(auto& p : this->prices) {
+ p -= delta;
+ }
+
+ kdtree_->adjust_weights(delta);
+
+ bool price_goes_up = delta < 0;
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ if (this->items[item_idx].is_diagonal()) {
+ auto new_price = this->prices[item_idx];
+ if (price_goes_up) {
+ diag_items_heap_.decrease(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ } else {
+ diag_items_heap_.increase(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ }
+ }
+ }
+ best_diagonal_item_value_ -= delta;
+ second_best_diagonal_item_value_ -= delta;
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::adjust_prices()
+{
+ auto pr_begin = this->prices.begin();
+ auto pr_end = this->prices.end();
+ Real min_price = *(std::min_element(pr_begin, pr_end));
+ adjust_prices(min_price);
+}
+
+template<class Real_, class PointContainer_>
+size_t AuctionOracleKDTreeRestricted<Real_, PointContainer_>::get_heap_top_size() const
+{
+ return top_diag_indices_.size();
+}
+
+template<class Real_, class PointContainer_>
+std::pair<Real_, Real_> AuctionOracleKDTreeRestricted<Real_, PointContainer_>::get_minmax_price() const
+{
+ auto r = std::minmax_element(this->prices.begin(), this->prices.end());
+ return std::make_pair(*r.first, *r.second);
+}
+
+
+
+template<class Real_, class PointContainer_>
+AuctionOracleKDTreeRestricted<Real_, PointContainer_>::~AuctionOracleKDTreeRestricted()
+{
+ delete kdtree_;
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeRestricted<Real_, PointContainer_>::sanity_check()
+{
+#ifdef DEBUG_KDTREE_RESTR_ORACLE
+ if (best_diagonal_items_computed_) {
+ std::vector<Real> diag_items_price_vec;
+ diag_items_price_vec.reserve(this->items.size());
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ if (this->items.at(item_idx).is_diagonal()) {
+ diag_items_price_vec.push_back(this->prices.at(item_idx));
+ } else {
+ diag_items_price_vec.push_back(std::numeric_limits<Real>::max());
+ }
+ }
+
+ auto best_iter = std::min_element(diag_items_price_vec.begin(), diag_items_price_vec.end());
+ assert(best_iter != diag_items_price_vec.end());
+ Real true_best_diag_value = *best_iter;
+ size_t true_best_diag_idx = best_iter - diag_items_price_vec.begin();
+ assert(true_best_diag_value != std::numeric_limits<Real>::max());
+
+ Real true_second_best_diag_value = std::numeric_limits<Real>::max();
+ size_t true_second_best_diag_idx = k_invalid_index;
+ for(size_t item_idx = 0; item_idx < diag_items_price_vec.size(); ++item_idx) {
+ if (this->items.at(item_idx).is_normal()) {
+ assert(top_diag_lookup_.at(item_idx) == k_invalid_index);
+ continue;
+ }
+
+ auto i_iter = std::find(top_diag_indices_.begin(), top_diag_indices_.end(), item_idx);
+ if (diag_items_price_vec.at(item_idx) == true_best_diag_value) {
+ assert(i_iter != top_diag_indices_.end());
+ assert(top_diag_lookup_.at(item_idx) == i_iter - top_diag_indices_.begin());
+ } else {
+ assert(top_diag_lookup_.at(item_idx) == k_invalid_index);
+ assert(i_iter == top_diag_indices_.end());
+ }
+
+ if (item_idx == true_best_diag_idx) {
+ continue;
+ }
+ if (diag_items_price_vec.at(item_idx) < true_second_best_diag_value) {
+ true_second_best_diag_value = diag_items_price_vec.at(item_idx);
+ true_second_best_diag_idx = item_idx;
+ }
+ }
+
+ assert(true_best_diag_value == best_diagonal_item_value_);
+ assert(true_second_best_diag_idx != k_invalid_index);
+ assert(true_second_best_diag_value == second_best_diagonal_item_value_);
+ }
+#endif
+}
+
+
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/auction_oracle_kdtree_single_diag.h b/wasserstein/include/auction_oracle_kdtree_single_diag.h
new file mode 100644
index 0000000..9192993
--- /dev/null
+++ b/wasserstein/include/auction_oracle_kdtree_single_diag.h
@@ -0,0 +1,219 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_KDTREE_SINGLE_DIAG_H
+#define AUCTION_ORACLE_KDTREE_SINGLE_DIAG_H
+
+
+#include <map>
+#include <memory>
+#include <set>
+#include <list>
+#include <ostream>
+
+#include "basic_defs_ws.h"
+#include "dnn/geometry/euclidean-fixed.h"
+#include "dnn/local/kd-tree.h"
+
+namespace hera {
+namespace ws {
+
+
+template <class Real = double>
+struct ItemSlice;
+
+template <class Real = double>
+bool operator<(const ItemSlice<Real>& s_1, const ItemSlice<Real>& s_2);
+
+template <class Real = double>
+bool operator>(const ItemSlice<Real>& s_1, const ItemSlice<Real>& s_2);
+
+template <class Real>
+struct ItemSlice {
+public:
+ using RealType = Real;
+
+ size_t item_idx;
+ Real loss;
+ ItemSlice(size_t _item_idx, const Real _loss);
+
+ void set_loss(const Real new_loss) { loss = new_loss; }
+ void adjust_loss(const Real delta) { loss -= delta; }
+
+ friend bool operator< <>(const ItemSlice<Real>&, const ItemSlice<Real>&);
+ friend bool operator> <>(const ItemSlice<Real>&, const ItemSlice<Real>&);
+
+private:
+};
+
+
+template <class Real = double>
+class LossesHeap {
+public:
+ using ItemSliceR = ItemSlice<Real>;
+ using KeeperTypeR = std::set<ItemSliceR, std::less<ItemSliceR> >;
+ using IterTypeR = typename KeeperTypeR::iterator;
+
+ LossesHeap() {}
+ LossesHeap(const std::vector<ItemSliceR>&);
+ void adjust_prices(const Real delta); // subtract delta from all values
+ ItemSliceR get_best_slice() const;
+ ItemSliceR get_second_best_slice() const;
+
+ template<typename ...Args>
+ decltype(auto) emplace(Args&&... args)
+ {
+ return keeper.emplace(std::forward<Args>(args)...);
+ }
+
+
+ IterTypeR begin() { return keeper.begin(); }
+ IterTypeR end() { return keeper.end(); }
+ void erase(IterTypeR iter) { assert(iter != keeper.end()); keeper.erase(iter); }
+ decltype(auto) insert(const ItemSliceR& item) { return keeper.insert(item); }
+ size_t size() const { return keeper.size(); }
+ bool empty() const { return keeper.empty(); }
+//private:
+ std::set<ItemSliceR, std::less<ItemSliceR> > keeper;
+};
+
+template <class Real>
+struct DiagonalBid {
+ DiagonalBid() {}
+
+ std::vector<size_t> assigned_normal_items;
+ std::vector<Real> assigned_normal_items_bid_values;
+
+ std::vector<size_t> best_item_indices;
+ std::vector<Real> bid_values;
+
+ // common bid value for diag-diag
+ Real diag_to_diag_value { 0.0 };
+
+ // analogous to second best item value; denoted by w in Bertsekas's paper on auction for transportation problem
+ Real almost_best_value { 0.0 };
+
+ // how many points to get from unassigned diagonal chunk
+ int num_from_unassigned_diag { 0 };
+};
+
+template <class Real_ = double, class PointContainer_ = std::vector<DiagramPoint<Real_>>>
+struct AuctionOracleKDTreeSingleDiag : AuctionOracleBase<Real_, PointContainer_> {
+
+ using PointContainer = PointContainer_;
+ using Real = Real_;
+
+ using DnnPoint = dnn::Point<2, Real>;
+ using DnnTraits = dnn::PointTraits<DnnPoint>;
+
+ using IdxValPairR = typename ws::IdxValPair<Real>;
+ using ItemSliceR = typename ws::ItemSlice<Real>;
+ using LossesHeapR = typename ws::LossesHeap<Real>;
+ using LossesHeapIterR = typename ws::LossesHeap<Real>::IterTypeR;
+ using DiagramPointR = typename ws::DiagramPoint<Real>;
+ using DiagonalBidR = typename ws::DiagonalBid<Real>;
+
+ AuctionOracleKDTreeSingleDiag(const PointContainer& bidders,
+ const PointContainer& items,
+ const AuctionParams<Real>& params);
+ ~AuctionOracleKDTreeSingleDiag();
+ // data members
+ // temporarily make everything public
+ Real max_val_;
+ size_t num_diag_items_;
+ size_t num_normal_items_;
+ size_t num_diag_bidders_;
+ size_t num_normal_bidders_;
+ dnn::KDTree<DnnTraits>* kdtree_;
+ std::vector<DnnPoint> dnn_points_;
+ std::vector<DnnPoint*> dnn_point_handles_;
+ std::vector<size_t> kdtree__items_;
+
+ // this heap is used by off-diagonal bidders to get the cheapest diagonal
+ // item; index in the IdxVal is a valid item index in the vector of items
+ // items in diag_assigned_to_diag_slice_ and in diag_unassigned_slice_
+ // are not stored in this heap
+ LossesHeapR diag_items_heap_;
+ // vector of iterators; if item_idx is in diag_assigned_to_diag_slice_ or
+ // in diag_unassigned_slice_, then diag_items_heap__iters_[item_idx] ==
+ // diag_items_heap_.end()
+ std::vector<LossesHeapIterR> diag_items_heap__iters_;
+
+
+ // this heap is used by _the_ diagonal bidder to get the cheapest items
+ // * value in IdxValPair is price + persistence (i.e., price for
+ // diagonal items)
+ // * index in IdxValPair is a valid item index in the vector of items
+ // items in diag_assigned_to_diag_slice_ and in diag_unassigned_slice_
+ // are not stored in this heap
+ LossesHeapR all_items_heap_;
+ std::vector<LossesHeapIterR> all_items_heap__iters_;
+
+ std::unordered_set<size_t> diag_assigned_to_diag_slice_;
+ std::unordered_set<size_t> diag_unassigned_slice_;
+
+
+ std::unordered_set<size_t> normal_items_assigned_to_diag_;
+
+ Real diag_to_diag_price_;
+ Real diag_unassigned_price_;
+
+ // methods
+ Real get_price(const size_t item_idx) const override;
+ void set_price(const size_t item_idx,
+ const Real new_price,
+ const bool item_is_diagonal,
+ const bool bidder_is_diagonal,
+ const OwnerType old_owner_type);
+
+ IdxValPair<Real> get_optimal_bid(const IdxType bidder_idx);
+
+ DiagonalBidR get_optimal_bids_for_diagonal(int unassigned_mass);
+ void process_unassigned_diagonal(const int unassigned_mass,
+ int& accumulated_mass,
+ bool& saw_diagonal_slice,
+ int& num_classes,
+ Real& w,
+ DiagonalBidR& result,
+ bool& found_w);
+
+ void adjust_prices();
+ void flush_assignment();
+ void sanity_check();
+
+ bool is_item_diagonal(const size_t item_idx) const;
+ bool is_item_normal(const size_t item_idx) const { return not is_item_diagonal(item_idx); }
+
+};
+
+} // ws
+} // hera
+
+#include "auction_oracle_kdtree_single_diag.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_oracle_kdtree_single_diag.hpp b/wasserstein/include/auction_oracle_kdtree_single_diag.hpp
new file mode 100644
index 0000000..42677ab
--- /dev/null
+++ b/wasserstein/include/auction_oracle_kdtree_single_diag.hpp
@@ -0,0 +1,717 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+#ifndef AUCTION_ORACLE_KDTREE_RESTRICTED_SINGLE_DIAG_HPP
+#define AUCTION_ORACLE_KDTREE_RESTRICTED_SINGLE_DIAG_HPP
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "auction_oracle.h"
+
+
+#ifdef FOR_R_TDA
+#undef DEBUG_AUCTION
+#endif
+
+namespace hera {
+namespace ws {
+
+// *****************************
+// AuctionOracleKDTreeSingleDiag
+// *****************************
+
+
+
+template <class Real>
+ItemSlice<Real>::ItemSlice(size_t _item_idx,
+ const Real _loss) :
+ item_idx(_item_idx),
+ loss(_loss)
+{
+}
+
+
+template <class Real>
+bool operator<(const ItemSlice<Real>& s_1, const ItemSlice<Real>& s_2)
+{
+ return s_1.loss < s_2.loss
+ or (s_1.loss == s_2.loss and s_1.item_idx < s_2.item_idx);
+}
+
+template <class Real>
+bool operator>(const ItemSlice<Real>& s_1, const ItemSlice<Real>& s_2)
+{
+ return s_1.loss > s_2.loss
+ or (s_1.loss == s_2.loss and s_1.item_idx > s_2.item_idx);
+}
+
+template<class Real>
+std::ostream& operator<<(std::ostream& s, const ItemSlice<Real>& x)
+{
+ s << "(" << x.item_idx << ", " << x.loss << ")";
+ return s;
+}
+
+// *****************************
+// LossesHeap
+// *****************************
+
+
+template <class Real>
+void LossesHeap<Real>::adjust_prices(const Real delta)
+{
+ throw std::runtime_error("not implemented");
+}
+
+template <class Real>
+typename LossesHeap<Real>::ItemSliceR LossesHeap<Real>::get_best_slice() const
+{
+ return *(keeper.begin());
+}
+
+template <class Real>
+typename LossesHeap<Real>::ItemSliceR LossesHeap<Real>::get_second_best_slice() const
+{
+ if (keeper.size() > 1) {
+ return *std::next(keeper.begin());
+ } else {
+ return ItemSliceR(k_invalid_index, std::numeric_limits<Real>::max());
+ }
+}
+
+template<class Real>
+std::ostream& operator<<(std::ostream& s, const LossesHeap<Real>& x)
+{
+ s << "Heap[ ";
+ for(auto iter = x.keeper.begin(); iter != x.keeper.end(); ++iter) {
+ s << *iter << "\n";
+ }
+ s << "]\n";
+ return s;
+}
+
+// *****************************
+// DiagonalBid
+// *****************************
+
+template <class Real>
+std::ostream& operator<<(std::ostream& s, const DiagonalBid<Real>& b)
+{
+ s << "DiagonalBid { num_from_unassigned_diag = " << b.num_from_unassigned_diag;
+ s << ", diag_to_diag_value = " << b.diag_to_diag_value;
+ s << ", almost_best_value = " << b.almost_best_value;
+ s << ",\nbest_item_indices = [";
+ for(const auto i : b.best_item_indices) {
+ s << i << ", ";
+ }
+ s << "]\n";
+
+ s << ",\nbid_values= [";
+ for(const auto v : b.bid_values) {
+ s << v << ", ";
+ }
+ s << "]\n";
+
+ s << ",\nassigned_normal_items= [";
+ for(const auto i : b.assigned_normal_items) {
+ s << i << ", ";
+ }
+ s << "]\n";
+
+ s << ",\nassigned_normal_items_bid_values = [";
+ for(const auto v : b.assigned_normal_items_bid_values) {
+ s << v << ", ";
+ }
+ s << "]\n";
+
+ return s;
+}
+
+// *****************************
+// AuctionOracleKDTreeSingleDiag
+// *****************************
+
+template<class Real_, class PointContainer_>
+std::ostream& operator<<(std::ostream& s, const AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>& x)
+{
+ s << "oracle: bidders" << std::endl;
+ for(const auto& p : x.bidders) {
+ s << p << "\n";
+ }
+ s << "items:";
+
+ for(const auto& p : x.items) {
+ s << p << "\n";
+ }
+
+ s << "diag_unassigned_slice_.size = " << x.diag_unassigned_slice_.size() << ", ";
+ s << "diag_unassigned_price_ = " << x.diag_unassigned_price_ << ", ";
+ s << "diag unassigned slice [";
+
+ for(const auto& i : x.diag_unassigned_slice_) {
+ s << i << ", ";
+ }
+ s << "]\n ";
+
+ s << "diag_assigned_to_diag_slice_.size = " << x.diag_assigned_to_diag_slice_.size() << ", ";
+ s << "diag_assigned_to_diag_price = " << x.diag_to_diag_price_ << "\n";
+ s << "diag_assigned_to_diag_slice_ [";
+
+ for(const auto& i : x.diag_assigned_to_diag_slice_) {
+ s << i << ", ";
+ }
+ s << "]\n ";
+
+ s << "diag_items_heap_.size = " << x.diag_items_heap_.size() << "\n ";
+ s << x.diag_items_heap_;
+
+ s << "all_items_heap_.size = " << x.all_items_heap_.size() << "\n ";
+ s << x.all_items_heap_;
+
+ s << "epsilon = " << x.epsilon << std::endl;
+
+ return s;
+}
+
+
+template<class Real_, class PointContainer_>
+AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::AuctionOracleKDTreeSingleDiag(const PointContainer_& _bidders,
+ const PointContainer_& _items,
+ const AuctionParams<Real>& params) :
+ AuctionOracleBase<Real_, PointContainer_>(_bidders, _items, params),
+ max_val_(std::pow( 3.0 * getFurthestDistance3Approx<>(_bidders, _items, params.internal_p), params.wasserstein_power)),
+ num_diag_items_(0),
+ kdtree__items_(_items.size(), k_invalid_index)
+{
+ size_t dnn_item_idx { 0 };
+ dnn_points_.clear();
+
+ all_items_heap__iters_.clear();
+ all_items_heap__iters_.reserve( 4 * _items.size() / 7);
+
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ const auto& item = this->items[item_idx];
+ if (item.is_normal() ) {
+ // store normal items in kd-tree
+ kdtree__items_[item_idx] = dnn_item_idx;
+ // index of items is id of dnn-point
+ DnnPoint p(item_idx);
+ p[0] = item.x;
+ p[1] = item.y;
+ dnn_points_.push_back(p);
+ assert(dnn_item_idx == dnn_points_.size() - 1);
+ dnn_item_idx++;
+ // add slice to vector
+ auto ins_res = all_items_heap_.emplace(item_idx, this->get_value_for_diagonal_bidder(item_idx));
+ all_items_heap__iters_.push_back(ins_res.first);
+ assert(ins_res.second);
+ } else {
+ // all diagonal items are initially in the unassigned slice
+ diag_unassigned_slice_.insert(item_idx);
+ all_items_heap__iters_.push_back(all_items_heap_.end());
+ diag_items_heap__iters_.push_back(diag_items_heap_.end());
+ ++num_diag_items_;
+ }
+ }
+
+ num_normal_items_ = this->items.size() - num_diag_items_;
+ num_normal_bidders_ = num_diag_items_;
+ num_diag_bidders_ = this->bidders.size() - num_normal_bidders_;
+
+ assert(dnn_points_.size() < _items.size() );
+ for(size_t i = 0; i < dnn_points_.size(); ++i) {
+ dnn_point_handles_.push_back(&dnn_points_[i]);
+ }
+
+ DnnTraits traits;
+ traits.internal_p = params.internal_p;
+
+ kdtree_ = new dnn::KDTree<DnnTraits>(traits, dnn_point_handles_, this->wasserstein_power);
+
+ sanity_check();
+
+ //std::cout << "IN CTOR: " << *this << std::endl;
+
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::process_unassigned_diagonal(const int unassigned_mass, int& accumulated_mass, bool& saw_diagonal_slice, int& num_classes, Real& w, DiagonalBidR& result, bool& found_w)
+{
+ result.num_from_unassigned_diag = std::min(static_cast<int>(diag_unassigned_slice_.size()), static_cast<int>(unassigned_mass - accumulated_mass));
+ if (not saw_diagonal_slice) {
+ saw_diagonal_slice = true;
+ ++num_classes;
+ }
+
+ accumulated_mass += result.num_from_unassigned_diag;
+ //std::cout << "got mass from diagunassigned_slice, result.num_from_unassigned_diag = " << result.num_from_unassigned_diag << ", accumulated_mass = " << accumulated_mass << std::endl;
+
+ if (static_cast<int>(diag_unassigned_slice_.size()) > result.num_from_unassigned_diag and num_classes >= 2) {
+ found_w = true;
+ w = diag_unassigned_price_;
+ //std::cout << "w found from diag_unassigned_slice_, too, w = " << w << std::endl;
+ result.almost_best_value = w;
+ }
+
+}
+
+
+template<class Real_, class PointContainer_>
+typename AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::DiagonalBidR AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::get_optimal_bids_for_diagonal(int unassigned_mass)
+{
+ sanity_check();
+
+ assert(unassigned_mass == static_cast<decltype(unassigned_mass)>(num_diag_bidders_)
+ - static_cast<decltype(unassigned_mass)>(normal_items_assigned_to_diag_.size())
+ - static_cast<decltype(unassigned_mass)>(diag_assigned_to_diag_slice_.size()) );
+ assert(unassigned_mass > 0);
+
+ DiagonalBidR result;
+
+
+ // number of similarity classes already assigned to diagonal bidder
+ // each normal point is a single class
+ // all diagonal points are in one class
+ int num_classes = normal_items_assigned_to_diag_.size() + ( diag_assigned_to_diag_slice_.empty() ? 0 : 1 );
+ bool saw_diagonal_slice = not diag_assigned_to_diag_slice_.empty();
+ bool found_w = false;
+
+ //std::cout << "Enter get_optimal_bids_for_diagonal, unassigned_mass = " << unassigned_mass <<", num_classes = " << num_classes << ", saw_diagonal_slice = " << std::boolalpha << saw_diagonal_slice << std::endl;
+
+ decltype(unassigned_mass) accumulated_mass = 0;
+
+
+ Real w { std::numeric_limits<Real>::max() };
+ bool unassigned_not_processed = not diag_unassigned_slice_.empty();
+
+ for(auto slice_iter = all_items_heap_.begin(); slice_iter != all_items_heap_.end(); ++slice_iter) {
+
+ auto slice = *slice_iter;
+
+ if ( is_item_normal(slice.item_idx) and normal_items_assigned_to_diag_.count(slice.item_idx) == 1) {
+ //std::cout << __LINE__ << ": skipping slice " << slice << std::endl;
+ // this item is already assigned to diagonal bidder, skip
+ continue;
+ }
+
+ if (unassigned_not_processed and slice.loss >= diag_unassigned_price_) {
+ // diag_unassigned slice is better,
+ // process it first
+ process_unassigned_diagonal(unassigned_mass, accumulated_mass, saw_diagonal_slice, num_classes, w, result, found_w);
+ unassigned_not_processed = false;
+ if (accumulated_mass >= unassigned_mass and found_w) {
+ break;
+ }
+ }
+
+
+ if (is_item_normal(slice.item_idx)) {
+ // all off-diagonal items are distinct
+ ++num_classes;
+ } else if (not saw_diagonal_slice) {
+ saw_diagonal_slice = true;
+ ++num_classes;
+ }
+
+ if (accumulated_mass < unassigned_mass) {
+ //std::cout << __LINE__ << ": added slice to best items " << slice << std::endl;
+ result.best_item_indices.push_back(slice.item_idx);
+ }
+
+ if (accumulated_mass >= unassigned_mass and num_classes >= 2) {
+ //std::cout << "Found w, slice = " << slice << std::endl;
+ w = slice.loss;
+ found_w = true;
+ result.almost_best_value = w;
+ break;
+ }
+
+ // all items in all_items heap have mass 1
+ ++accumulated_mass;
+ //std::cout << "accumulated_mass = " << accumulated_mass << std::endl;
+
+ }
+
+ if (unassigned_not_processed and (accumulated_mass < unassigned_mass or not found_w)) {
+ process_unassigned_diagonal(unassigned_mass, accumulated_mass, saw_diagonal_slice, num_classes, w, result, found_w);
+ }
+
+ assert(found_w);
+
+ //if (w == std::numeric_limits<Real>::max()) { std::cout << "HERE: " << *this << std::endl; }
+ assert(w != std::numeric_limits<Real>::max());
+
+ result.assigned_normal_items.clear();
+ result.assigned_normal_items_bid_values.clear();
+
+ result.assigned_normal_items.reserve(normal_items_assigned_to_diag_.size());
+ result.assigned_normal_items_bid_values.reserve(normal_items_assigned_to_diag_.size());
+
+ // add already assigned normal items and their new prices to bid
+ for(const auto item_idx : normal_items_assigned_to_diag_) {
+ assert( all_items_heap__iters_[item_idx] != all_items_heap_.end() );
+ assert( is_item_normal(item_idx) );
+
+ result.assigned_normal_items.push_back(item_idx);
+ Real bid_value = w - this->get_cost_for_diagonal_bidder(item_idx) + this->epsilon;
+ //if ( bid_value <= this->get_price(item_idx) ) {
+ //std::cout << bid_value << " vs price " << this->get_price(item_idx) << std::endl;
+ //std::cout << *this << std::endl;
+ //}
+ assert( bid_value >= this->get_price(item_idx) );
+ result.assigned_normal_items_bid_values.push_back(bid_value);
+ }
+
+ // calculate bid values
+ // diag-to-diag items all have the same bid value
+ if (saw_diagonal_slice) {
+ result.diag_to_diag_value = w + this->epsilon;
+ } else {
+ result.diag_to_diag_value = std::numeric_limits<Real>::max();
+ }
+
+ result.bid_values.reserve(result.best_item_indices.size());
+ for(const auto item_idx : result.best_item_indices) {
+ Real bid_value = w - this->get_cost_for_diagonal_bidder(item_idx) + this->epsilon;
+ result.bid_values.push_back(bid_value);
+ }
+
+ return result;
+}
+
+
+template<class Real_, class PointContainer_>
+IdxValPair<Real_> AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::get_optimal_bid(IdxType bidder_idx)
+{
+ //std::cout << "enter get_optimal_bid" << std::endl;
+ sanity_check();
+
+ auto bidder = this->bidders[bidder_idx];
+
+ size_t best_item_idx;
+ Real best_item_price;
+ Real best_item_value;
+ Real second_best_item_value;
+
+ // this function is for normal bidders only
+ assert(bidder.is_normal());
+
+
+ // get 2 best items among non-diagonal points from kdtree_
+ DnnPoint bidder_dnn;
+ bidder_dnn[0] = bidder.getRealX();
+ bidder_dnn[1] = bidder.getRealY();
+ auto two_best_items = kdtree_->findK(bidder_dnn, 2);
+ size_t best_normal_item_idx { two_best_items[0].p->id() };
+ Real best_normal_item_value { two_best_items[0].d };
+ // if there is only one off-diagonal point in the second diagram,
+ // kd-tree will not return the second candidate.
+ // Set its price to inf, so it will always lose to the price of the projection
+ Real second_best_normal_item_value { two_best_items.size() == 1 ? std::numeric_limits<Real>::max() : two_best_items[1].d };
+
+ size_t best_diag_item_idx;
+ Real best_diag_value;
+ Real best_diag_price;
+
+ {
+ Real diag_edge_cost = std::pow(bidder.persistence_lp(this->internal_p), this->wasserstein_power);
+ auto best_diag_price_in_heap = diag_items_heap_.empty() ? std::numeric_limits<Real>::max() : diag_items_heap_.get_best_slice().loss;
+ auto best_diag_idx_in_heap = diag_items_heap_.empty() ? k_invalid_index : diag_items_heap_.get_best_slice().item_idx;
+ // if unassigned_diag_slice is empty, its price is max,
+ // same for diag-diag assigned slice, so the ifs below will work
+
+ if (best_diag_price_in_heap <= diag_to_diag_price_ and best_diag_price_in_heap <= diag_unassigned_price_) {
+ best_diag_item_idx = best_diag_idx_in_heap;
+ best_diag_value = diag_edge_cost + best_diag_price_in_heap;
+ best_diag_price = best_diag_price_in_heap;
+ } else if (diag_to_diag_price_ < best_diag_price_in_heap and diag_to_diag_price_ < diag_unassigned_price_) {
+ best_diag_item_idx = *diag_assigned_to_diag_slice_.begin();
+ best_diag_value = diag_edge_cost + diag_to_diag_price_;
+ best_diag_price = diag_to_diag_price_;
+ } else {
+ best_diag_item_idx = *diag_unassigned_slice_.begin();
+ best_diag_value = diag_edge_cost + diag_unassigned_price_;
+ best_diag_price = diag_unassigned_price_;
+ }
+
+ }
+
+ if ( best_diag_value < best_normal_item_value) {
+ best_item_idx = best_diag_item_idx;
+ best_item_price = best_diag_price;
+ best_item_value = best_diag_value;
+ second_best_item_value = best_normal_item_value;
+ } else if (best_diag_value < second_best_normal_item_value) {
+ best_item_idx = best_normal_item_idx;
+ best_item_price = this->get_price(best_item_idx);
+ best_item_value = best_normal_item_value;
+ second_best_item_value = best_diag_value;
+ } else {
+ best_item_idx = best_normal_item_idx;
+ best_item_price = this->get_price(best_item_idx);
+ best_item_value = best_normal_item_value;
+ second_best_item_value = second_best_normal_item_value;
+ }
+
+ IdxValPair<Real> result;
+
+ result.first = best_item_idx;
+ result.second = ( second_best_item_value - best_item_value ) + best_item_price + this->epsilon;
+
+ //std::cout << "bidder_idx = " << bidder_idx << ", best_item_idx = " << best_item_idx << ", best_item_value = " << best_item_value << ", second_best_item_value = " << second_best_item_value << ", eps = " << this->epsilon << std::endl;
+ assert( second_best_item_value >= best_item_value );
+ //assert( best_item_price == this->get_price(best_item_idx) );
+ assert(result.second >= best_item_price);
+ sanity_check();
+
+ return result;
+}
+/*
+a_{ij} = d_{ij}
+price_{ij} = a_{ij} + price_j
+*/
+
+
+
+//template<class Real_, class PointContainer_>
+//std::vector<IdxValPairR> AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::increase_price_of_assigned_to_diag(WHAT)
+//{
+ //WHAT;
+//}
+//
+
+template<class Real_, class PointContainer_>
+Real_ AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::get_price(const size_t item_idx) const
+{
+ if (is_item_diagonal(item_idx)) {
+ if (diag_assigned_to_diag_slice_.count(item_idx) == 1) {
+ return diag_to_diag_price_;
+ } else if (diag_unassigned_slice_.count(item_idx) == 1) {
+ return diag_unassigned_price_;
+ }
+ }
+ return this-> prices[item_idx];
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::set_price(const size_t item_idx,
+ const Real new_price,
+ const bool item_is_diagonal,
+ const bool bidder_is_diagonal,
+ const OwnerType old_owner_type)
+{
+
+ //std::cout << std::boolalpha << "enter set_price, item_idx = " << item_idx << ", new_price = " << new_price << ", old price = " << this->get_price(item_idx);
+ //std::cout << ", item_is_diagonal = " << item_is_diagonal << ", bidder_is_diagonal = " << bidder_is_diagonal << ", old_owner_type = " << old_owner_type << std::endl;
+
+ bool item_is_normal = not item_is_diagonal;
+ bool bidder_is_normal = not bidder_is_diagonal;
+
+ assert( new_price >= this->get_price(item_idx) );
+
+ // update vector prices
+ if (item_is_normal or bidder_is_normal) {
+ this->prices[item_idx] = new_price;
+ }
+
+ // update kdtree_
+ if (item_is_normal) {
+ assert(0 <= item_idx and item_idx < kdtree__items_.size());
+ assert(0 <= kdtree__items_[item_idx] and kdtree__items_[item_idx] < dnn_point_handles_.size());
+ kdtree_->change_weight( dnn_point_handles_[kdtree__items_[item_idx]], new_price);
+ }
+
+ // update all_items_heap_
+ if (bidder_is_diagonal and item_is_diagonal) {
+ // remove slice (item is buried in diag_assigned_to_diag_slice_)
+ assert(old_owner_type != OwnerType::k_diagonal);
+ auto iter = all_items_heap__iters_[item_idx];
+ assert(iter != all_items_heap_.end());
+ all_items_heap_.erase(iter);
+ all_items_heap__iters_[item_idx] = all_items_heap_.end();
+ } else {
+ auto iter = all_items_heap__iters_[item_idx];
+ if (iter != all_items_heap_.end()) {
+ // update existing element
+ ItemSliceR x = *iter;
+ x.set_loss( this->get_value_for_diagonal_bidder(item_idx) );
+ all_items_heap_.erase(iter);
+ auto ins_res = all_items_heap_.insert(x);
+ all_items_heap__iters_[item_idx] = ins_res.first;
+ assert(ins_res.second);
+ } else {
+ // insert new slice
+ // for diagonal items value = price
+ ItemSliceR x { item_idx, new_price };
+ auto ins_res = all_items_heap_.insert(x);
+ all_items_heap__iters_[item_idx] = ins_res.first;
+ assert(ins_res.second);
+ }
+ }
+
+ // update diag_items_heap_
+ if (item_is_diagonal and bidder_is_normal) {
+ // update existing element
+ auto iter = diag_items_heap__iters_[item_idx];
+ if (iter != diag_items_heap_.end()) {
+ ItemSliceR x = *iter;
+ x.set_loss( new_price );
+ diag_items_heap_.erase(iter);
+ auto ins_res = diag_items_heap_.insert(x);
+ diag_items_heap__iters_[item_idx] = ins_res.first;
+ assert(ins_res.second);
+ } else {
+ // insert new slice
+ // for diagonal items value = price
+ ItemSliceR x { item_idx, new_price };
+ auto ins_res = diag_items_heap_.insert(x);
+ diag_items_heap__iters_[item_idx] = ins_res.first;
+ assert(ins_res.second);
+ }
+ } else if (bidder_is_diagonal and item_is_diagonal ) {
+ // remove slice (item is buried in diag_assigned_to_diag_slice_)
+ assert(old_owner_type != OwnerType::k_diagonal);
+ auto iter = diag_items_heap__iters_[item_idx];
+ assert(iter != diag_items_heap_.end());
+ diag_items_heap_.erase(iter);
+ diag_items_heap__iters_[item_idx] = diag_items_heap_.end();
+ }
+
+ // update diag_unassigned_price_
+ if (item_is_diagonal and old_owner_type == OwnerType::k_none and diag_unassigned_slice_.empty()) {
+ diag_unassigned_price_ = std::numeric_limits<Real>::max();
+ }
+
+}
+
+
+template<class Real_, class PointContainer_>
+bool AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::is_item_diagonal(const size_t item_idx) const
+{
+ return item_idx < this->num_diag_items_;
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::flush_assignment()
+{
+ //std::cout << "enter oracle->flush_assignment" << std::endl;
+ sanity_check();
+
+ for(const auto item_idx : diag_assigned_to_diag_slice_) {
+ diag_unassigned_slice_.insert(item_idx);
+ }
+ diag_assigned_to_diag_slice_.clear();
+
+ // common price of diag-diag items becomes price of diag-unassigned-slice
+ // diag_to_diag_slice is now empty, set its price to max
+ // so that get_optimal_bid works correctly
+ diag_unassigned_price_ = diag_to_diag_price_;
+ diag_to_diag_price_ = std::numeric_limits<Real>::max();
+
+ normal_items_assigned_to_diag_.clear();
+
+ sanity_check();
+}
+
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::adjust_prices()
+{
+ return;
+
+ throw std::runtime_error("not implemented");
+ auto pr_begin = this->prices.begin();
+ auto pr_end = this->prices.end();
+
+ Real min_price = *(std::min_element(pr_begin, pr_end));
+
+ for(auto& p : this->prices) {
+ p -= min_price;
+ }
+
+ kdtree_->adjust_weights(min_price);
+ diag_items_heap_.adjust_prices(min_price);
+ all_items_heap_.adjust_prices(min_price);
+}
+
+
+template<class Real_, class PointContainer_>
+AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::~AuctionOracleKDTreeSingleDiag()
+{
+ delete kdtree_;
+}
+
+template<class Real_, class PointContainer_>
+void AuctionOracleKDTreeSingleDiag<Real_, PointContainer_>::sanity_check()
+{
+#ifdef DEBUG_AUCTION
+
+ //std::cout << "ORACLE CURRENT STATE IN SANITY CHECK" << *this << std::endl;
+
+ assert( diag_items_heap_.size() + diag_assigned_to_diag_slice_.size() + diag_unassigned_slice_.size() == num_diag_items_ );
+ assert( diag_items_heap__iters_.size() == num_diag_items_ );
+ for(size_t i = 0; i < num_diag_items_; ++i) {
+ if (diag_items_heap__iters_.at(i) != diag_items_heap_.end()) {
+ assert(diag_items_heap__iters_[i]->item_idx == i);
+ }
+ }
+
+ assert( all_items_heap_.size() + diag_assigned_to_diag_slice_.size() + diag_unassigned_slice_.size() == this->num_items_ );
+ assert( all_items_heap__iters_.size() == this->num_items_ );
+ for(size_t i = 0; i < this->num_items_; ++i) {
+ if (all_items_heap__iters_.at(i) != all_items_heap_.end()) {
+ assert(all_items_heap__iters_[i]->item_idx == i);
+ } else {
+ assert( i < num_diag_items_ );
+ }
+ }
+
+ for(size_t i = 0; i < num_diag_items_; ++i) {
+ int is_in_assigned_slice = diag_assigned_to_diag_slice_.count(i);
+ int is_in_unassigned_slice = diag_unassigned_slice_.count(i);
+ int is_in_heap = diag_items_heap__iters_[i] != diag_items_heap_.end();
+ assert( is_in_assigned_slice + is_in_unassigned_slice + is_in_heap == 1);
+ }
+
+ //assert((diag_assigned_to_diag_slice_.empty() and diag_to_diag_price_ == std::numeric_limits<Real>::max()) or (not diag_assigned_to_diag_slice_.empty() and diag_to_diag_price_ != std::numeric_limits<Real>::max()));
+ //assert((diag_unassigned_slice_.empty() and diag_unassigned_price_ == std::numeric_limits<Real>::max()) or (not diag_unassigned_slice_.empty() and diag_unassigned_price_ != std::numeric_limits<Real>::max()));
+
+ assert(diag_assigned_to_diag_slice_.empty() or diag_to_diag_price_ != std::numeric_limits<Real>::max());
+ assert(diag_unassigned_slice_.empty() or diag_unassigned_price_ != std::numeric_limits<Real>::max());
+#endif
+}
+
+
+} // ws
+} // hera
+#endif
diff --git a/wasserstein/include/auction_oracle_lazy_heap.h b/wasserstein/include/auction_oracle_lazy_heap.h
new file mode 100644
index 0000000..8b37421
--- /dev/null
+++ b/wasserstein/include/auction_oracle_lazy_heap.h
@@ -0,0 +1,191 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_LAZY_HEAP_H
+#define AUCTION_ORACLE_LAZY_HEAP_H
+
+
+#define USE_BOOST_HEAP
+
+#include <map>
+#include <memory>
+#include <set>
+#include <list>
+
+#ifdef USE_BOOST_HEAP
+#include <boost/heap/d_ary_heap.hpp>
+#endif
+
+#include "basic_defs_ws.h"
+
+namespace ws {
+
+template <typename T>
+struct CompPairsBySecondStruct {
+ bool operator()(const IdxValPair<T>& a, const IdxValPair<T>& b) const
+ {
+ return a.second < b.second;
+ }
+};
+
+
+template <typename T>
+struct CompPairsBySecondGreaterStruct {
+ bool operator()(const IdxValPair<T>& a, const IdxValPair<T>& b) const
+ {
+ return a.second > b.second;
+ }
+};
+
+template <typename T>
+struct CompPairsBySecondLexStruct {
+ bool operator()(const IdxValPair<T>& a, const IdxValPair<T>& b) const
+ {
+ return a.second < b.second or (a.second == b.second and a.first > b.first);
+ }
+};
+
+template <typename T>
+struct CompPairsBySecondLexGreaterStruct {
+ bool operator()(const IdxValPair<T>& a, const IdxValPair<T>& b) const
+ {
+ return a.second > b.second or (a.second == b.second and a.first > b.first);
+ }
+};
+
+using ItemsTimePair = std::pair<IdxType, int>;
+using UpdateList = std::list<ItemsTimePair>;
+using UpdateListIter = UpdateList::iterator;
+
+
+#ifdef USE_BOOST_HEAP
+template <class Real>
+using LossesHeap = boost::heap::d_ary_heap<IdxValPair<Real>, boost::heap::arity<2>, boost::heap::mutable_<true>, boost::heap::compare<CompPairsBySecondGreaterStruct<Real>>>;
+#else
+template<typename T, class ComparisonStruct>
+class IdxValHeap {
+public:
+ using InternalKeeper = std::set<IdxValPair<T>, ComparisonStruct>;
+ using handle_type = typename InternalKeeper::iterator;
+ // methods
+ handle_type push(const IdxValPair<T>& val)
+ {
+ auto res_pair = _heap.insert(val);
+ assert(res_pair.second);
+ assert(res_pair.first != _heap.end());
+ return res_pair.first;
+ }
+
+ void decrease(handle_type& handle, const IdxValPair<T>& new_val)
+ {
+ _heap.erase(handle);
+ handle = push(new_val);
+ }
+
+ void increase(handle_type& handle, const IdxValPair<T>& new_val)
+ {
+ _heap.erase(handle);
+ handle = push(new_val);
+
+ size_t size() const
+ {
+ return _heap.size();
+ }
+
+ handle_type ordered_begin()
+ {
+ return _heap.begin();
+ }
+
+ handle_type ordered_end()
+ {
+ return _heap.end();
+ }
+
+
+private:
+ std::set<IdxValPair<T>, ComparisonStruct> _heap;
+};
+
+// if we store losses, the minimal value should come first
+template <class Real>
+using LossesHeap = IdxValHeap<Real, CompPairsBySecondLexStruct>;
+#endif
+
+
+template <class Real = double>
+struct AuctionOracleLazyHeapRestricted : AuctionOracleBase<Real> {
+
+ using LossesHeapR = typename ws::LossesHeap<Real>;
+ using LossesHeapRHandle = typename ws::LossesHeap<Real>::handle_type;
+ using DiagramPointR = typename ws::DiagramPoint<Real>;
+
+
+ AuctionOracleLazyHeapRestricted(const std::vector<DiagramPointR>& bidders, const std::vector<DiagramPointR>& items, const Real wasserstein_power, const Real _internal_p = get_infinity<Real>());
+ ~AuctionOracleLazyHeapRestricted();
+ // data members
+ // temporarily make everything public
+ std::vector<std::vector<Real>> weight_matrix;
+ //Real weight_adj_const;
+ Real max_val;
+ // vector of heaps to find the best items
+ std::vector<LossesHeapR*> losses_heap;
+ std::vector<std::vector<size_t>> items_indices_for_heap_handles;
+ std::vector<std::vector<LossesHeapRHandle>> losses_heap_handles;
+ // methods
+ void fill_in_losses_heap();
+ void set_price(const IdxType items_idx, const Real new_price);
+ IdxValPair<Real> get_optimal_bid(const IdxType bidder_idx);
+ Real get_matching_weight(const std::vector<IdxType>& bidders_to_items) const;
+ void adjust_prices();
+ // to update the queue in lazy fashion
+ std::vector<UpdateListIter> items_iterators;
+ UpdateList update_list;
+ std::vector<int> bidders_update_moments;
+ int update_counter;
+ void update_queue_for_bidder(const IdxType bidder_idx);
+ LossesHeapR diag_items_heap;
+ std::vector<LossesHeapRHandle> diag_heap_handles;
+ std::vector<size_t> heap_handles_indices;
+ // debug
+
+ DebugOptimalBid<Real> get_optimal_bid_debug(const IdxType bidder_idx);
+
+ // for diagonal points
+ bool best_diagonal_items_computed;
+ size_t best_diagonal_item_idx;
+ Real best_diagonal_item_value;
+ size_t second_best_diagonal_item_idx;
+ Real second_best_diagonal_item_value;
+};
+
+} // end of namespace ws
+
+#include "auction_oracle_lazy_heap.h"
+
+#endif
diff --git a/wasserstein/include/auction_oracle_lazy_heap.hpp b/wasserstein/include/auction_oracle_lazy_heap.hpp
new file mode 100644
index 0000000..d179b3d
--- /dev/null
+++ b/wasserstein/include/auction_oracle_lazy_heap.hpp
@@ -0,0 +1,465 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "auction_oracle.h"
+
+
+#ifdef FOR_R_TDA
+#undef DEBUG_AUCTION
+#endif
+
+namespace ws {
+
+// *****************************
+// AuctionOracleLazyHeapRestricted
+// *****************************
+
+
+template<class Real>
+AuctionOracleLazyHeapRestricted<Real>::AuctionOracleLazyHeapRestricted(const std::vector<DiagramPoint<Real>>& _bidders,
+ const std::vector<DiagramPoint<Real>>& _items,
+ Real _wasserstein_power,
+ Real _internal_p) :
+ AuctionOracleAbstract<Real>(_bidders, _items, _wasserstein_power, _internal_p),
+ max_val(0.0),
+ bidders_update_moments(_bidders.size(), 0),
+ update_counter(0),
+ heap_handles_indices(_items.size(), k_invalid_index),
+ best_diagonal_items_computed(false)
+{
+ weight_matrix.reserve(_bidders.size());
+ //const Real max_dist_upper_bound = 3 * getFurthestDistance3Approx(b, g);
+ //weight_adj_const = pow(max_dist_upper_bound, wasserstein_power);
+ // init weight matrix
+ for(const auto& point_A : _bidders) {
+ std::vector<Real> weight_vec;
+ weight_vec.clear();
+ weight_vec.reserve(_bidders.size());
+ for(const auto& point_B : _items) {
+ Real val = pow(dist_lp(point_A, point_B, _internal_p), _wasserstein_power);
+ weight_vec.push_back( val );
+ if ( val > max_val )
+ max_val = val;
+ }
+ weight_matrix.push_back(weight_vec);
+ }
+ fill_in_losses_heap();
+ for(size_t item_idx = 0; item_idx < _items.size(); ++item_idx) {
+ update_list.push_back(std::make_pair(static_cast<IdxType>(item_idx), 0));
+ }
+ for(auto update_list_iter = update_list.begin(); update_list_iter != update_list.end(); ++update_list_iter) {
+ items_iterators.push_back(update_list_iter);
+ }
+
+ size_t handle_idx {0};
+ for(size_t item_idx = 0; item_idx < _items.size(); ++item_idx) {
+ if (_items[item_idx].is_diagonal() ) {
+ heap_handles_indices[item_idx] = handle_idx++;
+ diag_heap_handles.push_back(diag_items_heap.push(std::make_pair(item_idx, 0)));
+ }
+ }
+}
+
+
+template<class Real>
+void AuctionOracleLazyHeapRestricted<Real>::update_queue_for_bidder(IdxType bidder_idx)
+{
+ assert(0 <= bidder_idx and bidder_idx < static_cast<int>(this->bidders.size()));
+ assert(bidder_idx < static_cast<int>(bidders_update_moments.size()));
+ assert(losses_heap[bidder_idx] != nullptr );
+
+ int bidder_last_update_time = bidders_update_moments[bidder_idx];
+ auto iter = update_list.begin();
+ while (iter != update_list.end() and iter->second >= bidder_last_update_time) {
+ IdxType item_idx = iter->first;
+ size_t handle_idx = items_indices_for_heap_handles[bidder_idx][item_idx];
+ if (handle_idx < this->items.size() ) {
+ IdxValPair<Real> new_val { item_idx, weight_matrix[bidder_idx][item_idx] + this->prices[item_idx]};
+ // to-do: change indexing of losses_heap_handles
+ losses_heap[bidder_idx]->decrease(losses_heap_handles[bidder_idx][handle_idx], new_val);
+ }
+ iter++;
+ }
+ bidders_update_moments[bidder_idx] = update_counter;
+}
+
+
+template<class Real>
+void AuctionOracleLazyHeapRestricted<Real>::fill_in_losses_heap()
+{
+ using LossesHeapR = typename ws::LossesHeap<Real>;
+ using LossesHeapRHandleVec = typename std::vector<typename ws::LossesHeap<Real>::handle_type>;
+
+ for(size_t bidder_idx = 0; bidder_idx < this->bidders.size(); ++bidder_idx) {
+ DiagramPoint<Real> bidder { this->bidders[bidder_idx] };
+ // no heap for diagonal bidders
+ if ( bidder.is_diagonal() ) {
+ losses_heap.push_back( nullptr );
+ losses_heap_handles.push_back(LossesHeapRHandleVec());
+ items_indices_for_heap_handles.push_back( std::vector<size_t>() );
+ continue;
+ } else {
+ losses_heap.push_back( new LossesHeapR() );
+
+ assert( losses_heap.at(bidder_idx) != nullptr );
+
+ items_indices_for_heap_handles.push_back( std::vector<size_t>(this->items.size(), k_invalid_index) );
+ LossesHeapRHandleVec handles_vec;
+ losses_heap_handles.push_back(handles_vec);
+ size_t handle_idx { 0 };
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ assert( items_indices_for_heap_handles.at(bidder_idx).at(item_idx) > 0 );
+ DiagramPoint<Real> item { this->items[item_idx] };
+ if ( item.is_normal() ) {
+ // item can be assigned to bidder, store in heap
+ IdxValPair<Real> vp { item_idx, weight_matrix[bidder_idx][item_idx] + this->prices[item_idx] };
+ losses_heap_handles[bidder_idx].push_back( losses_heap[bidder_idx]->push(vp) );
+ // keep corresponding index in items_indices_for_heap_handles
+ items_indices_for_heap_handles[bidder_idx][item_idx] = handle_idx++;
+ }
+ }
+ }
+ }
+}
+
+
+template<class Real>
+AuctionOracleLazyHeapRestricted<Real>::~AuctionOracleLazyHeapRestricted()
+{
+ for(auto h : losses_heap) {
+ delete h;
+ }
+}
+
+
+template<class Real>
+void AuctionOracleLazyHeapRestricted<Real>::set_price(IdxType item_idx, Real new_price)
+{
+ assert( this->prices.at(item_idx) < new_price );
+#ifdef DEBUG_AUCTION
+ std::cout << "price incremented by " << this->prices.at(item_idx) - new_price << std::endl;
+#endif
+ this->prices[item_idx] = new_price;
+ if (this->items[item_idx].is_normal() ) {
+ // lazy: record the moment we updated the price of the items,
+ // do not update queues.
+ // 1. move the items with updated price to the front of the update_list,
+ update_list.splice(update_list.begin(), update_list, items_iterators[item_idx]);
+ // 2. record the moment we updated the price and increase the counter
+ update_list.front().second = update_counter++;
+ } else {
+ // diagonal items are stored in one heap
+ diag_items_heap.decrease(diag_heap_handles[heap_handles_indices[item_idx]], std::make_pair(item_idx, new_price));
+ best_diagonal_items_computed = false;
+ }
+}
+
+// subtract min. price from all prices
+template<class Real>
+void AuctionOracleLazyHeapRestricted<Real>::adjust_prices()
+{
+}
+
+
+template<class Real>
+DebugOptimalBid<Real> AuctionOracleLazyHeapRestricted<Real>::get_optimal_bid_debug(IdxType bidder_idx)
+{
+ DebugOptimalBid<Real> result;
+ assert(bidder_idx >=0 and bidder_idx < static_cast<IdxType>(this->bidders.size()) );
+
+ auto bidder = this->bidders[bidder_idx];
+ std::vector<IdxValPair<Real>> cand_items;
+ // corresponding point is always considered as a candidate
+
+ size_t proj_item_idx = bidder_idx;
+ assert( 0 <= proj_item_idx and proj_item_idx < this->items.size() );
+ auto proj_item = this->items[proj_item_idx];
+ assert(proj_item.type != bidder.type);
+ //assert(proj_item.proj_id == bidder.id);
+ //assert(proj_item.id == bidder.proj_id);
+ // todo: store precomputed distance?
+ Real proj_item_value = this->get_value_for_bidder(bidder_idx, proj_item_idx);
+ cand_items.push_back( std::make_pair(proj_item_idx, proj_item_value) );
+
+ if (bidder.is_normal()) {
+ assert(losses_heap.at(bidder_idx) != nullptr);
+ assert(losses_heap[bidder_idx]->size() >= 2);
+ update_queue_for_bidder(bidder_idx);
+ auto pHeap = losses_heap[bidder_idx];
+ assert( pHeap != nullptr );
+ auto top_iter = pHeap->ordered_begin();
+ cand_items.push_back( *top_iter );
+ ++top_iter; // now points to the second-best items
+ cand_items.push_back( *top_iter );
+ std::sort(cand_items.begin(), cand_items.end(), CompPairsBySecondStruct<Real>());
+ assert(cand_items[1].second >= cand_items[0].second);
+ } else {
+ // for diagonal bidder the only normal point has already been added
+ // the other 2 candidates are diagonal items only, get from the heap
+ // with prices
+ assert(diag_items_heap.size() > 1);
+ auto top_diag_iter = diag_items_heap.ordered_begin();
+ auto topDiag1 = *top_diag_iter++;
+ auto topDiag2 = *top_diag_iter;
+ cand_items.push_back(topDiag1);
+ cand_items.push_back(topDiag2);
+ std::sort(cand_items.begin(), cand_items.end(), CompPairsBySecondStruct<Real>());
+ assert(cand_items.size() == 3);
+ assert(cand_items[2].second >= cand_items[1].second);
+ assert(cand_items[1].second >= cand_items[0].second);
+ }
+
+ result.best_item_idx = cand_items[0].first;
+ result.second_best_item_idx = cand_items[1].first;
+ result.best_item_value = cand_items[0].second;
+ result.second_best_item_value = cand_items[1].second;
+
+ // checking code
+
+ //DebugOptimalBid<Real> debug_my_result(result);
+ //DebugOptimalBid<Real> debug_naive_result;
+ //debug_naive_result.best_item_value = 1e20;
+ //debug_naive_result.second_best_item_value = 1e20;
+ //Real curr_item_value;
+ //for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ //if ( this->bidders[bidder_idx].type != this->items[item_idx].type and
+ //this->bidders[bidder_idx].proj_id != this->items[item_idx].id)
+ //continue;
+
+ //curr_item_value = pow(dist_lp(this->bidders[bidder_idx], this->items[item_idx]), wasserstein_power) + this->prices[item_idx];
+ //if (curr_item_value < debug_naive_result.best_item_value) {
+ //debug_naive_result.best_item_value = curr_item_value;
+ //debug_naive_result.best_item_idx = item_idx;
+ //}
+ //}
+
+ //for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ //if (item_idx == debug_naive_result.best_item_idx) {
+ //continue;
+ //}
+ //if ( this->bidders[bidder_idx].type != this->items[item_idx].type and
+ //this->bidders[bidder_idx].proj_id != this->items[item_idx].id)
+ //continue;
+
+ //curr_item_value = pow(dist_lp(this->bidders[bidder_idx], this->items[item_idx]), wasserstein_power) + this->prices[item_idx];
+ //if (curr_item_value < debug_naive_result.second_best_item_value) {
+ //debug_naive_result.second_best_item_value = curr_item_value;
+ //debug_naive_result.second_best_item_idx = item_idx;
+ //}
+ //}
+
+ //if ( fabs( debug_my_result.best_item_value - debug_naive_result.best_item_value ) > 1e-6 or
+ //fabs( debug_naive_result.second_best_item_value - debug_my_result.second_best_item_value) > 1e-6 ) {
+ //std::cerr << "bidder_idx = " << bidder_idx << "; ";
+ //std::cerr << this->bidders[bidder_idx] << std::endl;
+ //for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ //std::cout << item_idx << ": " << this->items[item_idx] << "; price = " << this->prices[item_idx] << std::endl;
+ //}
+ //std::cerr << "debug_my_result: " << debug_my_result << std::endl;
+ //std::cerr << "debug_naive_result: " << debug_naive_result << std::endl;
+ //auto pHeap = losses_heap[bidder_idx];
+ //assert( pHeap != nullptr );
+ //for(auto top_iter = pHeap->ordered_begin(); top_iter != pHeap->ordered_end(); ++top_iter) {
+ //std::cerr << "in heap: " << top_iter->first << ": " << top_iter->second << "; real value = " << dist_lp(bidder, this->items[top_iter->first]) + this->prices[top_iter->first] << std::endl;
+ //}
+ //for(auto ci : cand_items) {
+ //std::cout << "ci.idx = " << ci.first << ", value = " << ci.second << std::endl;
+ //}
+
+ ////std::cerr << "two_best_items: " << two_best_items[0].d << " " << two_best_items[1].d << std::endl;
+ //assert(false);
+ //}
+
+
+ //std::cout << "get_optimal_bid: bidder_idx = " << bidder_idx << "; best_item_idx = " << best_item_idx << "; best_item_value = " << best_item_value << "; best_items_price = " << this->prices[best_item_idx] << "; second_best_item_idx = " << top_iter->first << "; second_best_value = " << second_best_item_value << "; second_best_price = " << this->prices[top_iter->first] << "; bid = " << this->prices[best_item_idx] + ( best_item_value - second_best_item_value ) + epsilon << "; epsilon = " << epsilon << std::endl;
+ //std::cout << "get_optimal_bid: bidder_idx = " << bidder_idx << "; best_item_idx = " << best_item_idx << "; best_items_dist= " << (weight_adj_const - best_item_value) << "; best_items_price = " << this->prices[best_item_idx] << "; second_best_item_idx = " << top_iter->first << "; second_best_dist= " << (weight_adj_const - second_best_item_value) << "; second_best_price = " << this->prices[top_iter->first] << "; bid = " << this->prices[best_item_idx] + ( best_item_value - second_best_item_value ) + epsilon << "; epsilon = " << epsilon << std::endl;
+
+ return result;
+}
+
+
+template<class Real>
+IdxValPair<Real> AuctionOracleLazyHeapRestricted<Real>::get_optimal_bid(const IdxType bidder_idx)
+{
+ IdxType best_item_idx;
+ //IdxType second_best_item_idx;
+ Real best_item_value;
+ Real second_best_item_value;
+
+ auto& bidder = this->bidders[bidder_idx];
+ IdxType proj_item_idx = bidder_idx;
+ assert( 0 <= proj_item_idx and proj_item_idx < this->items.size() );
+ auto proj_item = this->items[proj_item_idx];
+ assert(proj_item.type != bidder.type);
+ //assert(proj_item.proj_id == bidder.id);
+ //assert(proj_item.id == bidder.proj_id);
+ // todo: store precomputed distance?
+ Real proj_item_value = this->get_value_for_bidder(bidder_idx, proj_item_idx);
+
+ if (bidder.is_diagonal()) {
+ // for diagonal bidder the only normal point has already been added
+ // the other 2 candidates are diagonal items only, get from the heap
+ // with prices
+ assert(diag_items_heap.size() > 1);
+ if (!best_diagonal_items_computed) {
+ auto top_diag_iter = diag_items_heap.ordered_begin();
+ best_diagonal_item_idx = top_diag_iter->first;
+ best_diagonal_item_value = top_diag_iter->second;
+ top_diag_iter++;
+ second_best_diagonal_item_idx = top_diag_iter->first;
+ second_best_diagonal_item_value = top_diag_iter->second;
+ best_diagonal_items_computed = true;
+ }
+
+ if ( proj_item_value < best_diagonal_item_value) {
+ best_item_idx = proj_item_idx;
+ best_item_value = proj_item_value;
+ second_best_item_value = best_diagonal_item_value;
+ //second_best_item_idx = best_diagonal_item_idx;
+ } else if (proj_item_value < second_best_diagonal_item_value) {
+ best_item_idx = best_diagonal_item_idx;
+ best_item_value = best_diagonal_item_value;
+ second_best_item_value = proj_item_value;
+ //second_best_item_idx = proj_item_idx;
+ } else {
+ best_item_idx = best_diagonal_item_idx;
+ best_item_value = best_diagonal_item_value;
+ second_best_item_value = second_best_diagonal_item_value;
+ //second_best_item_idx = second_best_diagonal_item_idx;
+ }
+ } else {
+ // for normal bidder get 2 best items among non-diagonal (=normal) points
+ // from the corresponding heap
+ assert(diag_items_heap.size() > 1);
+ update_queue_for_bidder(bidder_idx);
+ auto top_norm_iter = losses_heap[bidder_idx]->ordered_begin();
+ IdxType best_normal_item_idx { top_norm_iter->first };
+ Real best_normal_item_value { top_norm_iter->second };
+ top_norm_iter++;
+ Real second_best_normal_item_value { top_norm_iter->second };
+ //IdxType second_best_normal_item_idx { top_norm_iter->first };
+
+ if ( proj_item_value < best_normal_item_value) {
+ best_item_idx = proj_item_idx;
+ best_item_value = proj_item_value;
+ second_best_item_value = best_normal_item_value;
+ //second_best_item_idx = best_normal_item_idx;
+ } else if (proj_item_value < second_best_normal_item_value) {
+ best_item_idx = best_normal_item_idx;
+ best_item_value = best_normal_item_value;
+ second_best_item_value = proj_item_value;
+ //second_best_item_idx = proj_item_idx;
+ } else {
+ best_item_idx = best_normal_item_idx;
+ best_item_value = best_normal_item_value;
+ second_best_item_value = second_best_normal_item_value;
+ //second_best_item_idx = second_best_normal_item_idx;
+ }
+ }
+
+ IdxValPair<Real> result;
+
+ assert( second_best_item_value >= best_item_value );
+
+ result.first = best_item_idx;
+ result.second = ( second_best_item_value - best_item_value ) + this->prices[best_item_idx] + this->epsilon;
+
+
+ // checking code
+
+ //DebugOptimalBid<Real> debug_my_result;
+ //debug_my_result.best_item_idx = best_item_idx;
+ //debug_my_result.best_item_value = best_item_value;
+ //debug_my_result.second_best_item_idx = second_best_item_idx;
+ //debug_my_result.second_best_item_value = second_best_item_value;
+ //DebugOptimalBid<Real> debug_naive_result;
+ //debug_naive_result.best_item_value = 1e20;
+ //debug_naive_result.second_best_item_value = 1e20;
+ //Real curr_item_value;
+ //for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ //if ( this->bidders[bidder_idx].type != this->items[item_idx].type and
+ //this->bidders[bidder_idx].proj_id != this->items[item_idx].id)
+ //continue;
+
+ //curr_item_value = this->get_value_for_bidder(bidder_idx, item_idx);
+ //if (curr_item_value < debug_naive_result.best_item_value) {
+ //debug_naive_result.best_item_value = curr_item_value;
+ //debug_naive_result.best_item_idx = item_idx;
+ //}
+ //}
+
+ //for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ //if (item_idx == debug_naive_result.best_item_idx) {
+ //continue;
+ //}
+ //if ( this->bidders[bidder_idx].type != this->items[item_idx].type and
+ //this->bidders[bidder_idx].proj_id != this->items[item_idx].id)
+ //continue;
+
+ //curr_item_value = this->get_value_for_bidder(bidder_idx, item_idx);
+ //if (curr_item_value < debug_naive_result.second_best_item_value) {
+ //debug_naive_result.second_best_item_value = curr_item_value;
+ //debug_naive_result.second_best_item_idx = item_idx;
+ //}
+ //}
+ ////std::cout << "got naive result" << std::endl;
+
+ //if ( fabs( debug_my_result.best_item_value - debug_naive_result.best_item_value ) > 1e-6 or
+ //fabs( debug_naive_result.second_best_item_value - debug_my_result.second_best_item_value) > 1e-6 ) {
+ //std::cerr << "bidder_idx = " << bidder_idx << "; ";
+ //std::cerr << this->bidders[bidder_idx] << std::endl;
+ //for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ //std::cout << item_idx << ": " << this->items[item_idx] << "; price = " << this->prices[item_idx] << std::endl;
+ //}
+ //std::cerr << "debug_my_result: " << debug_my_result << std::endl;
+ //std::cerr << "debug_naive_result: " << debug_naive_result << std::endl;
+ //auto pHeap = losses_heap[bidder_idx];
+ //if ( pHeap != nullptr ) {
+ //for(auto top_iter = pHeap->ordered_begin(); top_iter != pHeap->ordered_end(); ++top_iter) {
+ //std::cerr << "in heap: " << top_iter->first << ": " << top_iter->second << "; real value = " << dist_lp(bidder, this->items[top_iter->first]) + this->prices[top_iter->first] << std::endl;
+ //}
+ //}
+ ////for(auto ci : cand_items) {
+ ////std::cout << "ci.idx = " << ci.first << ", value = " << ci.second << std::endl;
+ ////}
+
+ ////std::cerr << "two_best_items: " << two_best_items[0].d << " " << two_best_items[1].d << std::endl;
+ //assert(false);
+ // }
+ //std::cout << "get_optimal_bid: bidder_idx = " << bidder_idx << "; best_item_idx = " << best_item_idx << "; best_item_value = " << best_item_value << "; best_items_price = " << this->prices[best_item_idx] << "; second_best_item_idx = " << top_iter->first << "; second_best_value = " << second_best_item_value << "; second_best_price = " << this->prices[top_iter->first] << "; bid = " << this->prices[best_item_idx] + ( best_item_value - second_best_item_value ) + epsilon << "; epsilon = " << epsilon << std::endl;
+ //std::cout << "get_optimal_bid: bidder_idx = " << bidder_idx << "; best_item_idx = " << best_item_idx << "; best_items_dist= " << (weight_adj_const - best_item_value) << "; best_items_price = " << this->prices[best_item_idx] << "; second_best_item_idx = " << top_iter->first << "; second_best_dist= " << (weight_adj_const - second_best_item_value) << "; second_best_price = " << this->prices[top_iter->first] << "; bid = " << this->prices[best_item_idx] + ( best_item_value - second_best_item_value ) + epsilon << "; epsilon = " << epsilon << std::endl;
+
+ return result;
+}
+
+} // end of namespace ws
diff --git a/wasserstein/include/auction_oracle_stupid_sparse_restricted.h b/wasserstein/include/auction_oracle_stupid_sparse_restricted.h
new file mode 100644
index 0000000..df63daf
--- /dev/null
+++ b/wasserstein/include/auction_oracle_stupid_sparse_restricted.h
@@ -0,0 +1,112 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_ORACLE_STUPID_SPARSE_RESTRICTED_H
+#define AUCTION_ORACLE_STUPID_SPARSE_RESTRICTED_H
+
+#include <map>
+#include <memory>
+#include <set>
+
+#include "basic_defs_ws.h"
+#include "diagonal_heap.h"
+#include "auction_oracle_base.h"
+#include "dnn/geometry/euclidean-fixed.h"
+#include "dnn/local/kd-tree.h"
+
+
+namespace hera {
+namespace ws {
+
+template <int k_max_nn, class Real_ = double, class PointContainer_ = std::vector<DiagramPoint<Real_>>>
+struct AuctionOracleStupidSparseRestricted : AuctionOracleBase<Real_, PointContainer_> {
+
+ using PointContainer = PointContainer_;
+ using Real = Real_;
+
+ using LossesHeapR = typename ws::LossesHeapOld<Real>;
+ using LossesHeapRHandle = typename ws::LossesHeapOld<Real>::handle_type;
+ using DiagramPointR = typename ws::DiagramPoint<Real>;
+ using DebugOptimalBidR = typename ws::DebugOptimalBid<Real>;
+
+ using DnnPoint = dnn::Point<2, Real>;
+ using DnnTraits = dnn::PointTraits<DnnPoint>;
+
+
+ AuctionOracleStupidSparseRestricted(const PointContainer& bidders, const PointContainer& items, const AuctionParams<Real>& params);
+ // data members
+ // temporarily make everything public
+ std::vector<std::vector<size_t>> admissible_items_;
+ Real max_val_;
+ LossesHeapR diag_items_heap_;
+ std::vector<LossesHeapRHandle> diag_heap_handles_;
+ std::vector<size_t> heap_handles_indices_;
+
+// std::vector<size_t> kdtree_items_;
+
+ std::vector<size_t> top_diag_indices_;
+ std::vector<size_t> top_diag_lookup_;
+ size_t top_diag_counter_ { 0 };
+ bool best_diagonal_items_computed_ { false };
+ Real best_diagonal_item_value_;
+ Real second_best_diagonal_item_idx_ { k_invalid_index };
+ Real second_best_diagonal_item_value_ { std::numeric_limits<Real>::max() };
+
+
+ // methods
+ void set_price(const IdxType items_idx, const Real new_price, const bool update_diag = true);
+ IdxValPair<Real> get_optimal_bid(const IdxType bidder_idx);
+ void adjust_prices();
+ void adjust_prices(const Real delta);
+
+ // debug routines
+ DebugOptimalBidR get_optimal_bid_debug(IdxType bidder_idx) const;
+ void sanity_check();
+
+
+ // heap top vector
+ size_t get_heap_top_size() const;
+ void recompute_top_diag_items(bool hard = false);
+ void recompute_second_best_diag();
+ void reset_top_diag_counter();
+ void increment_top_diag_counter();
+ void add_top_diag_index(const size_t item_idx);
+ void remove_top_diag_index(const size_t item_idx);
+ bool is_in_top_diag_indices(const size_t item_idx) const;
+
+ std::pair<Real, Real> get_minmax_price() const;
+
+};
+
+} // ws
+} // hera
+
+
+#include "auction_oracle_stupid_sparse_restricted.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_oracle_stupid_sparse_restricted.hpp b/wasserstein/include/auction_oracle_stupid_sparse_restricted.hpp
new file mode 100644
index 0000000..9df2874
--- /dev/null
+++ b/wasserstein/include/auction_oracle_stupid_sparse_restricted.hpp
@@ -0,0 +1,521 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+#ifndef AUCTION_ORACLE_STUPID_SPARSE_HPP
+#define AUCTION_ORACLE_STUPID_SPARSE_HPP
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "basic_defs_ws.h"
+#include "auction_oracle_stupid_sparse_restricted.h"
+
+#ifdef FOR_R_TDA
+#undef DEBUG_AUCTION
+#endif
+
+namespace hera {
+namespace ws {
+
+
+// *****************************
+// AuctionOracleStupidSparseRestricted
+// *****************************
+
+
+template <int k_max_nn, class Real_, class PointContainer_>
+std::ostream& operator<<(std::ostream& output, const AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>& oracle)
+{
+ output << "Oracle: " << &oracle << std::endl;
+ output << "max_val_ = " << oracle.max_val_ << ", ";
+ output << "best_diagonal_items_computed_ = " << oracle.best_diagonal_items_computed_ << ", ";
+ output << "best_diagonal_item_value_ = " << oracle.best_diagonal_item_value_ << ", ";
+ output << "second_best_diagonal_item_idx_ = " << oracle.second_best_diagonal_item_idx_ << ", ";
+ output << "second_best_diagonal_item_value_ = " << oracle.second_best_diagonal_item_value_ << ", ";
+ output << "prices = " << format_container_to_log(oracle.prices) << "\n";
+ output << "diag_items_heap_ = " << losses_heap_to_string(oracle.diag_items_heap_) << "\n";
+ output << "top_diag_indices_ = " << format_container_to_log(oracle.top_diag_indices_) << "\n";
+ output << "top_diag_counter_ = " << oracle.top_diag_counter_ << "\n";
+ output << "top_diag_lookup_ = " << format_container_to_log(oracle.top_diag_lookup_) << "\n";
+ output << "end of oracle " << &oracle << std::endl;
+ return output;
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::AuctionOracleStupidSparseRestricted(const PointContainer_& _bidders,
+ const PointContainer_& _items,
+ const AuctionParams<Real_>& params) :
+ AuctionOracleBase<Real_, PointContainer_>(_bidders, _items, params),
+ admissible_items_(_bidders.size(), std::vector<size_t>()),
+ heap_handles_indices_(_items.size(), k_invalid_index),
+ top_diag_lookup_(_items.size(), k_invalid_index)
+{
+ // initialize admissible edges
+ std::vector<size_t> kdtree_items_(_items.size(), k_invalid_index);
+ std::vector<DnnPoint> dnn_points_;
+ std::vector<DnnPoint*> dnn_point_handles_;
+ size_t dnn_item_idx { 0 };
+ size_t true_idx { 0 };
+ dnn_points_.reserve(this->items.size());
+ // store normal items in kd-tree
+ for(const auto& g : this->items) {
+ if (g.is_normal() ) {
+ kdtree_items_[true_idx] = dnn_item_idx;
+ // index of items is id of dnn-point
+ DnnPoint p(true_idx);
+ p[0] = g.getRealX();
+ p[1] = g.getRealY();
+ dnn_points_.push_back(p);
+ assert(dnn_item_idx == dnn_points_.size() - 1);
+ dnn_item_idx++;
+ }
+ true_idx++;
+ }
+ assert(dnn_points_.size() < _items.size() );
+ for(size_t i = 0; i < dnn_points_.size(); ++i) {
+ dnn_point_handles_.push_back(&dnn_points_[i]);
+ }
+ DnnTraits traits;
+ traits.internal_p = params.internal_p;
+ dnn::KDTree<DnnTraits> kdtree_(traits, dnn_point_handles_, params.wasserstein_power);
+
+ // loop over normal bidders, find nearest neighbours
+ size_t bidder_idx = 0;
+ for(const auto& b : this->bidders) {
+ if (b.is_normal()) {
+ admissible_items_[bidder_idx].reserve(k_max_nn);
+ DnnPoint bidder_dnn;
+ bidder_dnn[0] = b.getRealX();
+ bidder_dnn[1] = b.getRealY();
+ auto nearest_neighbours = kdtree_.findK(bidder_dnn, k_max_nn);
+ assert(nearest_neighbours.size() == k_max_nn);
+ for(const auto& x : nearest_neighbours) {
+ admissible_items_[bidder_idx].push_back(x.p->id());
+ }
+ }
+ bidder_idx++;
+ }
+
+ size_t handle_idx {0};
+ for(size_t item_idx = 0; item_idx < _items.size(); ++item_idx) {
+ if (this->items[item_idx].is_diagonal()) {
+ heap_handles_indices_[item_idx] = handle_idx++;
+ diag_heap_handles_.push_back(diag_items_heap_.push(std::make_pair(item_idx, 0.0)));
+ }
+ }
+ max_val_ = 3*getFurthestDistance3Approx<>(_bidders, _items, params.internal_p);
+ max_val_ = std::pow(max_val_, params.wasserstein_power);
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+bool AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::is_in_top_diag_indices(const size_t item_idx) const
+{
+ return top_diag_lookup_[item_idx] != k_invalid_index;
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::add_top_diag_index(const size_t item_idx)
+{
+ assert(find(top_diag_indices_.begin(), top_diag_indices_.end(), item_idx) == top_diag_indices_.end());
+ assert(this->items[item_idx].is_diagonal());
+
+ top_diag_indices_.push_back(item_idx);
+ top_diag_lookup_[item_idx] = top_diag_indices_.size() - 1;
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::remove_top_diag_index(const size_t item_idx)
+{
+ if (top_diag_indices_.size() > 1) {
+ // remove item_idx from top_diag_indices after swapping
+ // it with the last element, update index lookup appropriately
+ auto old_index = top_diag_lookup_[item_idx];
+ auto end_element = top_diag_indices_.back();
+ std::swap(top_diag_indices_[old_index], top_diag_indices_.back());
+ top_diag_lookup_[end_element] = old_index;
+ }
+
+ top_diag_indices_.pop_back();
+ top_diag_lookup_[item_idx] = k_invalid_index;
+ if (top_diag_indices_.size() < 2) {
+ recompute_second_best_diag();
+ }
+ best_diagonal_items_computed_ = not top_diag_indices_.empty();
+ reset_top_diag_counter();
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::increment_top_diag_counter()
+{
+ assert(top_diag_counter_ >= 0 and top_diag_counter_ < top_diag_indices_.size());
+
+ ++top_diag_counter_;
+ if (top_diag_counter_ >= top_diag_indices_.size()) {
+ top_diag_counter_ -= top_diag_indices_.size();
+ }
+
+ assert(top_diag_counter_ >= 0 and top_diag_counter_ < top_diag_indices_.size());
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::reset_top_diag_counter()
+{
+ top_diag_counter_ = 0;
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::recompute_top_diag_items(bool hard)
+{
+ assert(hard or top_diag_indices_.empty());
+
+ if (hard) {
+ std::fill(top_diag_lookup_.begin(), top_diag_lookup_.end(), k_invalid_index);
+ top_diag_indices_.clear();
+ }
+
+ auto top_diag_iter = diag_items_heap_.ordered_begin();
+ best_diagonal_item_value_ = top_diag_iter->second;
+ add_top_diag_index(top_diag_iter->first);
+
+ ++top_diag_iter;
+
+ // traverse the heap while we see the same value
+ while(top_diag_iter != diag_items_heap_.ordered_end()) {
+ if ( top_diag_iter->second != best_diagonal_item_value_) {
+ break;
+ } else {
+ add_top_diag_index(top_diag_iter->first);
+ }
+ ++top_diag_iter;
+ }
+
+ recompute_second_best_diag();
+
+ best_diagonal_items_computed_ = true;
+ reset_top_diag_counter();
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+typename AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::DebugOptimalBidR
+AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::get_optimal_bid_debug(IdxType bidder_idx) const
+{
+ DebugOptimalBidR result;
+ throw std::runtime_error("Not implemented");
+ return result;
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+IdxValPair<Real_> AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::get_optimal_bid(IdxType bidder_idx)
+{
+ auto bidder = this->bidders[bidder_idx];
+
+ // corresponding point is always considered as a candidate
+ // if bidder is a diagonal point, proj_item is a normal point,
+ // and vice versa.
+
+ size_t best_item_idx { k_invalid_index };
+ size_t second_best_item_idx { k_invalid_index };
+ size_t best_diagonal_item_idx { k_invalid_index };
+ Real best_item_value;
+ Real second_best_item_value;
+
+
+ size_t proj_item_idx = bidder_idx;
+ assert( 0 <= proj_item_idx and proj_item_idx < this->items.size() );
+ assert(this->items[proj_item_idx].type != bidder.type);
+ Real proj_item_value = this->get_value_for_bidder(bidder_idx, proj_item_idx);
+
+ if (bidder.is_diagonal()) {
+ // for diagonal bidder the only normal point has already been added
+ // the other 2 candidates are diagonal items only, get from the heap
+ // with prices
+
+ if (not best_diagonal_items_computed_) {
+ recompute_top_diag_items();
+ }
+
+ best_diagonal_item_idx = top_diag_indices_[top_diag_counter_];
+ increment_top_diag_counter();
+
+ if ( proj_item_value < best_diagonal_item_value_) {
+ best_item_idx = proj_item_idx;
+ best_item_value = proj_item_value;
+ second_best_item_value = best_diagonal_item_value_;
+ second_best_item_idx = best_diagonal_item_idx;
+ } else if (proj_item_value < second_best_diagonal_item_value_) {
+ best_item_idx = best_diagonal_item_idx;
+ best_item_value = best_diagonal_item_value_;
+ second_best_item_value = proj_item_value;
+ second_best_item_idx = proj_item_idx;
+ } else {
+ best_item_idx = best_diagonal_item_idx;
+ best_item_value = best_diagonal_item_value_;
+ second_best_item_value = second_best_diagonal_item_value_;
+ second_best_item_idx = second_best_diagonal_item_idx_;
+ }
+ } else {
+
+ size_t best_normal_item_idx { k_invalid_index };
+ size_t second_best_normal_item_idx { k_invalid_index };
+ Real best_normal_item_value { std::numeric_limits<Real>::max() };
+ Real second_best_normal_item_value { std::numeric_limits<Real>::max() };
+
+ // find best item
+ for(const auto curr_item_idx : admissible_items_[bidder_idx]) {
+ auto curr_item_value = this->get_value_for_bidder(bidder_idx, curr_item_idx);
+ if (curr_item_value < best_normal_item_value) {
+ best_normal_item_idx = curr_item_idx;
+ best_normal_item_value = curr_item_value;
+ }
+ }
+
+ // find second-best item
+ for(const auto curr_item_idx : admissible_items_[bidder_idx]) {
+ if (curr_item_idx == best_normal_item_idx) {
+ continue;
+ }
+ auto curr_item_value = this->get_value_for_bidder(bidder_idx, curr_item_idx);
+ if (curr_item_value < second_best_normal_item_value) {
+ second_best_normal_item_idx = curr_item_idx;
+ second_best_normal_item_value = curr_item_value;
+ }
+ }
+
+ if ( proj_item_value < best_normal_item_value) {
+ best_item_idx = proj_item_idx;
+ increment_top_diag_counter();
+ best_item_value = proj_item_value;
+ second_best_item_value = best_normal_item_value;
+ } else if (proj_item_value < second_best_normal_item_value) {
+ best_item_idx = best_normal_item_idx;
+ best_item_value = best_normal_item_value;
+ second_best_item_value = proj_item_value;
+ } else {
+ best_item_idx = best_normal_item_idx;
+ best_item_value = best_normal_item_value;
+ second_best_item_value = second_best_normal_item_value;
+ }
+ }
+
+ IdxValPair<Real> result;
+
+ assert( second_best_item_value >= best_item_value );
+
+ result.first = best_item_idx;
+ result.second = ( second_best_item_value - best_item_value ) + this->prices[best_item_idx] + this->epsilon;
+
+ return result;
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::recompute_second_best_diag()
+{
+ if (top_diag_indices_.size() > 1) {
+ second_best_diagonal_item_value_ = best_diagonal_item_value_;
+ second_best_diagonal_item_idx_ = top_diag_indices_[0];
+ } else {
+ if (diag_items_heap_.size() == 1) {
+ second_best_diagonal_item_value_ == std::numeric_limits<Real>::max();
+ second_best_diagonal_item_idx_ = k_invalid_index;
+ } else {
+ auto diag_iter = diag_items_heap_.ordered_begin();
+ ++diag_iter;
+ second_best_diagonal_item_value_ = diag_iter->second;
+ second_best_diagonal_item_idx_ = diag_iter->first;
+ }
+ }
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::set_price(IdxType item_idx,
+ Real new_price,
+ const bool update_diag)
+{
+ assert(this->prices.size() == this->items.size());
+ assert( 0 < diag_heap_handles_.size() and diag_heap_handles_.size() <= this->items.size());
+ // adjust_prices decreases prices,
+ // also this variable must be true in reverse phases of FR-auction
+ bool item_goes_down = new_price > this->prices[item_idx];
+
+ this->prices[item_idx] = new_price;
+ if ( this->items[item_idx].is_diagonal() ) {
+ assert(diag_heap_handles_.size() > heap_handles_indices_.at(item_idx));
+ if (item_goes_down) {
+ diag_items_heap_.decrease(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ } else {
+ diag_items_heap_.increase(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ }
+ if (update_diag) {
+ // Update top_diag_indices_ only if necessary:
+ // normal bidders take their projections, which might not be on top
+ // also, set_price is called by adjust_prices, and we may have already
+ // removed the item from top_diag
+ if (is_in_top_diag_indices(item_idx)) {
+ remove_top_diag_index(item_idx);
+ }
+
+ if (item_idx == second_best_diagonal_item_idx_) {
+ recompute_second_best_diag();
+ }
+ }
+ }
+}
+
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::adjust_prices(Real delta)
+{
+ if (delta == 0.0)
+ return;
+
+ for(auto& p : this->prices) {
+ p -= delta;
+ }
+
+ bool price_goes_up = delta < 0;
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ if (this->items[item_idx].is_diagonal()) {
+ auto new_price = this->prices[item_idx];
+ if (price_goes_up) {
+ diag_items_heap_.decrease(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ } else {
+ diag_items_heap_.increase(diag_heap_handles_[heap_handles_indices_[item_idx]], std::make_pair(item_idx, new_price));
+ }
+ }
+ }
+ best_diagonal_item_value_ -= delta;
+ second_best_diagonal_item_value_ -= delta;
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::adjust_prices()
+{
+ auto pr_begin = this->prices.begin();
+ auto pr_end = this->prices.end();
+ Real min_price = *(std::min_element(pr_begin, pr_end));
+ adjust_prices(min_price);
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+size_t AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::get_heap_top_size() const
+{
+ return top_diag_indices_.size();
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+std::pair<Real_, Real_> AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::get_minmax_price() const
+{
+ auto r = std::minmax_element(this->prices.begin(), this->prices.end());
+ return std::make_pair(*r.first, *r.second);
+}
+
+template<int k_max_nn, class Real_, class PointContainer_>
+void AuctionOracleStupidSparseRestricted<k_max_nn, Real_, PointContainer_>::sanity_check()
+{
+#ifdef DEBUG_STUPID_SPARSE_RESTR_ORACLE
+
+ assert(admissible_items_.size() == this->bidders.size());
+
+ for(size_t bidder_idx = 0; bidder_idx < this->bidders.size(); ++bidder_idx) {
+ if (this->bidders[bidder_idx].is_normal()) {
+ assert(admissible_items_[bidder_idx].size() == k_max_nn);
+ } else {
+ assert(admissible_items_[bidder_idx].size() == 0);
+ }
+ }
+
+ if (best_diagonal_items_computed_) {
+ std::vector<Real> diag_items_price_vec;
+ diag_items_price_vec.reserve(this->items.size());
+
+ for(size_t item_idx = 0; item_idx < this->items.size(); ++item_idx) {
+ if (this->items.at(item_idx).is_diagonal()) {
+ diag_items_price_vec.push_back(this->prices.at(item_idx));
+ } else {
+ diag_items_price_vec.push_back(std::numeric_limits<Real>::max());
+ }
+ }
+
+ auto best_iter = std::min_element(diag_items_price_vec.begin(), diag_items_price_vec.end());
+ assert(best_iter != diag_items_price_vec.end());
+ Real true_best_diag_value = *best_iter;
+ size_t true_best_diag_idx = best_iter - diag_items_price_vec.begin();
+ assert(true_best_diag_value != std::numeric_limits<Real>::max());
+
+ Real true_second_best_diag_value = std::numeric_limits<Real>::max();
+ size_t true_second_best_diag_idx = k_invalid_index;
+ for(size_t item_idx = 0; item_idx < diag_items_price_vec.size(); ++item_idx) {
+ if (this->items.at(item_idx).is_normal()) {
+ assert(top_diag_lookup_.at(item_idx) == k_invalid_index);
+ continue;
+ }
+
+ auto i_iter = std::find(top_diag_indices_.begin(), top_diag_indices_.end(), item_idx);
+ if (diag_items_price_vec.at(item_idx) == true_best_diag_value) {
+ assert(i_iter != top_diag_indices_.end());
+ assert(top_diag_lookup_.at(item_idx) == i_iter - top_diag_indices_.begin());
+ } else {
+ assert(top_diag_lookup_.at(item_idx) == k_invalid_index);
+ assert(i_iter == top_diag_indices_.end());
+ }
+
+ if (item_idx == true_best_diag_idx) {
+ continue;
+ }
+ if (diag_items_price_vec.at(item_idx) < true_second_best_diag_value) {
+ true_second_best_diag_value = diag_items_price_vec.at(item_idx);
+ true_second_best_diag_idx = item_idx;
+ }
+ }
+
+ if (true_best_diag_value != best_diagonal_item_value_) {
+ std::cerr << *this;
+ }
+
+ assert(true_best_diag_value == best_diagonal_item_value_);
+
+ assert(true_second_best_diag_idx != k_invalid_index);
+ assert(true_second_best_diag_value == second_best_diagonal_item_value_);
+ }
+#endif
+}
+
+
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/auction_runner_fr.h b/wasserstein/include/auction_runner_fr.h
new file mode 100644
index 0000000..0c67b65
--- /dev/null
+++ b/wasserstein/include/auction_runner_fr.h
@@ -0,0 +1,272 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_RUNNER_FR_H
+#define AUCTION_RUNNER_FR_H
+
+#define ORDERED_BY_PERSISTENCE
+
+#include <unordered_set>
+
+#include "auction_oracle.h"
+
+namespace hera {
+namespace ws {
+
+// the two parameters that you can tweak in auction algorithm are:
+// 1. epsilon_common_ratio
+// 2. max_num_phases
+
+template<class RealType_, class AuctionOracle_ = AuctionOracleKDTreeRestricted<RealType_>> // alternatively: AuctionOracleLazyHeap --- TODO
+class AuctionRunnerFR {
+public:
+
+ using Real = RealType_;
+ using AuctionOracle = AuctionOracle_;
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointVec = std::vector<DgmPoint>;
+ using IdxValPairR = IdxValPair<Real>;
+
+ const Real k_lowest_bid_value = -(std::numeric_limits<Real>::max() - 1); // all bid values must be positive
+
+
+ AuctionRunnerFR(const std::vector<DgmPoint>& A,
+ const std::vector<DgmPoint>& B,
+ const Real q,
+ const Real _delta,
+ const Real _internal_p,
+ const Real _initial_epsilon = 0.0,
+ const Real _eps_factor = 5.0,
+ const int _max_num_phases = std::numeric_limits<int>::max(),
+ const Real _gamma_threshold = 0.0,
+ const size_t _max_bids_per_round = std::numeric_limits<size_t>::max(),
+ const std::string& _log_filename_prefix = "");
+
+ void set_epsilon(Real new_val);
+ Real get_epsilon() const { return epsilon; }
+ void run_auction();
+ Real get_wasserstein_distance();
+ Real get_wasserstein_cost();
+ Real get_relative_error(const bool debug_output = false) const;
+ bool phase_can_be_final() const;
+private:
+ // private data
+ std::vector<DgmPoint> bidders, items;
+ const size_t num_bidders;
+ const size_t num_items;
+ std::vector<IdxType> items_to_bidders;
+ std::vector<IdxType> bidders_to_items;
+ Real wasserstein_power;
+ Real epsilon;
+ Real delta;
+ Real internal_p;
+ Real initial_epsilon;
+ const Real epsilon_common_ratio; // next epsilon = current epsilon / epsilon_common_ratio
+ Real cumulative_epsilon_factor { 1.0 };
+ const int max_num_phases; // maximal number of phases of epsilon-scaling
+ bool is_forward { true }; // to use in distributed version only
+ Real weight_adj_const;
+ Real wasserstein_cost;
+ std::vector<IdxValPairR> forward_bid_table;
+ std::vector<IdxValPairR> reverse_bid_table;
+ // to get the 2 best items
+ AuctionOracle forward_oracle;
+ AuctionOracle reverse_oracle;
+ std::unordered_set<size_t> unassigned_bidders;
+ std::unordered_set<size_t> unassigned_items;
+ std::unordered_set<size_t> items_with_bids;
+ std::unordered_set<size_t> bidders_with_bids;
+
+#ifdef ORDERED_BY_PERSISTENCE
+ // to process unassigned by persistence
+ size_t batch_size;
+ using RealIdxPair = std::pair<Real, size_t>;
+ std::set<RealIdxPair, std::greater<RealIdxPair>> unassigned_bidders_by_persistence;
+ std::set<RealIdxPair, std::greater<RealIdxPair>> unassigned_items_by_persistence;
+#endif
+
+
+ // to imitate Gauss-Seidel
+ const size_t max_bids_per_round;
+
+ // to stop earlier in the last phase
+ const Real total_items_persistence;
+ const Real total_bidders_persistence;
+ Real partial_cost;
+ Real unassigned_bidders_persistence;
+ Real unassigned_items_persistence;
+ Real gamma_threshold;
+ size_t unassigned_threshold;
+
+ bool is_distance_computed { false };
+ int num_rounds { 0 };
+ int num_rounds_non_cumulative { 0 };
+ int num_phase { 0 };
+
+
+ size_t num_diag_items { 0 };
+ size_t num_normal_items { 0 };
+ size_t num_diag_bidders { 0 };
+ size_t num_normal_bidders { 0 };
+
+
+
+ // private methods
+ void assign_forward(const IdxType item_idx, const IdxType bidder_idx);
+ void assign_reverse(const IdxType item_idx, const IdxType bidder_idx);
+ void assign_to_best_bidder(const IdxType item_idx);
+ void assign_to_best_item(const IdxType bidder_idx);
+ void clear_forward_bid_table();
+ void clear_reverse_bid_table();
+ void assign_diag_to_diag();
+ void run_auction_phases(const int max_num_phases, const Real _initial_epsilon);
+ void run_auction_phase();
+ void run_forward_auction_phase();
+ void run_reverse_auction_phase();
+ void submit_forward_bid(IdxType bidder_idx, const IdxValPairR& bid);
+ void submit_reverse_bid(IdxType item_idx, const IdxValPairR& bid);
+ void flush_assignment();
+ Real get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx) const;
+ Real get_cost_to_diagonal(const DgmPoint& pt) const;
+ Real get_gamma() const;
+
+ template<class Range>
+ void run_forward_bidding_step(const Range& r);
+
+ template<class Range>
+ void run_reverse_bidding_step(const Range& r);
+
+ void add_unassigned_bidder(const size_t bidder_idx);
+ void add_unassigned_item(const size_t item_idx);
+ void remove_unassigned_bidder(const size_t bidder_idx);
+ void remove_unassigned_item(const size_t item_idx);
+
+ bool is_item_diagonal(const size_t item_idx) const { return item_idx < num_diag_items; }
+ bool is_item_normal(const size_t item_idx) const { return not is_item_diagonal(item_idx); }
+ bool is_bidder_diagonal(const size_t bidder_idx) const { return bidder_idx >= num_normal_bidders; }
+ bool is_bidder_normal(const size_t bidder_idx) const { return not is_bidder_diagonal(bidder_idx); }
+
+ size_t num_forward_bids_submitted { 0 };
+ size_t num_reverse_bids_submitted { 0 };
+
+ void decrease_epsilon();
+ // stopping criteria
+ bool continue_forward(const size_t, const size_t);
+ bool continue_reverse(const size_t, const size_t);
+ bool continue_phase();
+
+
+
+ // for debug only
+ void sanity_check();
+ void check_epsilon_css();
+ void print_debug();
+ void print_matching();
+
+ std::string log_filename_prefix;
+ const Real k_max_relative_error = 2.0; // if relative error cannot be estimated or is too large, use this value
+ void reset_round_stat(); // empty, if logging is disable
+ void reset_phase_stat();
+
+ std::unordered_set<size_t> never_assigned_bidders;
+ std::unordered_set<size_t> never_assigned_items;
+
+#ifdef LOG_AUCTION
+ std::unordered_set<size_t> unassigned_normal_bidders;
+ std::unordered_set<size_t> unassigned_diag_bidders;
+
+ std::unordered_set<size_t> unassigned_normal_items;
+ std::unordered_set<size_t> unassigned_diag_items;
+
+
+ size_t all_assigned_round { 0 };
+ size_t all_assigned_round_found { false };
+
+ int num_forward_rounds_non_cumulative { 0 };
+ int num_forward_rounds { 0 };
+
+ int num_reverse_rounds_non_cumulative { 0 };
+ int num_reverse_rounds { 0 };
+
+ // all per-round vars are non-cumulative
+
+ // forward rounds
+ int num_normal_forward_bids_submitted { 0 };
+ int num_diag_forward_bids_submitted { 0 };
+
+ int num_forward_diag_to_diag_assignments { 0 };
+ int num_forward_diag_to_normal_assignments { 0 };
+ int num_forward_normal_to_diag_assignments { 0 };
+ int num_forward_normal_to_normal_assignments { 0 };
+
+ int num_forward_diag_from_diag_thefts { 0 };
+ int num_forward_diag_from_normal_thefts { 0 };
+ int num_forward_normal_from_diag_thefts { 0 };
+ int num_forward_normal_from_normal_thefts { 0 };
+
+ // reverse rounds
+ int num_normal_reverse_bids_submitted { 0 };
+ int num_diag_reverse_bids_submitted { 0 };
+
+ int num_reverse_diag_to_diag_assignments { 0 };
+ int num_reverse_diag_to_normal_assignments { 0 };
+ int num_reverse_normal_to_diag_assignments { 0 };
+ int num_reverse_normal_to_normal_assignments { 0 };
+
+ int num_reverse_diag_from_diag_thefts { 0 };
+ int num_reverse_diag_from_normal_thefts { 0 };
+ int num_reverse_normal_from_diag_thefts { 0 };
+ int num_reverse_normal_from_normal_thefts { 0 };
+
+ // price change statistics
+ std::vector<std::vector<size_t>> forward_price_change_cnt_vec;
+ std::vector<std::vector<size_t>> reverse_price_change_cnt_vec;
+
+ size_t parallel_threshold = 5000;
+ int num_parallelizable_rounds { 0 };
+ int num_parallelizable_forward_rounds { 0 };
+ int num_parallelizable_reverse_rounds { 0 };
+
+ int num_parallel_bids { 0 };
+ int num_total_bids { 0 };
+
+ int num_parallel_assignments { 0 };
+ int num_total_assignments { 0 };
+#endif
+
+};
+
+
+
+} // ws
+} // hera
+
+#include "auction_runner_fr.hpp"
+
+#undef ORDERED_BY_PERSISTENCE
+#endif
diff --git a/wasserstein/include/auction_runner_fr.hpp b/wasserstein/include/auction_runner_fr.hpp
new file mode 100644
index 0000000..b0b65d0
--- /dev/null
+++ b/wasserstein/include/auction_runner_fr.hpp
@@ -0,0 +1,1208 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_RUNNER_FR_HPP
+#define AUCTION_RUNNER_FR_HPP
+
+#include <cassert>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+
+#include "auction_runner_fr.h"
+
+#ifdef FOR_R_TDA
+#include "Rcpp.h"
+#undef DEBUG_FR_AUCTION
+#endif
+
+
+namespace hera {
+namespace ws {
+
+
+// *****************************
+// AuctionRunnerFR
+// *****************************
+
+template<class R, class AO>
+AuctionRunnerFR<R, AO>::AuctionRunnerFR(const std::vector<DgmPoint>& A,
+ const std::vector<DgmPoint>& B,
+ const Real q,
+ const Real _delta,
+ const Real _internal_p,
+ const Real _initial_epsilon,
+ const Real _eps_factor,
+ const int _max_num_phases,
+ const Real _gamma_threshold,
+ const size_t _max_bids_per_round,
+ const std::string& _log_filename_prefix
+ ) :
+ bidders(A),
+ items(B),
+ num_bidders(A.size()),
+ num_items(A.size()),
+ items_to_bidders(A.size(), k_invalid_index),
+ bidders_to_items(A.size(), k_invalid_index),
+ wasserstein_power(q),
+ delta(_delta),
+ internal_p(_internal_p),
+ initial_epsilon(_initial_epsilon),
+ epsilon_common_ratio(_eps_factor == 0.0 ? 5.0 : _eps_factor),
+ max_num_phases(_max_num_phases),
+ forward_bid_table(A.size(), std::make_pair(k_invalid_index, k_lowest_bid_value) ),
+ reverse_bid_table(B.size(), std::make_pair(k_invalid_index, k_lowest_bid_value) ),
+ forward_oracle(bidders, items, q, _internal_p),
+ reverse_oracle(items, bidders, q, _internal_p),
+ max_bids_per_round(_max_bids_per_round),
+ total_items_persistence(std::accumulate(items.begin(),
+ items.end(),
+ R(0.0),
+ [_internal_p, q](const Real& ps, const DgmPoint& item)
+ { return ps + std::pow(item.persistence_lp(_internal_p), q); }
+ )),
+ total_bidders_persistence(std::accumulate(bidders.begin(),
+ bidders.end(),
+ R(0.0),
+ [_internal_p, q](const Real& ps, const DgmPoint& bidder)
+ { return ps + std::pow(bidder.persistence_lp(_internal_p), q); }
+ )),
+ partial_cost(0.0),
+ unassigned_bidders_persistence(total_bidders_persistence),
+ unassigned_items_persistence(total_items_persistence),
+ gamma_threshold(_gamma_threshold),
+ log_filename_prefix(_log_filename_prefix)
+{
+ assert(A.size() == B.size());
+ for(const auto& p : bidders) {
+ if (p.is_normal()) {
+ num_normal_bidders++;
+ num_diag_items++;
+ } else {
+ num_normal_items++;
+ num_diag_bidders++;
+ }
+ }
+
+#ifdef ORDERED_BY_PERSISTENCE
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ unassigned_bidders_by_persistence.insert(std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx));
+ }
+
+ for(size_t item_idx = 0; item_idx < num_items; ++item_idx) {
+ unassigned_items_by_persistence.insert(std::make_pair(items[item_idx].persistence_lp(1.0), item_idx));
+ }
+#endif
+
+ // for experiments
+ unassigned_threshold = bidders.size() / 200;
+ unassigned_threshold = 0;
+
+#ifdef ORDERED_BY_PERSISTENCE
+ batch_size = 5000;
+#endif
+}
+
+template<class R, class AO>
+typename AuctionRunnerFR<R, AO>::Real
+AuctionRunnerFR<R, AO>::get_cost_to_diagonal(const DgmPoint& pt) const
+{
+ if (1.0 == wasserstein_power) {
+ return pt.persistence_lp(internal_p);
+ } else {
+ return std::pow(pt.persistence_lp(internal_p), wasserstein_power);
+ }
+}
+
+
+template<class R, class AO>
+typename AuctionRunnerFR<R, AO>::Real
+AuctionRunnerFR<R, AO>::get_gamma() const
+{
+ if (1.0 == wasserstein_power) {
+ return unassigned_items_persistence + unassigned_bidders_persistence;
+ } else {
+ return std::pow(unassigned_items_persistence + unassigned_bidders_persistence,
+ 1.0 / wasserstein_power);
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::reset_phase_stat()
+{
+ num_rounds_non_cumulative = 0;
+#ifdef LOG_AUCTION
+ num_parallelizable_rounds = 0;
+ num_parallelizable_forward_rounds = 0;
+ num_parallelizable_reverse_rounds = 0;
+ num_forward_rounds_non_cumulative = 0;
+ num_reverse_rounds_non_cumulative = 0;
+#endif
+}
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::reset_round_stat()
+{
+ num_forward_bids_submitted = 0;
+ num_reverse_bids_submitted = 0;
+#ifdef LOG_AUCTION
+ num_normal_forward_bids_submitted = 0;
+ num_diag_forward_bids_submitted = 0;
+
+ num_forward_diag_to_diag_assignments = 0;
+ num_forward_diag_to_normal_assignments = 0;
+ num_forward_normal_to_diag_assignments = 0;
+ num_forward_normal_to_normal_assignments = 0;
+
+ num_forward_diag_from_diag_thefts = 0;
+ num_forward_diag_from_normal_thefts = 0;
+ num_forward_normal_from_diag_thefts = 0;
+ num_forward_normal_from_normal_thefts = 0;
+
+ // reverse rounds
+ num_normal_reverse_bids_submitted = 0;
+ num_diag_reverse_bids_submitted = 0;
+
+ num_reverse_diag_to_diag_assignments = 0;
+ num_reverse_diag_to_normal_assignments = 0;
+ num_reverse_normal_to_diag_assignments = 0;
+ num_reverse_normal_to_normal_assignments = 0;
+
+ num_reverse_diag_from_diag_thefts = 0;
+ num_reverse_diag_from_normal_thefts = 0;
+ num_reverse_normal_from_diag_thefts = 0;
+ num_reverse_normal_from_normal_thefts = 0;
+#endif
+}
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::assign_forward(IdxType item_idx, IdxType bidder_idx)
+{
+ sanity_check();
+ // only unassigned bidders submit bids
+ assert(bidders_to_items[bidder_idx] == k_invalid_index);
+
+ IdxType old_item_owner = items_to_bidders[item_idx];
+
+ // set new owner
+ bidders_to_items[bidder_idx] = item_idx;
+ items_to_bidders[item_idx] = bidder_idx;
+
+ // remove bidder and item from the sets of unassigned bidders/items
+ remove_unassigned_bidder(bidder_idx);
+
+ if (k_invalid_index != old_item_owner) {
+ // old owner of item becomes unassigned
+ bidders_to_items[old_item_owner] = k_invalid_index;
+ add_unassigned_bidder(old_item_owner);
+ // existing edge was removed, decrease partial_cost
+ partial_cost -= get_item_bidder_cost(item_idx, old_item_owner);
+ } else {
+ // item was unassigned before
+ remove_unassigned_item(item_idx);
+ }
+
+ // new edge was added to matching, increase partial cost
+ partial_cost += get_item_bidder_cost(item_idx, bidder_idx);
+
+#ifdef LOG_AUCTION
+
+ if (unassigned_bidders.size() > parallel_threshold) {
+ num_parallel_assignments++;
+ }
+ num_total_assignments++;
+
+
+ int it_d = is_item_diagonal(item_idx);
+ int b_d = is_bidder_diagonal(bidder_idx);
+ // 2 - None
+ int old_d = ( k_invalid_index == old_item_owner ) ? 2 : is_bidder_diagonal(old_item_owner);
+ int key = 100 * old_d + 10 * b_d + it_d;
+ switch(key) {
+ case 211 : num_forward_diag_to_diag_assignments++;
+ break;
+ case 210 : num_forward_diag_to_normal_assignments++;
+ break;
+ case 201 : num_forward_normal_to_diag_assignments++;
+ break;
+ case 200 : num_forward_normal_to_normal_assignments++;
+ break;
+
+ case 111 : num_forward_diag_to_diag_assignments++;
+ num_forward_diag_from_diag_thefts++;
+ break;
+ case 110 : num_forward_diag_to_normal_assignments++;
+ num_forward_diag_from_diag_thefts++;
+ break;
+ break;
+ case 101 : num_forward_normal_to_diag_assignments++;
+ num_forward_normal_from_diag_thefts++;
+ break;
+ break;
+ case 100 : num_forward_normal_to_normal_assignments++;
+ num_forward_normal_from_diag_thefts++;
+ break;
+
+ case 11 : num_forward_diag_to_diag_assignments++;
+ num_forward_diag_from_normal_thefts++;
+ break;
+ case 10 : num_forward_diag_to_normal_assignments++;
+ num_forward_diag_from_normal_thefts++;
+ break;
+ break;
+ case 1 : num_forward_normal_to_diag_assignments++;
+ num_forward_normal_from_normal_thefts++;
+ break;
+ break;
+ case 0 : num_forward_normal_to_normal_assignments++;
+ num_forward_normal_from_normal_thefts++;
+ break;
+ default : std::cerr << "key = " << key << std::endl;
+ throw std::runtime_error("Bug in logging, wrong key");
+ break;
+ }
+#endif
+
+ sanity_check();
+}
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::assign_reverse(IdxType item_idx, IdxType bidder_idx)
+{
+ // only unassigned items submit bids in reverse phase
+ assert(items_to_bidders[item_idx] == k_invalid_index);
+
+ IdxType old_bidder_owner = bidders_to_items[bidder_idx];
+
+ // set new owner
+ bidders_to_items[bidder_idx] = item_idx;
+ items_to_bidders[item_idx] = bidder_idx;
+
+ // remove bidder and item from the sets of unassigned bidders/items
+ remove_unassigned_item(item_idx);
+
+ if (k_invalid_index != old_bidder_owner) {
+ // old owner of item becomes unassigned
+ items_to_bidders[old_bidder_owner] = k_invalid_index;
+ add_unassigned_item(old_bidder_owner);
+ // existing edge was removed, decrease partial_cost
+ partial_cost -= get_item_bidder_cost(old_bidder_owner, bidder_idx);
+ } else {
+ // item was unassigned before
+ remove_unassigned_bidder(bidder_idx);
+ }
+
+ // new edge was added to matching, increase partial cost
+ partial_cost += get_item_bidder_cost(item_idx, bidder_idx);
+
+#ifdef LOG_AUCTION
+ if (unassigned_items.size() > parallel_threshold) {
+ num_parallel_assignments++;
+ }
+ num_total_assignments++;
+
+ int it_d = is_item_diagonal(item_idx);
+ int b_d = is_bidder_diagonal(bidder_idx);
+ // 2 - None
+ int old_d = (k_invalid_index == old_bidder_owner) ? 2 : is_item_diagonal(old_bidder_owner);
+ int key = 100 * old_d + 10 * it_d + b_d;
+ switch(key) {
+ case 211 : num_reverse_diag_to_diag_assignments++;
+ break;
+ case 210 : num_reverse_diag_to_normal_assignments++;
+ break;
+ case 201 : num_reverse_normal_to_diag_assignments++;
+ break;
+ case 200 : num_reverse_normal_to_normal_assignments++;
+ break;
+
+ case 111 : num_reverse_diag_to_diag_assignments++;
+ num_reverse_diag_from_diag_thefts++;
+ break;
+ case 110 : num_reverse_diag_to_normal_assignments++;
+ num_reverse_diag_from_diag_thefts++;
+ break;
+ break;
+ case 101 : num_reverse_normal_to_diag_assignments++;
+ num_reverse_normal_from_diag_thefts++;
+ break;
+ break;
+ case 100 : num_reverse_normal_to_normal_assignments++;
+ num_reverse_normal_from_diag_thefts++;
+ break;
+
+ case 11 : num_reverse_diag_to_diag_assignments++;
+ num_reverse_diag_from_normal_thefts++;
+ break;
+ case 10 : num_reverse_diag_to_normal_assignments++;
+ num_reverse_diag_from_normal_thefts++;
+ break;
+ break;
+ case 1 : num_reverse_normal_to_diag_assignments++;
+ num_reverse_normal_from_normal_thefts++;
+ break;
+ break;
+ case 0 : num_reverse_normal_to_normal_assignments++;
+ num_reverse_normal_from_normal_thefts++;
+ break;
+ default : std::cerr << "key = " << key << std::endl;
+ throw std::runtime_error("Bug in logging, wrong key");
+ break;
+ }
+
+#endif
+}
+
+template<class R, class AO>
+typename AuctionRunnerFR<R, AO>::Real
+AuctionRunnerFR<R, AO>::get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx) const
+{
+ if (wasserstein_power == 1.0) {
+ return dist_lp(bidders[bidder_idx], items[item_idx], internal_p);
+ } else {
+ return std::pow(dist_lp(bidders[bidder_idx], items[item_idx], internal_p),
+ wasserstein_power);
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::assign_to_best_bidder(IdxType item_idx)
+{
+ assert( item_idx >= 0 and item_idx < static_cast<IdxType>(num_items) );
+ assert( forward_bid_table[item_idx].first != k_invalid_index);
+
+ auto best_bidder_idx = forward_bid_table[item_idx].first;
+ auto best_bid_value = forward_bid_table[item_idx].second;
+ assign_forward(item_idx, best_bidder_idx);
+ forward_oracle.sanity_check();
+ forward_oracle.set_price(item_idx, best_bid_value, true);
+ forward_oracle.sanity_check();
+ auto new_bidder_price = -get_item_bidder_cost(item_idx, best_bidder_idx) - best_bid_value;
+ reverse_oracle.set_price(best_bidder_idx, new_bidder_price, false);
+ check_epsilon_css();
+#ifdef LOG_AUCTION
+ forward_price_change_cnt_vec.back()[item_idx]++;
+ reverse_price_change_cnt_vec.back()[best_bidder_idx]++;
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::assign_to_best_item(IdxType bidder_idx)
+{
+ check_epsilon_css();
+ assert( bidder_idx >= 0 and bidder_idx < static_cast<IdxType>(num_bidders) );
+ assert( reverse_bid_table[bidder_idx].first != k_invalid_index);
+ auto best_item_idx = reverse_bid_table[bidder_idx].first;
+ auto best_bid_value = reverse_bid_table[bidder_idx].second;
+ // both assign_forward and assign_reverse take item index first, bidder index second!
+ assign_reverse(best_item_idx, bidder_idx);
+ reverse_oracle.sanity_check();
+ reverse_oracle.set_price(bidder_idx, best_bid_value, true);
+ reverse_oracle.sanity_check();
+ auto new_item_price = -get_item_bidder_cost(best_item_idx, bidder_idx) - best_bid_value;
+ forward_oracle.set_price(best_item_idx, new_item_price, false);
+#ifdef LOG_AUCTION
+ forward_price_change_cnt_vec.back()[best_item_idx]++;
+ reverse_price_change_cnt_vec.back()[bidder_idx]++;
+#endif
+ check_epsilon_css();
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::clear_forward_bid_table()
+{
+ auto item_iter = items_with_bids.begin();
+ while(item_iter != items_with_bids.end()) {
+ auto item_with_bid_idx = *item_iter;
+ forward_bid_table[item_with_bid_idx].first = k_invalid_index;
+ forward_bid_table[item_with_bid_idx].second = k_lowest_bid_value;
+ item_iter = items_with_bids.erase(item_iter);
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::clear_reverse_bid_table()
+{
+ auto bidder_iter = bidders_with_bids.begin();
+ while(bidder_iter != bidders_with_bids.end()) {
+ auto bidder_with_bid_idx = *bidder_iter;
+ reverse_bid_table[bidder_with_bid_idx].first = k_invalid_index;
+ reverse_bid_table[bidder_with_bid_idx].second = k_lowest_bid_value;
+ bidder_iter = bidders_with_bids.erase(bidder_iter);
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::submit_forward_bid(IdxType bidder_idx, const IdxValPairR& bid)
+{
+ IdxType best_item_idx = bid.first;
+ Real bid_value = bid.second;
+ assert( best_item_idx >= 0 );
+
+ auto value_in_bid_table = forward_bid_table[best_item_idx].second;
+ bool new_bid_wins = (value_in_bid_table < bid_value);
+ // if we have tie, lower persistence wins
+// if (value_in_bid_table == bid_value) {
+//
+// assert(forward_bid_table.at(best_item_idx).first != k_invalid_index);
+// assert(&bidders.at(forward_bid_table.at(best_item_idx).first));
+//
+// auto bidder_in_bid_table = bidders[forward_bid_table[best_item_idx].first];
+// new_bid_wins = bidders[best_item_idx].persistence_lp(internal_p) < bidder_in_bid_table.persistence_lp(internal_p);
+// }
+
+ if (new_bid_wins) {
+ forward_bid_table[best_item_idx].first = bidder_idx;
+ forward_bid_table[best_item_idx].second = bid_value;
+ }
+
+ items_with_bids.insert(best_item_idx);
+
+#ifdef LOG_AUCTION
+
+ if (unassigned_bidders.size() > parallel_threshold) {
+ num_parallel_bids++;
+ }
+ num_total_bids++;
+
+
+ if (is_bidder_diagonal(bidder_idx)) {
+ num_diag_forward_bids_submitted++;
+ } else {
+ num_normal_forward_bids_submitted++;
+ }
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::submit_reverse_bid(IdxType item_idx, const IdxValPairR& bid)
+{
+ assert( items.at(item_idx).is_diagonal() or items.at(item_idx).is_normal() );
+ IdxType best_bidder_idx = bid.first;
+ assert( bidders.at(best_bidder_idx).is_diagonal() or bidders.at(best_bidder_idx).is_normal() );
+ Real bid_value = bid.second;
+ assert(bid_value > k_lowest_bid_value);
+ auto value_in_bid_table = reverse_bid_table[best_bidder_idx].second;
+ bool new_bid_wins = (value_in_bid_table < bid_value);
+ // if we have tie, lower persistence wins
+// if (value_in_bid_table == bid_value) {
+// assert(reverse_bid_table[best_bidder_idx].first != k_invalid_index);
+// auto bidder_in_bid_table = bidders[reverse_bid_table[best_bidder_idx].first];
+// new_bid_wins = bidders[best_bidder_idx].persistence_lp(internal_p) < bidder_in_bid_table.persistence_lp(internal_p);
+// }
+ if (new_bid_wins) {
+ reverse_bid_table[best_bidder_idx].first = item_idx;
+ reverse_bid_table[best_bidder_idx].second = bid_value;
+ }
+ bidders_with_bids.insert(best_bidder_idx);
+
+#ifdef LOG_AUCTION
+
+ if (unassigned_items.size() > parallel_threshold) {
+ num_parallel_bids++;
+ }
+ num_total_bids++;
+
+ if (is_item_diagonal(item_idx)) {
+ num_diag_reverse_bids_submitted++;
+ } else {
+ num_normal_reverse_bids_submitted++;
+ }
+#endif
+}
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::print_debug()
+{
+#ifdef DEBUG_FR_AUCTION
+ std::cout << "**********************" << std::endl;
+ std::cout << "Current assignment:" << std::endl;
+ for(size_t idx = 0; idx < bidders_to_items.size(); ++idx) {
+ std::cout << idx << " <--> " << bidders_to_items[idx] << std::endl;
+ }
+ std::cout << "Weights: " << std::endl;
+ //for(size_t i = 0; i < num_bidders; ++i) {
+ //for(size_t j = 0; j < num_items; ++j) {
+ //std::cout << oracle.weight_matrix[i][j] << " ";
+ //}
+ //std::cout << std::endl;
+ //}
+ std::cout << "Bidder prices: " << std::endl;
+ for(const auto price : forward_oracle.get_prices()) {
+ std::cout << price << std::endl;
+ }
+ std::cout << "**********************" << std::endl;
+#endif
+}
+
+
+template<class R, class AO>
+typename AuctionRunnerFR<R,AO>::Real
+AuctionRunnerFR<R, AO>::get_relative_error(const bool debug_output) const
+{
+ Real result;
+ Real gamma = get_gamma();
+ // cost minus n epsilon
+ Real reduced_cost = partial_cost - num_bidders * get_epsilon();
+ if ( reduced_cost < 0) {
+ result = k_max_relative_error;
+ } else {
+ Real denominator = std::pow(reduced_cost, 1.0 / wasserstein_power) - gamma;
+ if (denominator <= 0) {
+ result = k_max_relative_error;
+ } else {
+ Real numerator = 2 * gamma +
+ std::pow(partial_cost, 1.0 / wasserstein_power) -
+ std::pow(reduced_cost, 1.0 / wasserstein_power);
+
+ result = numerator / denominator;
+ }
+ }
+ return result;
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::flush_assignment()
+{
+ for(auto& b2i : bidders_to_items) {
+ b2i = k_invalid_index;
+ }
+ for(auto& i2b : items_to_bidders) {
+ i2b = k_invalid_index;
+ }
+
+ // all bidders and items become unassigned
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ unassigned_bidders.insert(bidder_idx);
+ }
+
+ // all items and items become unassigned
+ for(size_t item_idx = 0; item_idx < num_items; ++item_idx) {
+ unassigned_items.insert(item_idx);
+ }
+
+
+ //forward_oracle.adjust_prices();
+ //reverse_oracle.adjust_prices();
+
+ partial_cost = 0.0;
+ unassigned_bidders_persistence = total_bidders_persistence;
+ unassigned_items_persistence = total_items_persistence;
+
+#ifdef ORDERED_BY_PERSISTENCE
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ unassigned_bidders_by_persistence.insert(std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx));
+ }
+
+ for(size_t item_idx = 0; item_idx < num_items; ++item_idx) {
+ unassigned_items_by_persistence.insert(std::make_pair(items[item_idx].persistence_lp(1.0), item_idx));
+ }
+#endif
+
+#ifdef LOG_AUCTION
+
+ reset_phase_stat();
+
+ forward_price_change_cnt_vec.push_back(std::vector<size_t>(num_items, 0));
+ reverse_price_change_cnt_vec.push_back(std::vector<size_t>(num_bidders, 0));
+
+ // all bidders and items become unassigned
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if (is_bidder_normal(bidder_idx)) {
+ unassigned_normal_bidders.insert(bidder_idx);
+ } else {
+ unassigned_diag_bidders.insert(bidder_idx);
+ }
+ }
+
+ never_assigned_bidders = unassigned_bidders;
+
+ for(size_t item_idx = 0; item_idx < items.size(); ++item_idx) {
+ if (is_item_normal(item_idx)) {
+ unassigned_normal_items.insert(item_idx);
+ } else {
+ unassigned_diag_items.insert(item_idx);
+ }
+ }
+
+ never_assigned_items = unassigned_items;
+#endif
+ check_epsilon_css();
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::set_epsilon(Real new_val)
+{
+ assert(new_val > 0.0);
+ epsilon = new_val;
+ forward_oracle.set_epsilon(new_val);
+ reverse_oracle.set_epsilon(new_val);
+}
+
+
+template<class R, class AO>
+bool AuctionRunnerFR<R, AO>::continue_forward(const size_t original_unassigned_bidders, const size_t min_forward_matching_increment)
+{
+// if (unassigned_threshold == 0) {
+// return not unassigned_bidders.empty() and get_relative_error(false) > delta;
+// }
+ //return unassigned_bidders.size() > unassigned_threshold and
+ //static_cast<int>(unassigned_bidders.size()) >= static_cast<int>(original_unassigned_bidders) - static_cast<int>(min_forward_matching_increment);
+ return unassigned_bidders.size() > unassigned_threshold and
+ static_cast<int>(unassigned_bidders.size()) >= static_cast<int>(original_unassigned_bidders) - static_cast<int>(min_forward_matching_increment) and
+ get_relative_error() >= delta;
+// return not unassigned_bidders.empty() and
+// static_cast<int>(unassigned_bidders.size()) >= static_cast<int>(original_unassigned_bidders) - static_cast<int>(min_forward_matching_increment) and
+// get_relative_error() >= delta;
+}
+
+
+template<class R, class AO>
+bool AuctionRunnerFR<R, AO>::continue_reverse(const size_t original_unassigned_items, const size_t min_reverse_matching_increment)
+{
+ //return unassigned_items.size() > unassigned_threshold and
+ //static_cast<int>(unassigned_items.size()) >= static_cast<int>(original_unassigned_items) - static_cast<int>(min_reverse_matching_increment);
+ return unassigned_items.size() > unassigned_threshold and
+ static_cast<int>(unassigned_items.size()) >= static_cast<int>(original_unassigned_items) - static_cast<int>(min_reverse_matching_increment) and
+ get_relative_error() >= delta;
+// return not unassigned_items.empty() and
+// static_cast<int>(unassigned_items.size()) >= static_cast<int>(original_unassigned_items) - static_cast<int>(min_reverse_matching_increment) and
+// get_relative_error() >= delta;
+}
+
+
+template<class R, class AO>
+bool AuctionRunnerFR<R, AO>::continue_phase()
+{
+ //return not unassigned_bidders.empty();
+ return unassigned_bidders.size() > unassigned_threshold and get_relative_error() >= delta;
+// return not never_assigned_bidders.empty() or
+// not never_assigned_items.empty() or
+// unassigned_bidders.size() > unassigned_threshold and get_relative_error() >= delta;
+}
+
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::run_auction_phase()
+{
+ num_phase++;
+ while(continue_phase()) {
+ forward_oracle.recompute_top_diag_items(true);
+ forward_oracle.sanity_check();
+ run_forward_auction_phase();
+ reverse_oracle.recompute_top_diag_items(true);
+ reverse_oracle.sanity_check();
+ run_reverse_auction_phase();
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::run_auction_phases(const int max_num_phases, const Real _initial_epsilon)
+{
+ set_epsilon(_initial_epsilon);
+ assert( forward_oracle.get_epsilon() > 0 );
+ assert( reverse_oracle.get_epsilon() > 0 );
+ for(int phase_num = 0; phase_num < max_num_phases; ++phase_num) {
+ flush_assignment();
+
+ run_auction_phase();
+ Real current_result = partial_cost;
+
+ if (get_relative_error(true) <= delta) {
+ break;
+ }
+ // decrease epsilon for the next iteration
+ decrease_epsilon();
+
+ unassigned_threshold = std::floor( static_cast<double>(unassigned_threshold) / 1.1 );
+
+ if (phase_can_be_final()) {
+ unassigned_threshold = 0;
+ }
+ }
+}
+
+template<class R, class AO>
+bool AuctionRunnerFR<R, AO>::phase_can_be_final() const
+{
+ Real estimated_error;
+ // cost minus n epsilon
+ Real reduced_cost = partial_cost - num_bidders * get_epsilon();
+ if (reduced_cost <= 0.0) {
+ return false;
+ } else {
+ Real denominator = std::pow(reduced_cost, 1.0 / wasserstein_power);
+ if (denominator <= 0) {
+ return false;
+ } else {
+ Real numerator = std::pow(partial_cost, 1.0 / wasserstein_power) -
+ std::pow(reduced_cost, 1.0 / wasserstein_power);
+
+ estimated_error = numerator / denominator;
+ return estimated_error <= delta;
+ }
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::run_auction()
+{
+ double init_eps = ( initial_epsilon > 0.0 ) ? initial_epsilon : std::min(forward_oracle.max_val_, reverse_oracle.max_val_) / 4.0 ;
+ assert(init_eps > 0.0);
+ run_auction_phases(max_num_phases, init_eps);
+ is_distance_computed = true;
+ wasserstein_cost = partial_cost;
+ if (get_relative_error() > delta) {
+#ifndef FOR_R_TDA
+ std::cerr << "Maximum iteration number exceeded, exiting. Current result is: ";
+ std::cerr << get_wasserstein_distance() << std::endl;
+#endif
+ throw std::runtime_error("Maximum iteration number exceeded");
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::add_unassigned_bidder(const size_t bidder_idx)
+{
+ const DgmPoint& bidder = bidders[bidder_idx];
+ unassigned_bidders.insert(bidder_idx);
+ unassigned_bidders_persistence += get_cost_to_diagonal(bidder);
+
+#ifdef ORDERED_BY_PERSISTENCE
+ unassigned_bidders_by_persistence.insert(std::make_pair(bidder.persistence_lp(1.0), bidder_idx));
+#endif
+
+#ifdef LOG_AUCTION
+ if (is_bidder_diagonal(bidder_idx)) {
+ unassigned_diag_bidders.insert(bidder_idx);
+ } else {
+ unassigned_normal_bidders.insert(bidder_idx);
+ }
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::add_unassigned_item(const size_t item_idx)
+{
+ const DgmPoint& item = items[item_idx];
+ unassigned_items.insert(item_idx);
+ unassigned_items_persistence += get_cost_to_diagonal(item);
+
+#ifdef ORDERED_BY_PERSISTENCE
+ unassigned_items_by_persistence.insert(std::make_pair(item.persistence_lp(1.0), item_idx));
+#endif
+
+#ifdef LOG_AUCTION
+ if (is_item_diagonal(item_idx)) {
+ unassigned_diag_items.insert(item_idx);
+ } else {
+ unassigned_normal_items.insert(item_idx);
+ }
+#endif
+}
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::remove_unassigned_bidder(const size_t bidder_idx)
+{
+ unassigned_bidders_persistence -= get_cost_to_diagonal(bidders[bidder_idx]);
+
+ unassigned_bidders.erase(bidder_idx);
+ never_assigned_bidders.erase(bidder_idx);
+
+#ifdef ORDERED_BY_PERSISTENCE
+ unassigned_bidders_by_persistence.erase(std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx));
+#endif
+
+#ifdef LOG_AUCTION
+ if (is_bidder_diagonal(bidder_idx)) {
+ unassigned_diag_bidders.erase(bidder_idx);
+ } else {
+ unassigned_normal_bidders.erase(bidder_idx);
+ }
+ if (never_assigned_bidders.empty() and not all_assigned_round_found) {
+ all_assigned_round = num_rounds_non_cumulative;
+ all_assigned_round_found = true;
+ }
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::remove_unassigned_item(const size_t item_idx)
+{
+ unassigned_items_persistence -= get_cost_to_diagonal(items[item_idx]);
+
+ never_assigned_items.erase(item_idx);
+ unassigned_items.erase(item_idx);
+
+#ifdef ORDERED_BY_PERSISTENCE
+ unassigned_items_by_persistence.erase(std::make_pair(items[item_idx].persistence_lp(1.0), item_idx));
+#endif
+
+#ifdef LOG_AUCTION
+ if (is_item_normal(item_idx)) {
+ unassigned_normal_items.erase(item_idx);
+ } else {
+ unassigned_diag_items.erase(item_idx);
+ }
+ if (never_assigned_items.empty() and not all_assigned_round_found) {
+ all_assigned_round = num_rounds_non_cumulative;
+ all_assigned_round_found = true;
+ }
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::decrease_epsilon()
+{
+ auto eps_diff = 1.01 * get_epsilon() * (epsilon_common_ratio - 1.0 ) / epsilon_common_ratio;
+ reverse_oracle.adjust_prices( -eps_diff );
+ set_epsilon( get_epsilon() / epsilon_common_ratio );
+ cumulative_epsilon_factor *= epsilon_common_ratio;
+}
+
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::run_reverse_auction_phase()
+{
+ size_t original_unassigned_items = unassigned_items.size();
+// const size_t min_reverse_matching_increment = std::max( static_cast<size_t>(1), static_cast<size_t>(original_unassigned_items / 10));
+ size_t min_reverse_matching_increment = 1;
+
+ while (continue_reverse(original_unassigned_items, min_reverse_matching_increment)) {
+ num_rounds++;
+ num_rounds_non_cumulative++;
+
+ check_epsilon_css();
+#ifdef LOG_AUCTION
+ if (unassigned_items.size() >= parallel_threshold) {
+ ++num_parallelizable_reverse_rounds;
+ ++num_parallelizable_rounds;
+ }
+ num_reverse_rounds++;
+ num_reverse_rounds_non_cumulative++;
+#endif
+
+ reset_round_stat();
+ // bidding
+#ifdef ORDERED_BY_PERSISTENCE
+ std::vector<size_t> active_items;
+ active_items.reserve(batch_size);
+ for(auto iter = unassigned_items_by_persistence.begin();
+ iter != unassigned_items_by_persistence.end(); ++iter) {
+ active_items.push_back(iter->second);
+ if (active_items.size() >= batch_size) {
+ break;
+ }
+ }
+ run_reverse_bidding_step(active_items);
+#else
+ //if (not never_assigned_items.empty())
+ //run_reverse_bidding_step(never_assigned_items);
+ //else
+ //run_reverse_bidding_step(unassigned_items);
+ run_reverse_bidding_step(unassigned_items);
+#endif
+
+ // assignment phase
+ for(auto bidder_idx : bidders_with_bids ) {
+ assign_to_best_item(bidder_idx);
+ }
+
+ check_epsilon_css();
+ }
+}
+
+template<class R, class AO>
+template<class Range>
+void AuctionRunnerFR<R, AO>::run_forward_bidding_step(const Range& active_bidders)
+{
+ clear_forward_bid_table();
+ for(const auto bidder_idx : active_bidders) {
+ submit_forward_bid(bidder_idx, forward_oracle.get_optimal_bid(bidder_idx));
+ if (++num_forward_bids_submitted >= max_bids_per_round) {
+ break;
+ }
+ }
+}
+
+template<class R, class AO>
+template<class Range>
+void AuctionRunnerFR<R, AO>::run_reverse_bidding_step(const Range& active_items)
+{
+ clear_reverse_bid_table();
+
+ assert(bidders_with_bids.empty());
+ assert(std::all_of(reverse_bid_table.begin(), reverse_bid_table.end(),
+ [ki = k_invalid_index, kl = k_lowest_bid_value](const IdxValPairR& b) { return static_cast<size_t>(b.first) == ki and b.second == kl; }));
+
+ for(const auto item_idx : active_items) {
+ submit_reverse_bid(item_idx, reverse_oracle.get_optimal_bid(item_idx));
+ if (++num_reverse_bids_submitted >= max_bids_per_round) {
+ break;
+ }
+ }
+}
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::run_forward_auction_phase()
+{
+ const size_t original_unassigned_bidders = unassigned_bidders.size();
+// const size_t min_forward_matching_increment = std::max( static_cast<size_t>(1), static_cast<size_t>(original_unassigned_bidders / 10));
+ const size_t min_forward_matching_increment = 1;
+ while (continue_forward(original_unassigned_bidders, min_forward_matching_increment)) {
+ check_epsilon_css();
+ num_rounds++;
+#ifdef LOG_AUCTION
+ if (unassigned_bidders.size() >= parallel_threshold) {
+ ++num_parallelizable_forward_rounds;
+ ++num_parallelizable_rounds;
+ }
+ num_forward_rounds++;
+ num_forward_rounds_non_cumulative++;
+#endif
+
+ reset_round_stat();
+ // bidding step
+#ifdef ORDERED_BY_PERSISTENCE
+ std::vector<size_t> active_bidders;
+ active_bidders.reserve(batch_size);
+ for(auto iter = unassigned_bidders_by_persistence.begin();
+ iter != unassigned_bidders_by_persistence.end(); ++iter) {
+ active_bidders.push_back(iter->second);
+ if (active_bidders.size() >= batch_size) {
+ break;
+ }
+ }
+ run_forward_bidding_step(active_bidders);
+#else
+
+ //if (not never_assigned_bidders.empty())
+ //run_forward_bidding_step(never_assigned_bidders);
+ //else
+ //run_forward_bidding_step(unassigned_bidders);
+ run_forward_bidding_step(unassigned_bidders);
+#endif
+
+ // assignment step
+ for(auto item_idx : items_with_bids ) {
+ assign_to_best_bidder(item_idx);
+ }
+
+ check_epsilon_css();
+
+#ifdef LOG_AUCTION
+ forward_plot_logger->info("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14} {15} {16} {17} {18} {19} {20} {21} {22}",
+ num_phase,
+ num_rounds,
+ num_forward_rounds,
+ unassigned_bidders.size(),
+ get_gamma(),
+ partial_cost,
+ forward_oracle.get_epsilon(),
+ num_normal_forward_bids_submitted,
+ num_diag_forward_bids_submitted,
+ num_forward_diag_to_diag_assignments,
+ num_forward_diag_to_normal_assignments,
+ num_forward_normal_to_diag_assignments,
+ num_forward_normal_to_normal_assignments,
+ num_forward_diag_from_diag_thefts,
+ num_forward_diag_from_normal_thefts,
+ num_forward_normal_from_diag_thefts,
+ num_forward_normal_from_normal_thefts,
+ unassigned_normal_bidders.size(),
+ unassigned_diag_bidders.size(),
+ unassigned_normal_items.size(),
+ unassigned_diag_items.size(),
+ forward_oracle.get_heap_top_size(),
+ get_relative_error(false)
+ );
+#endif
+ } ;
+
+}
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::assign_diag_to_diag()
+{
+ size_t n_diag_to_diag = std::min(num_diag_bidders, num_diag_items);
+ if (n_diag_to_diag < 2)
+ return;
+ for(size_t i = 0; i < n_diag_to_diag; ++i) {
+ }
+}
+
+template<class R, class AO>
+typename AuctionRunnerFR<R, AO>::Real
+AuctionRunnerFR<R, AO>::get_wasserstein_distance()
+{
+ assert(is_distance_computed);
+ return std::pow(wasserstein_cost, 1.0 / wasserstein_power);
+}
+
+template<class R, class AO>
+typename AuctionRunnerFR<R, AO>::Real
+AuctionRunnerFR<R, AO>::get_wasserstein_cost()
+{
+ assert(is_distance_computed);
+ return wasserstein_cost;
+}
+
+
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::sanity_check()
+{
+#ifdef DEBUG_FR_AUCTION
+ assert(partial_cost >= 0);
+
+
+ assert(num_diag_items == num_normal_bidders);
+ assert(num_diag_bidders == num_normal_items);
+ assert(num_diag_bidders + num_normal_bidders == num_bidders);
+ assert(num_diag_items + num_normal_items == num_items);
+ assert(num_items == num_bidders);
+
+
+ for(size_t b = 0; b < num_bidders; ++b) {
+ assert( is_bidder_diagonal(b) == bidders.at(b).is_diagonal() );
+ assert( is_bidder_normal(b) == bidders.at(b).is_normal() );
+ }
+
+ for(size_t i = 0; i < num_items; ++i) {
+ assert( is_item_diagonal(i) == items.at(i).is_diagonal() );
+ assert( is_item_normal(i) == items.at(i).is_normal() );
+ }
+
+ // check matching consistency
+ assert(bidders_to_items.size() == num_bidders);
+ assert(items_to_bidders.size() == num_bidders);
+
+ assert(std::count(bidders_to_items.begin(), bidders_to_items.end(), k_invalid_index) == std::count(items_to_bidders.begin(), items_to_bidders.end(), k_invalid_index));
+
+ Real true_partial_cost = 0.0;
+
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if (bidders_to_items[bidder_idx] != k_invalid_index) {
+ assert(items_to_bidders.at(bidders_to_items[bidder_idx]) == static_cast<int>(bidder_idx));
+ true_partial_cost += get_item_bidder_cost(bidders_to_items[bidder_idx], bidder_idx);
+ }
+ }
+
+ assert(fabs(partial_cost - true_partial_cost) < 0.00001);
+
+ for(size_t item_idx = 0; item_idx < num_items; ++item_idx) {
+ if (items_to_bidders[item_idx] != k_invalid_index) {
+ assert(bidders_to_items.at(items_to_bidders[item_idx]) == static_cast<int>(item_idx));
+ }
+ }
+
+#ifdef ORDERED_BY_PERSISTENCE
+ assert(unassigned_bidders.size() == unassigned_bidders_by_persistence.size());
+ assert(unassigned_items.size() == unassigned_items_by_persistence.size());
+
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if (bidders_to_items[bidder_idx] == k_invalid_index) {
+ assert(unassigned_bidders.count(bidder_idx) == 1);
+ assert(unassigned_bidders_by_persistence.count(std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx)) == 1);
+ } else {
+ assert(unassigned_bidders.count(bidder_idx) == 0);
+ assert(unassigned_bidders_by_persistence.count(std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx)) == 0);
+ }
+ }
+
+ for(size_t item_idx = 0; item_idx < num_items; ++item_idx) {
+ if (items_to_bidders[item_idx] == k_invalid_index) {
+ assert(unassigned_items.count(item_idx) == 1);
+ assert(unassigned_items_by_persistence.count(std::make_pair(items[item_idx].persistence_lp(1.0), item_idx)) == 1);
+ } else {
+ assert(unassigned_items.count(item_idx) == 0);
+ assert(unassigned_items_by_persistence.count(std::make_pair(items[item_idx].persistence_lp(1.0), item_idx)) == 0);
+ }
+ }
+#endif
+
+
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::check_epsilon_css()
+{
+#ifdef DEBUG_FR_AUCTION
+ sanity_check();
+
+ std::vector<double> b_prices = reverse_oracle.get_prices();
+ std::vector<double> i_prices = forward_oracle.get_prices();
+ double eps = forward_oracle.get_epsilon();
+
+ for(size_t b = 0; b < num_bidders; ++b) {
+ for(size_t i = 0; i < num_items; ++i) {
+ if(((is_bidder_normal(b) and is_item_diagonal(i)) or (is_bidder_diagonal(b) and is_item_normal(i))) and b != i)
+ continue;
+ assert(b_prices[b] + i_prices[i] + eps >= -get_item_bidder_cost(i, b) - 0.000001);
+ }
+ }
+
+ for(size_t b = 0; b < num_bidders; ++b) {
+ auto i = bidders_to_items[b];
+ if (i != k_invalid_index) {
+ assert( fabs(b_prices[b] + i_prices[i] + get_item_bidder_cost(i, b)) < 0.000001 );
+ }
+ }
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerFR<R, AO>::print_matching()
+{
+#ifdef DEBUG_FR_AUCTION
+ sanity_check();
+ for(size_t bidder_idx = 0; bidder_idx < bidders_to_items.size(); ++bidder_idx) {
+ if (bidders_to_items[bidder_idx] >= 0) {
+ auto pA = bidders[bidder_idx];
+ auto pB = items[bidders_to_items[bidder_idx]];
+ std::cout << pA << " <-> " << pB << "+" << pow(dist_lp(pA, pB, internal_p), wasserstein_power) << std::endl;
+ } else {
+ assert(false);
+ }
+ }
+#endif
+}
+
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/auction_runner_gs.h b/wasserstein/include/auction_runner_gs.h
new file mode 100644
index 0000000..8ad95c2
--- /dev/null
+++ b/wasserstein/include/auction_runner_gs.h
@@ -0,0 +1,122 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_RUNNER_GS_H
+#define AUCTION_RUNNER_GS_H
+
+#include <memory>
+#include <unordered_set>
+
+#include "auction_oracle.h"
+
+namespace hera {
+namespace ws {
+
+template<class RealType_ = double, class AuctionOracle_ = AuctionOracleKDTreeRestricted<RealType_>, class PointContainer_ = std::vector<DiagramPoint<RealType_>> > // alternatively: AuctionOracleLazyHeap --- TODO
+class AuctionRunnerGS {
+public:
+ using Real = RealType_;
+ using AuctionOracle = AuctionOracle_;
+ using DgmPoint = typename AuctionOracle::DiagramPointR;
+ using IdxValPairR = IdxValPair<Real>;
+ using PointContainer = PointContainer_;
+
+
+ AuctionRunnerGS(const PointContainer& A,
+ const PointContainer& B,
+ const AuctionParams<Real>& params,
+ const std::string& _log_filename_prefix = "");
+
+ void set_epsilon(Real new_val) { assert(epsilon > 0.0); epsilon = new_val; };
+ Real get_epsilon() const { return oracle.get_epsilon(); }
+ Real get_wasserstein_cost();
+ Real get_wasserstein_distance();
+ Real get_relative_error() const { return relative_error; };
+ void enable_logging(const char* log_filename, const size_t _max_unassigned_to_log);
+//private:
+ // private data
+ PointContainer bidders, items;
+ const size_t num_bidders;
+ const size_t num_items;
+ std::vector<IdxType> items_to_bidders;
+ std::vector<IdxType> bidders_to_items;
+ Real wasserstein_power;
+ Real epsilon;
+ Real delta;
+ Real internal_p;
+ Real initial_epsilon;
+ Real epsilon_common_ratio; // next epsilon = current epsilon / epsilon_common_ratio
+ const int max_num_phases; // maximal number of iterations of epsilon-scaling
+ bool tolerate_max_iter_exceeded;
+ Real weight_adj_const;
+ Real wasserstein_cost;
+ Real relative_error;
+ int dimension;
+ // to get the 2 best items
+ AuctionOracle oracle;
+ std::unordered_set<size_t> unassigned_bidders;
+ // private methods
+ void assign_item_to_bidder(const IdxType bidder_idx, const IdxType items_idx);
+ void run_auction();
+ void run_auction_phases(const int max_num_phases, const Real _initial_epsilon);
+ void run_auction_phase();
+ void flush_assignment();
+ // return 0, if item_idx is invalid
+ Real get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx, const bool tolerate_invalid_idx = false) const;
+
+ // for debug only
+ void sanity_check();
+ void print_debug();
+ int count_unhappy();
+ void print_matching();
+ Real getDistanceToQthPowerInternal();
+ int num_phase { 0 };
+ int num_rounds { 0 };
+ bool is_distance_computed {false};
+#ifdef LOG_AUCTION
+ bool log_auction { false };
+ std::shared_ptr<spdlog::logger> console_logger;
+ std::shared_ptr<spdlog::logger> plot_logger;
+ std::unordered_set<size_t> unassigned_items;
+ size_t max_unassigned_to_log { 0 };
+ const char* logger_name = "auction_detailed_logger"; // the name in spdlog registry; filename is provided as parameter in enable_logging
+ const Real total_items_persistence;
+ const Real total_bidders_persistence;
+ Real partial_cost;
+ Real unassigned_bidders_persistence;
+ Real unassigned_items_persistence;
+#endif
+};
+
+} // ws
+} // hera
+
+
+#include "auction_runner_gs.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_runner_gs.hpp b/wasserstein/include/auction_runner_gs.hpp
new file mode 100644
index 0000000..4ef94db
--- /dev/null
+++ b/wasserstein/include/auction_runner_gs.hpp
@@ -0,0 +1,494 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+
+#include <assert.h>
+#include <stdexcept>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <chrono>
+#include <numeric>
+
+#include "def_debug_ws.h"
+
+#define PRINT_DETAILED_TIMING
+
+#ifdef FOR_R_TDA
+#include "Rcpp.h"
+#undef DEBUG_AUCTION
+#endif
+
+
+namespace hera {
+namespace ws {
+
+// *****************************
+// AuctionRunnerGS
+// *****************************
+
+template<class R, class AO, class PC>
+AuctionRunnerGS<R, AO, PC>::AuctionRunnerGS(const PC& A,
+ const PC& B,
+ const AuctionParams<Real>& params,
+ const std::string& _log_filename_prefix) :
+ bidders(A),
+ items(B),
+ num_bidders(A.size()),
+ num_items(B.size()),
+ items_to_bidders(B.size(), k_invalid_index),
+ bidders_to_items(A.size(), k_invalid_index),
+ wasserstein_power(params.wasserstein_power),
+ delta(params.delta),
+ internal_p(params.internal_p),
+ initial_epsilon(params.initial_epsilon),
+ epsilon_common_ratio(params.epsilon_common_ratio == 0.0 ? 5.0 : params.epsilon_common_ratio),
+ max_num_phases(params.max_num_phases),
+ tolerate_max_iter_exceeded(params.tolerate_max_iter_exceeded),
+ dimension(params.dim),
+ oracle(bidders, items, params)
+#ifdef LOG_AUCTION
+ , total_items_persistence(std::accumulate(items.begin(),
+ items.end(),
+ R(0.0),
+ [params](const Real& ps, const DgmPoint& item)
+ { return ps + std::pow(item.persistence_lp(params.internal_p), params.wasserstein_power); }
+ ))
+
+ , total_bidders_persistence(std::accumulate(bidders.begin(),
+ bidders.end(),
+ R(0.0),
+ [params](const Real& ps, const DgmPoint& bidder)
+ { return ps + std::pow(bidder.persistence_lp(params.internal_p), params.wasserstein_power); }
+ ))
+ , partial_cost(0.0)
+ , unassigned_bidders_persistence(0.0)
+ , unassigned_items_persistence(0.0)
+#endif
+
+{
+ assert(initial_epsilon >= 0.0 );
+ assert(epsilon_common_ratio >= 0.0 );
+ assert(A.size() == B.size());
+#ifdef LOG_AUCTION
+
+ unassigned_items_persistence = total_items_persistence;
+ unassigned_bidders_persistence = total_bidders_persistence;
+
+ console_logger = spdlog::get("console");
+ if (not console_logger) {
+ console_logger = spdlog::stdout_logger_st("console");
+ }
+ console_logger->set_pattern("[%H:%M:%S.%e] %v");
+ console_logger->debug("Gauss-Seidel, num_bidders = {0}", num_bidders);
+
+ plot_logger = spdlog::get("plot_logger");
+ if (not plot_logger) {
+ plot_logger = spdlog::basic_logger_st("plot_logger", "plot_logger.txt");
+ plot_logger->info("New plot starts here");
+ plot_logger->set_pattern("%v");
+ }
+#endif
+
+}
+
+#ifdef LOG_AUCTION
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::enable_logging(const char* log_filename, const size_t _max_unassigned_to_log)
+{
+ log_auction = true;
+ max_unassigned_to_log = _max_unassigned_to_log;
+
+ auto log = spdlog::basic_logger_st(logger_name, log_filename);
+ log->set_pattern("%v");
+}
+#endif
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::assign_item_to_bidder(IdxType item_idx, IdxType bidder_idx)
+{
+ num_rounds++;
+ sanity_check();
+ // only unassigned bidders should submit bids and get items
+ assert(bidders_to_items[bidder_idx] == k_invalid_index);
+ IdxType old_item_owner = items_to_bidders[item_idx];
+
+ // set new owner
+ bidders_to_items[bidder_idx] = item_idx;
+ items_to_bidders[item_idx] = bidder_idx;
+ // remove bidder from the list of unassigned bidders
+ unassigned_bidders.erase(bidder_idx);
+
+ // old owner becomes unassigned
+ if (old_item_owner != k_invalid_index) {
+ bidders_to_items[old_item_owner] = k_invalid_index;
+ unassigned_bidders.insert(old_item_owner);
+ }
+
+
+#ifdef LOG_AUCTION
+
+ partial_cost += get_item_bidder_cost(item_idx, bidder_idx, true);
+ partial_cost -= get_item_bidder_cost(item_idx, old_item_owner, true);
+
+ unassigned_items.erase(item_idx);
+
+ unassigned_bidders_persistence -= std::pow(bidders[bidder_idx].persistence_lp(internal_p), wasserstein_power);
+
+ if (old_item_owner != k_invalid_index) {
+ // item has been assigned to some other bidder,
+ // and he became unassigned
+ unassigned_bidders_persistence += std::pow(bidders[old_item_owner].persistence_lp(internal_p), wasserstein_power);
+ } else {
+ // item was unassigned before
+ unassigned_items_persistence -= std::pow(items[item_idx].persistence_lp(internal_p), wasserstein_power);
+ }
+
+ if (log_auction)
+ plot_logger->info("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}",
+ num_phase,
+ num_rounds,
+ unassigned_bidders.size(),
+ unassigned_items_persistence,
+ unassigned_bidders_persistence,
+ unassigned_items_persistence + unassigned_bidders_persistence,
+ partial_cost,
+ total_bidders_persistence,
+ total_items_persistence,
+ oracle.get_epsilon()
+ );
+
+
+ if (log_auction and unassigned_bidders.size() <= max_unassigned_to_log) {
+ auto logger = spdlog::get(logger_name);
+ if (logger) {
+ auto item = items[item_idx];
+ auto bidder = bidders[bidder_idx];
+ logger->info("{0} # ({1}, {2}) # ({3}, {4}) # {5} # {6} # {7}",
+ num_rounds,
+ item.getRealX(),
+ item.getRealY(),
+ bidder.getRealX(),
+ bidder.getRealY(),
+ format_point_set_to_log(unassigned_bidders, bidders),
+ format_point_set_to_log(unassigned_items, items),
+ oracle.get_epsilon());
+ }
+ }
+#endif
+}
+
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::flush_assignment()
+{
+ for(auto& b2i : bidders_to_items) {
+ b2i = k_invalid_index;
+ }
+ for(auto& i2b : items_to_bidders) {
+ i2b = k_invalid_index;
+ }
+ // we must flush assignment only after we got perfect matching
+ assert(unassigned_bidders.empty());
+ // all bidders become unassigned
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ unassigned_bidders.insert(bidder_idx);
+ }
+ assert(unassigned_bidders.size() == bidders.size());
+
+#ifdef LOG_AUCTION
+ partial_cost = 0.0;
+ unassigned_bidders_persistence = total_bidders_persistence;
+ unassigned_items_persistence = total_items_persistence;
+
+ for(size_t item_idx = 0; item_idx < items.size(); ++item_idx) {
+ unassigned_items.insert(item_idx);
+ }
+#endif
+
+ oracle.adjust_prices();
+}
+
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::run_auction_phases(const int max_num_phases, const Real _initial_epsilon)
+{
+ relative_error = std::numeric_limits<Real>::max();
+ // choose some initial epsilon
+ oracle.set_epsilon(_initial_epsilon);
+ assert( oracle.get_epsilon() > 0 );
+ for(int phase_num = 0; phase_num < max_num_phases; ++phase_num) {
+ flush_assignment();
+ run_auction_phase();
+ Real current_result = getDistanceToQthPowerInternal();
+// Real current_result_1 = 0.0;
+// for(size_t i = 0; i < num_bidders; ++i) {
+// current_result_1 += oracle.traits.distance(bidders[i], items[bidders_to_items[i]]);
+// }
+// current_result = current_result_1;
+// assert(fabs(current_result - current_result_1) < 0.001);
+ Real denominator = current_result - num_bidders * oracle.get_epsilon();
+ current_result = pow(current_result, 1.0 / wasserstein_power);
+#ifdef LOG_AUCTION
+ console_logger->info("Phase {0} done, num_rounds (cumulative) = {1}, current_result = {2}, epsilon = {3}",
+ phase_num, format_int(num_rounds), current_result,
+ oracle.get_epsilon());
+#endif
+ if ( denominator <= 0 ) {
+#ifdef LOG_AUCTION
+ console_logger->info("Epsilon is too large");
+#endif
+ } else {
+ denominator = pow(denominator, 1.0 / wasserstein_power);
+ Real numerator = current_result - denominator;
+ relative_error = numerator / denominator;
+ // spdlog::get("console")->info("relative error = {} / {} = {}, result = {}", numerator, denominator, relative_error, current_result);
+#ifdef LOG_AUCTION
+ console_logger->info("error = {0} / {1} = {2}",
+ numerator, denominator, relative_error);
+#endif
+ if (relative_error <= delta) {
+ break;
+ }
+ }
+ // decrease epsilon for the next iteration
+ oracle.set_epsilon( oracle.get_epsilon() / epsilon_common_ratio );
+ }
+}
+
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::run_auction()
+{
+
+ if (num_bidders == 1) {
+ assign_item_to_bidder(0, 0);
+ wasserstein_cost = get_item_bidder_cost(0,0);
+ is_distance_computed = true;
+ return;
+ }
+
+ double init_eps = ( initial_epsilon > 0.0 ) ? initial_epsilon : oracle.max_val_ / 4.0 ;
+ run_auction_phases(max_num_phases, init_eps);
+ is_distance_computed = true;
+ if (relative_error > delta and not tolerate_max_iter_exceeded) {
+#ifndef FOR_R_TDA
+ std::cerr << "Maximum iteration number exceeded, exiting. Current result is: ";
+ std::cerr << pow(wasserstein_cost, 1.0/wasserstein_power) << std::endl;
+#endif
+ throw std::runtime_error("Maximum iteration number exceeded");
+ }
+}
+
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::run_auction_phase()
+{
+ num_phase++;
+ //std::cout << "Entered run_auction_phase" << std::endl;
+ do {
+ size_t bidder_idx = *unassigned_bidders.begin();
+ auto optimal_bid = oracle.get_optimal_bid(bidder_idx);
+ auto optimal_item_idx = optimal_bid.first;
+ auto bid_value = optimal_bid.second;
+ assign_item_to_bidder(optimal_bid.first, bidder_idx);
+ oracle.set_price(optimal_item_idx, bid_value);
+ //print_debug();
+#ifdef FOR_R_TDA
+ if ( num_rounds % 10000 == 0 ) {
+ Rcpp::check_user_interrupt();
+ }
+#endif
+ } while (not unassigned_bidders.empty());
+ //std::cout << "run_auction_phase finished" << std::endl;
+
+#ifdef DEBUG_AUCTION
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if ( bidders_to_items[bidder_idx] < 0 or bidders_to_items[bidder_idx] >= (IdxType)num_bidders) {
+ std::cerr << "After auction terminated bidder " << bidder_idx;
+ std::cerr << " has no items assigned" << std::endl;
+ throw std::runtime_error("Auction did not give a perfect matching");
+ }
+ }
+#endif
+
+}
+
+template<class R, class AO, class PC>
+R AuctionRunnerGS<R, AO, PC>::get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx, const bool tolerate_invalid_idx) const
+{
+ if (item_idx != k_invalid_index and bidder_idx != k_invalid_index) {
+ return std::pow(dist_lp(bidders[bidder_idx], items[item_idx], internal_p, dimension), wasserstein_power);
+ } else {
+ if (tolerate_invalid_idx)
+ return R(0.0);
+ else
+ throw std::runtime_error("Invalid idx in get_item_bidder_cost, item_idx = " + std::to_string(item_idx) + ", bidder_idx = " + std::to_string(bidder_idx));
+ }
+}
+
+template<class R, class AO, class PC>
+R AuctionRunnerGS<R, AO, PC>::getDistanceToQthPowerInternal()
+{
+ sanity_check();
+ Real result = 0.0;
+ //std::cout << "-------------------------------------------------------------------------\n";
+ for(size_t bIdx = 0; bIdx < num_bidders; ++bIdx) {
+ result += get_item_bidder_cost(bidders_to_items[bIdx], bIdx);
+ }
+ //std::cout << "-------------------------------------------------------------------------\n";
+ wasserstein_cost = result;
+ return result;
+}
+
+template<class R, class AO, class PC>
+R AuctionRunnerGS<R, AO, PC>::get_wasserstein_distance()
+{
+ assert(is_distance_computed);
+ return pow(get_wasserstein_cost(), 1.0/wasserstein_power);
+}
+
+template<class R, class AO, class PC>
+R AuctionRunnerGS<R, AO, PC>::get_wasserstein_cost()
+{
+ assert(is_distance_computed);
+ return wasserstein_cost;
+}
+
+
+
+// Debug routines
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::print_debug()
+{
+#ifdef DEBUG_AUCTION
+ sanity_check();
+ std::cout << "**********************" << std::endl;
+ std::cout << "Current assignment:" << std::endl;
+ for(size_t idx = 0; idx < bidders_to_items.size(); ++idx) {
+ std::cout << idx << " <--> " << bidders_to_items[idx] << std::endl;
+ }
+ std::cout << "Weights: " << std::endl;
+ //for(size_t i = 0; i < num_bidders; ++i) {
+ //for(size_t j = 0; j < num_items; ++j) {
+ //std::cout << oracle.weight_matrix[i][j] << " ";
+ //}
+ //std::cout << std::endl;
+ //}
+ std::cout << "Prices: " << std::endl;
+ for(const auto price : oracle.get_prices()) {
+ std::cout << price << std::endl;
+ }
+ std::cout << "**********************" << std::endl;
+#endif
+}
+
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::sanity_check()
+{
+#ifdef DEBUG_AUCTION
+ if (bidders_to_items.size() != num_bidders) {
+ std::cerr << "Wrong size of bidders_to_items, must be " << num_bidders << ", is " << bidders_to_items.size() << std::endl;
+ throw std::runtime_error("Wrong size of bidders_to_items");
+ }
+
+ if (items_to_bidders.size() != num_bidders) {
+ std::cerr << "Wrong size of items_to_bidders, must be " << num_bidders << ", is " << items_to_bidders.size() << std::endl;
+ throw std::runtime_error("Wrong size of items_to_bidders");
+ }
+
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ assert( bidders_to_items[bidder_idx] == k_invalid_index or ( bidders_to_items[bidder_idx] < (IdxType)num_items and bidders_to_items[bidder_idx] >= 0));
+
+ if ( bidders_to_items[bidder_idx] != k_invalid_index) {
+
+ if ( std::count(bidders_to_items.begin(),
+ bidders_to_items.end(),
+ bidders_to_items[bidder_idx]) > 1 ) {
+ std::cerr << "Item " << bidders_to_items[bidder_idx];
+ std::cerr << " appears in bidders_to_items more than once" << std::endl;
+ throw std::runtime_error("Duplicate in bidders_to_items");
+ }
+
+ if (items_to_bidders.at(bidders_to_items[bidder_idx]) != static_cast<int>(bidder_idx)) {
+ std::cerr << "Inconsitency: bidder_idx = " << bidder_idx;
+ std::cerr << ", item_idx in bidders_to_items = ";
+ std::cerr << bidders_to_items[bidder_idx];
+ std::cerr << ", bidder_idx in items_to_bidders = ";
+ std::cerr << items_to_bidders[bidders_to_items[bidder_idx]] << std::endl;
+ throw std::runtime_error("inconsistent mapping");
+ }
+ }
+ }
+
+ for(IdxType item_idx = 0; item_idx < static_cast<IdxType>(num_bidders); ++item_idx) {
+ assert( items_to_bidders[item_idx] == k_invalid_index or ( items_to_bidders[item_idx] < static_cast<IdxType>(num_items) and items_to_bidders[item_idx] >= 0));
+ if ( items_to_bidders.at(item_idx) != k_invalid_index) {
+
+ // check for uniqueness
+ if ( std::count(items_to_bidders.begin(),
+ items_to_bidders.end(),
+ items_to_bidders[item_idx]) > 1 ) {
+ std::cerr << "Bidder " << items_to_bidders[item_idx];
+ std::cerr << " appears in items_to_bidders more than once" << std::endl;
+ throw std::runtime_error("Duplicate in items_to_bidders");
+ }
+ // check for consistency
+ if (bidders_to_items.at(items_to_bidders.at(item_idx)) != static_cast<int>(item_idx)) {
+ std::cerr << "Inconsitency: item_idx = " << item_idx;
+ std::cerr << ", bidder_idx in items_to_bidders = ";
+ std::cerr << items_to_bidders[item_idx];
+ std::cerr << ", item_idx in bidders_to_items= ";
+ std::cerr << bidders_to_items[items_to_bidders[item_idx]] << std::endl;
+ throw std::runtime_error("inconsistent mapping");
+ }
+ }
+ }
+#endif
+}
+
+template<class R, class AO, class PC>
+void AuctionRunnerGS<R, AO, PC>::print_matching()
+{
+#ifdef DEBUG_AUCTION
+ sanity_check();
+ for(size_t bIdx = 0; bIdx < bidders_to_items.size(); ++bIdx) {
+ if (bidders_to_items[bIdx] != k_invalid_index) {
+ auto pA = bidders[bIdx];
+ auto pB = items[bidders_to_items[bIdx]];
+ std::cout << pA << " <-> " << pB << "+" << pow(dist_lp(pA, pB, internal_p, dimension), wasserstein_power) << std::endl;
+ } else {
+ assert(false);
+ }
+ }
+#endif
+}
+
+} // ws
+} // hera
diff --git a/wasserstein/include/auction_runner_gs_single_diag.h b/wasserstein/include/auction_runner_gs_single_diag.h
new file mode 100644
index 0000000..f32fbbc
--- /dev/null
+++ b/wasserstein/include/auction_runner_gs_single_diag.h
@@ -0,0 +1,149 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef AUCTION_RUNNER_GS_SINGLE_DIAG_H
+#define AUCTION_RUNNER_GS_SINGLE_DIAG_H
+
+#include <unordered_set>
+#include <unordered_map>
+
+#include "auction_oracle.h"
+
+namespace hera {
+namespace ws {
+
+// the two parameters that you can tweak in auction algorithm are:
+// 1. epsilon_common_ratio
+// 2. max_iter_num
+
+template<class RealType_, class AuctionOracle_ = AuctionOracleKDTreeSingleDiag<RealType_> > // alternatively: AuctionOracleLazyHeap --- TODO
+class AuctionRunnerGaussSeidelSingleDiag {
+public:
+ using RealType = RealType_;
+ using Real = RealType_;
+ using AuctionOracle = AuctionOracle_;
+ using DgmPoint = DiagramPoint<Real>;
+ using DgmPointVec = std::vector<DgmPoint>;
+ using DiagonalBidR = DiagonalBid<Real>;
+
+
+
+ AuctionRunnerGaussSeidelSingleDiag(const DgmPointVec& A,
+ const DgmPointVec& B,
+ const Real q,
+ const Real _delta,
+ const Real _internal_p,
+ const Real _initial_epsilon,
+ const Real _eps_factor,
+ const int _max_iter_num = std::numeric_limits<int>::max());
+
+ void set_epsilon(Real new_val) { oracle->set_epsilon(new_val); };
+ Real get_epsilon() const { return oracle->get_epsilon(); }
+ Real get_wasserstein_cost();
+ Real get_wasserstein_distance();
+ Real get_relative_error() const { return relative_error; };
+ void enable_logging(const char* log_filename, const size_t _max_unassigned_to_log);
+//private:
+ // private data
+ DgmPointVec bidders, items;
+ const size_t num_bidders;
+ const size_t num_items;
+ size_t num_normal_bidders;
+ size_t num_diag_bidders;
+ size_t num_normal_items;
+ size_t num_diag_items;
+ std::vector<IdxType> items_to_bidders;
+ std::vector<IdxType> bidders_to_items;
+ const Real wasserstein_power;
+ const Real delta;
+ const Real internal_p;
+ const Real initial_epsilon;
+ Real epsilon_common_ratio; // next epsilon = current epsilon / epsilon_common_ratio
+ const int max_iter_num; // maximal number of iterations of epsilon-scaling
+ Real weight_adj_const;
+ Real wasserstein_cost;
+ Real relative_error;
+ // to get the 2 best items we use oracle
+ std::unique_ptr<AuctionOracle> oracle;
+ // unassigned guys
+ std::unordered_set<size_t> unassigned_normal_bidders;
+ std::unordered_set<size_t> unassigned_diag_bidders;
+ // private methods
+ //
+ void process_diagonal_bid(const DiagonalBidR& bid);
+
+ void assign_item_to_bidder(const IdxType item_idx,
+ const IdxType bidder_idx,
+ const IdxType old_owner_idx,
+ const bool item_is_diagonal,
+ const bool bidder_is_diagonal,
+ const bool call_set_prices = false,
+ const Real new_price = std::numeric_limits<Real>::max());
+
+ void run_auction();
+ void run_auction_phases(const int max_num_phases, const Real _initial_epsilon);
+ void run_auction_phase();
+ void flush_assignment();
+ // return 0, if item_idx is invalid
+ Real get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx, const bool tolerate_invalid_idx = false) const;
+
+ bool is_bidder_diagonal(const size_t bidder_idx) const;
+ bool is_bidder_normal(const size_t bidder_idx) const;
+ bool is_item_diagonal(const size_t item_idx) const;
+ bool is_item_normal(const size_t item_idx) const;
+
+ OwnerType get_owner_type(size_t bidder_idx) const;
+
+ // for debug only
+ void sanity_check();
+ void print_debug();
+ int count_unhappy();
+ void print_matching();
+ Real getDistanceToQthPowerInternal();
+ int num_phase { 0 };
+ int num_rounds { 0 };
+#ifdef LOG_AUCTION
+ bool log_auction { false };
+ std::unordered_set<size_t> unassigned_items;
+ size_t max_unassigned_to_log { 0 };
+ const char* logger_name = "auction_detailed_logger"; // the name in spdlog registry; filename is provided as parameter in enable_logging
+ const Real total_items_persistence;
+ const Real total_bidders_persistence;
+ Real partial_cost;
+ Real unassigned_bidders_persistence;
+ Real unassigned_items_persistence;
+#endif
+};
+
+} // ws
+} // hera
+
+
+#include "auction_runner_gs_single_diag.hpp"
+
+#endif
diff --git a/wasserstein/include/auction_runner_gs_single_diag.hpp b/wasserstein/include/auction_runner_gs_single_diag.hpp
new file mode 100644
index 0000000..a3c401e
--- /dev/null
+++ b/wasserstein/include/auction_runner_gs_single_diag.hpp
@@ -0,0 +1,738 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+
+#include <assert.h>
+#include <stdexcept>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <chrono>
+
+#include "def_debug_ws.h"
+
+#define PRINT_DETAILED_TIMING
+
+#ifdef FOR_R_TDA
+#include "Rcpp.h"
+#undef DEBUG_AUCTION
+#endif
+
+
+namespace hera {
+namespace ws {
+
+// *****************************
+// AuctionRunnerGaussSeidelSingleDiag
+// *****************************
+
+template<class R, class AO>
+std::ostream& operator<<(std::ostream& s, const AuctionRunnerGaussSeidelSingleDiag<R, AO>& ar)
+{
+ s << "--------------------------------------------------\n";
+ s << "AuctionRunnerGaussSeidelSingleDiag, current assignment, bidders_to_items:" << std::endl;
+ for(size_t idx = 0; idx < ar.bidders_to_items.size(); ++idx) {
+ s << idx << " <--> " << ar.bidders_to_items[idx] << std::endl;
+ }
+ s << "--------------------------------------------------\n";
+ s << "AuctionRunnerGaussSeidelSingleDiag, current assignment, items_to_bidders:" << std::endl;
+ for(size_t idx = 0; idx < ar.items_to_bidders.size(); ++idx) {
+ s << idx << " <--> " << ar.items_to_bidders[idx] << std::endl;
+ }
+ s << "--------------------------------------------------\n";
+ s << "AuctionRunnerGaussSeidelSingleDiag, prices:" << std::endl;
+ for(size_t item_idx = 0; item_idx < ar.num_items; ++item_idx) {
+ s << item_idx << ": " << ar.oracle->get_price(item_idx) << std::endl;
+ }
+ s << "--------------------------------------------------\n";
+ s << "AuctionRunnerGaussSeidelSingleDiag, oracle :" << *(ar.oracle) << std::endl;
+ s << "--------------------------------------------------\n";
+ return s;
+}
+
+
+template<class R, class AO>
+AuctionRunnerGaussSeidelSingleDiag<R, AO>::AuctionRunnerGaussSeidelSingleDiag(const DgmPointVec& A,
+ const DgmPointVec& B,
+ const Real q,
+ const Real _delta,
+ const Real _internal_p,
+ const Real _initial_epsilon,
+ const Real _eps_factor,
+ const int _max_iter_num) :
+ bidders(A),
+ items(B),
+ num_bidders(A.size()),
+ num_items(B.size()),
+ items_to_bidders(B.size(), k_invalid_index),
+ bidders_to_items(A.size(), k_invalid_index),
+ wasserstein_power(q),
+ delta(_delta),
+ internal_p(_internal_p),
+ initial_epsilon(_initial_epsilon),
+ epsilon_common_ratio(_eps_factor == 0.0 ? 5.0 : _eps_factor),
+ max_iter_num(_max_iter_num)
+#ifdef LOG_AUCTION
+ , total_items_persistence(std::accumulate(items.begin(),
+ items.end(),
+ R(0.0),
+ [_internal_p, q](const Real& ps, const DgmPoint& item)
+ { return ps + std::pow(item.persistence_lp(_internal_p), q); }
+ ))
+
+ , total_bidders_persistence(std::accumulate(bidders.begin(),
+ bidders.end(),
+ R(0.0),
+ [_internal_p, q](const Real& ps, const DgmPoint& bidder)
+ { return ps + std::pow(bidder.persistence_lp(_internal_p), q); }
+ ))
+ , partial_cost(0.0)
+ , unassigned_bidders_persistence(0.0)
+ , unassigned_items_persistence(0.0)
+#endif
+
+{
+ assert(initial_epsilon >= 0.0 );
+ assert(epsilon_common_ratio >= 0.0 );
+ assert(A.size() == B.size());
+ oracle = std::unique_ptr<AuctionOracle>(new AuctionOracle(bidders, items, wasserstein_power, internal_p));
+
+ for(num_normal_bidders = 0; num_normal_bidders < num_bidders; ++num_normal_bidders) {
+ if (bidders[num_normal_bidders].is_diagonal())
+ break;
+ }
+
+ num_diag_bidders = num_bidders - num_normal_bidders;
+ num_diag_items = num_normal_bidders;
+ num_normal_items = num_items - num_diag_items;
+
+ for(size_t i = num_normal_bidders; i < num_bidders; ++i) {
+ assert(bidders[i].is_diagonal());
+ }
+
+#ifdef LOG_AUCTION
+
+ unassigned_items_persistence = total_items_persistence;
+ unassigned_bidders_persistence = total_bidders_persistence;
+
+ if (not spdlog::get("plot_logger")) {
+ auto log = spdlog::basic_logger_st("plot_logger", "plot_logger.txt");
+ log->info("New plot starts here");
+ log->set_pattern("%v");
+ }
+#endif
+
+}
+
+#ifdef LOG_AUCTION
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::enable_logging(const char* log_filename, const size_t _max_unassigned_to_log)
+{
+ log_auction = true;
+ max_unassigned_to_log = _max_unassigned_to_log;
+
+ auto log = spdlog::basic_logger_st(logger_name, log_filename);
+ log->set_pattern("%v");
+}
+#endif
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::process_diagonal_bid(const DiagonalBidR& bid)
+{
+
+ //std::cout << "Enter process_diagonal_bid, bid = " << bid << std::endl;
+
+ // increase price of already assigned normal items
+ for(size_t k = 0; k < bid.assigned_normal_items.size(); ++k) {
+ size_t assigned_normal_item_idx = bid.assigned_normal_items[k];
+ Real new_price = bid.assigned_normal_items_bid_values[k];
+ bool item_is_diagonal = false;
+ bool bidder_is_diagonal = true;
+
+ // TODO: SPECIAL PROCEDURE HEER`
+ oracle->set_price(assigned_normal_item_idx, new_price, item_is_diagonal, bidder_is_diagonal, OwnerType::k_diagonal);
+ }
+
+ // set common diag-diag price
+ // if diag_assigned_to_diag_slice_ is empty, it will be
+ // numeric_limits<Real>::max()
+
+ oracle->diag_to_diag_price_ = bid.diag_to_diag_value;
+
+ int unassigned_diag_idx = 0;
+ auto unassigned_diag_item_iter = oracle->diag_unassigned_slice_.begin();
+ auto bid_vec_idx = 0;
+ for(const auto diag_bidder_idx : unassigned_diag_bidders) {
+ if (unassigned_diag_idx < bid.num_from_unassigned_diag) {
+ // take diagonal point from unassigned slice
+
+ //std::cout << "assigning to diag_bidder_idx = " << diag_bidder_idx << std::endl;
+ assert(unassigned_diag_item_iter != oracle->diag_unassigned_slice_.end());
+
+ auto item_idx = *unassigned_diag_item_iter;
+
+ ++unassigned_diag_idx;
+ ++unassigned_diag_item_iter;
+ assign_item_to_bidder(item_idx, diag_bidder_idx, k_invalid_index, true, true, false);
+ } else {
+ // take point from best_item_indices
+ size_t item_idx = bid.best_item_indices[bid_vec_idx];
+ Real new_price = bid.bid_values[bid_vec_idx];
+ bid_vec_idx++;
+
+ auto old_owner_idx = items_to_bidders[item_idx];
+ bool item_is_diagonal = is_item_diagonal(item_idx);
+
+ assign_item_to_bidder(item_idx, diag_bidder_idx, old_owner_idx, item_is_diagonal, true, true, new_price);
+ }
+ }
+
+ // all bids of diagonal bidders are satisfied
+ unassigned_diag_bidders.clear();
+
+ if (oracle->diag_unassigned_slice_.empty()) {
+ oracle->diag_unassigned_price_ = std::numeric_limits<Real>::max();
+ }
+
+ //std::cout << "Exit process_diagonal_bid\n" << *this;
+}
+
+template<class R, class AO>
+bool AuctionRunnerGaussSeidelSingleDiag<R, AO>::is_bidder_diagonal(const size_t bidder_idx) const
+{
+ return bidder_idx >= num_normal_bidders;
+}
+
+template<class R, class AO>
+bool AuctionRunnerGaussSeidelSingleDiag<R, AO>::is_bidder_normal(const size_t bidder_idx) const
+{
+ return bidder_idx < num_normal_bidders;
+}
+
+template<class R, class AO>
+bool AuctionRunnerGaussSeidelSingleDiag<R, AO>::is_item_diagonal(const size_t item_idx) const
+{
+ return item_idx < num_diag_items;
+}
+
+template<class R, class AO>
+bool AuctionRunnerGaussSeidelSingleDiag<R, AO>::is_item_normal(const size_t item_idx) const
+{
+ return item_idx >= num_diag_items;
+}
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::assign_item_to_bidder(const IdxType item_idx,
+ const IdxType bidder_idx,
+ const IdxType old_owner_idx,
+ const bool item_is_diagonal,
+ const bool bidder_is_diagonal,
+ const bool call_set_price,
+ const R new_price)
+{
+ //std::cout << "Enter assign_item_to_bidder, " << std::boolalpha ;
+ //std::cout << "item_idx = " << item_idx << ", bidder_idx = " << bidder_idx << ", old_owner_idx = " << old_owner_idx << ", item_is_diagonal = " << item_is_diagonal << ", bidder_is_diagonal = " << bidder_is_diagonal << std::endl;
+ //std::cout << "################################################################################" << std::endl;
+ //std::cout << *this << std::endl;
+ //std::cout << *(this->oracle) << std::endl;
+ //std::cout << "################################################################################" << std::endl;
+ num_rounds++;
+
+ // for readability
+ const bool item_is_normal = not item_is_diagonal;
+ const bool bidder_is_normal = not bidder_is_diagonal;
+
+ // only unassigned bidders should submit bids and get items
+ assert(bidders_to_items[bidder_idx] == k_invalid_index);
+
+
+ // update matching information
+ bidders_to_items[bidder_idx] = item_idx;
+ items_to_bidders[item_idx] = bidder_idx;
+
+
+ // remove bidder from the list of unassigned bidders
+ // for diagonal bidders we don't need to: in Gauss-Seidel they are all
+ // processed at once, so the set unassigned_diag_bidders will be cleared
+ if (bidder_is_normal) {
+ unassigned_normal_bidders.erase(bidder_idx);
+ }
+
+ OwnerType old_owner_type = get_owner_type(old_owner_idx);
+
+ if (old_owner_type != OwnerType::k_none) {
+ bidders_to_items[old_owner_idx] = k_invalid_index;
+ }
+
+ switch(old_owner_type)
+ {
+ case OwnerType::k_normal : unassigned_normal_bidders.insert(old_owner_idx);
+ break;
+ case OwnerType::k_diagonal : unassigned_diag_bidders.insert(old_owner_idx);
+ break;
+ case OwnerType::k_none : break;
+ }
+
+
+ // update normal_items_assigned_to_diag_
+
+ if (old_owner_type == OwnerType::k_diagonal and item_is_normal and bidder_is_normal) {
+ // normal item was stolen from diagonal, erase
+ assert( oracle->normal_items_assigned_to_diag_.count(item_idx) == 1 );
+ oracle->normal_items_assigned_to_diag_.erase(item_idx);
+ } else if (bidder_is_diagonal and item_is_normal and old_owner_type != OwnerType::k_diagonal) {
+ // diagonal bidder got a new normal item, insert
+ assert(oracle->normal_items_assigned_to_diag_.count(item_idx) == 0);
+ oracle->normal_items_assigned_to_diag_.insert(item_idx);
+ }
+
+
+ // update diag_assigned_to_diag_slice_
+ if (item_is_diagonal and bidder_is_normal and old_owner_type == OwnerType::k_diagonal) {
+ assert( oracle->diag_assigned_to_diag_slice_.count(item_idx) == 1);
+ oracle->diag_assigned_to_diag_slice_.erase(item_idx);
+ } else if (item_is_diagonal and bidder_is_diagonal) {
+ assert( old_owner_type != OwnerType::k_diagonal ); // diagonal does not steal from itself
+ assert( oracle->diag_assigned_to_diag_slice_.count(item_idx) == 0);
+ oracle->diag_assigned_to_diag_slice_.insert(item_idx);
+ }
+
+ // update diag_unassigned_slice_
+ if (item_is_diagonal and old_owner_type == OwnerType::k_none) {
+ oracle->diag_unassigned_slice_.erase(item_idx);
+ }
+
+ if ( not (not call_set_price or new_price != std::numeric_limits<R>::max())) {
+ std::cout << "In the middle of assign_item_to_bidder, " << std::boolalpha ;
+ std::cout << "item_idx = " << item_idx << ", bidder_idx = " << bidder_idx << ", old_owner_idx = " << old_owner_idx << ", item_is_diagonal = " << item_is_diagonal << ", bidder_is_diagonal = " << bidder_is_diagonal << std::endl;
+ std::cout << "################################################################################" << std::endl;
+ std::cout << *this << std::endl;
+ std::cout << "################################################################################" << std::endl;
+ }
+ assert(not call_set_price or new_price != std::numeric_limits<R>::max());
+ if (call_set_price) {
+ oracle->set_price(item_idx, new_price, item_is_diagonal, bidder_is_diagonal, old_owner_type);
+ }
+
+ //std::cout << "Exit assign_item_to_bidder, state\n" << *this << std::endl;
+
+#ifdef LOG_AUCTION
+
+ partial_cost += get_item_bidder_cost(item_idx, bidder_idx, true);
+ partial_cost -= get_item_bidder_cost(item_idx, old_owner_idx, true);
+
+ unassigned_items.erase(item_idx);
+
+ unassigned_bidders_persistence -= std::pow(bidders[bidder_idx].persistence_lp(internal_p), wasserstein_power);
+
+ if (old_owner_type != OwnerType::k_none) {
+ // item has been assigned to some other bidder,
+ // and he became unassigned
+ unassigned_bidders_persistence += std::pow(bidders[old_owner_idx].persistence_lp(internal_p), wasserstein_power);
+ } else {
+ // item was unassigned before
+ unassigned_items_persistence -= std::pow(items[item_idx].persistence_lp(internal_p), wasserstein_power);
+ }
+
+ auto plot_logger = spdlog::get("plot_logger");
+ plot_logger->info("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10}",
+ num_phase,
+ num_rounds,
+ unassigned_normal_bidders.size(),
+ unassigned_diag_bidders.size(),
+ unassigned_items_persistence,
+ unassigned_bidders_persistence,
+ unassigned_items_persistence + unassigned_bidders_persistence,
+ partial_cost,
+ total_bidders_persistence,
+ total_items_persistence,
+ oracle->get_epsilon()
+ );
+
+
+ if (log_auction and unassigned_normal_bidders.size() + unassigned_diag_bidders.size() <= max_unassigned_to_log) {
+ auto logger = spdlog::get(logger_name);
+ if (logger) {
+ auto item = items[item_idx];
+ auto bidder = bidders[bidder_idx];
+ logger->info("{0} # ({1}, {2}) # ({3}, {4}) # {5} # {6} # {7} # {8}",
+ num_rounds,
+ item.getRealX(),
+ item.getRealY(),
+ bidder.getRealX(),
+ bidder.getRealY(),
+ format_point_set_to_log(unassigned_diag_bidders, bidders),
+ format_point_set_to_log(unassigned_normal_bidders, bidders),
+ format_point_set_to_log(unassigned_items, items),
+ oracle->get_epsilon());
+ }
+ }
+#endif
+}
+
+
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::flush_assignment()
+{
+ for(auto& b2i : bidders_to_items) {
+ b2i = k_invalid_index;
+ }
+ for(auto& i2b : items_to_bidders) {
+ i2b = k_invalid_index;
+ }
+
+ // we must flush assignment only after we got perfect matching
+ assert(unassigned_normal_bidders.empty() and unassigned_diag_bidders.empty());
+ // all bidders become unassigned
+ for(size_t bidder_idx = 0; bidder_idx < num_normal_bidders; ++bidder_idx) {
+ unassigned_normal_bidders.insert(bidder_idx);
+ }
+ for(size_t bidder_idx = num_normal_bidders; bidder_idx < num_bidders; ++bidder_idx) {
+ unassigned_diag_bidders.insert(bidder_idx);
+ }
+ assert(unassigned_normal_bidders.size() + unassigned_diag_bidders.size() == bidders.size());
+ assert(unassigned_normal_bidders.size() == num_normal_bidders);
+ assert(unassigned_diag_bidders.size() == num_diag_bidders);
+
+ oracle->flush_assignment();
+ oracle->adjust_prices();
+
+#ifdef LOG_AUCTION
+ partial_cost = 0.0;
+ unassigned_bidders_persistence = total_bidders_persistence;
+ unassigned_items_persistence = total_items_persistence;
+
+ for(size_t item_idx = 0; item_idx < items.size(); ++item_idx) {
+ unassigned_items.insert(item_idx);
+ }
+#endif
+
+}
+
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::run_auction_phases(const int max_num_phases, const Real _initial_epsilon)
+{
+ relative_error = std::numeric_limits<Real>::max();
+ // choose some initial epsilon
+ oracle->set_epsilon(_initial_epsilon);
+ assert( oracle->get_epsilon() > 0 );
+ for(int phase_num = 0; phase_num < max_num_phases; ++phase_num) {
+ flush_assignment();
+ run_auction_phase();
+ phase_num++;
+ //std::cout << "Iteration " << phase_num << " completed. " << std::endl;
+ // result is d^q
+ Real current_result = getDistanceToQthPowerInternal();
+ Real denominator = current_result - num_bidders * oracle->get_epsilon();
+ current_result = pow(current_result, 1.0 / wasserstein_power);
+ //std::cout << "Current result is " << current_result << std::endl;
+ if ( denominator <= 0 ) {
+ //std::cout << "Epsilon is too big." << std::endl;
+ } else {
+ denominator = pow(denominator, 1.0 / wasserstein_power);
+ Real numerator = current_result - denominator;
+ relative_error = numerator / denominator;
+ //std::cout << " numerator: " << numerator << " denominator: " << denominator << std::endl;
+ //std::cout << " error bound: " << numerator / denominator << std::endl;
+ // if relative error is greater than delta, continue
+ if (relative_error <= delta) {
+ break;
+ }
+ }
+ // decrease epsilon for the next iteration
+ oracle->set_epsilon( oracle->get_epsilon() / epsilon_common_ratio );
+ }
+ //print_matching();
+}
+
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::run_auction()
+{
+ double init_eps = ( initial_epsilon > 0.0 ) ? initial_epsilon : oracle->max_val_ / 4.0 ;
+ run_auction_phases(max_iter_num, init_eps);
+ if (relative_error > delta) {
+#ifndef FOR_R_TDA
+ std::cerr << "Maximum iteration number exceeded, exiting. Current result is: ";
+ std::cerr << pow(wasserstein_cost, 1.0/wasserstein_power) << std::endl;
+#endif
+ throw std::runtime_error("Maximum iteration number exceeded");
+ }
+}
+
+template<class R, class AO>
+OwnerType AuctionRunnerGaussSeidelSingleDiag<R, AO>::get_owner_type(size_t bidder_idx) const
+{
+ if (bidder_idx == k_invalid_index) {
+ return OwnerType::k_none;
+ } else if (is_bidder_diagonal(bidder_idx)) {
+ return OwnerType::k_diagonal;
+ } else {
+ return OwnerType::k_normal;
+ }
+}
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::run_auction_phase()
+{
+ num_phase++;
+ //std::cout << "Entered run_auction_phase" << std::endl;
+ do {
+
+ if (not unassigned_diag_bidders.empty()) {
+ // process all unassigned diagonal bidders
+ // easy for Gauss-Seidel: every bidder alwasy gets all he wants
+ //
+ sanity_check();
+ //std::cout << "Current state " << __LINE__ << *this << std::endl;
+ process_diagonal_bid(oracle->get_optimal_bids_for_diagonal( unassigned_diag_bidders.size() ));
+ sanity_check();
+ } else {
+ sanity_check();
+ // process normal unassigned bidder
+ size_t bidder_idx = *(unassigned_normal_bidders.begin());
+ auto optimal_bid = oracle->get_optimal_bid(bidder_idx);
+ auto optimal_item_idx = optimal_bid.first;
+ auto bid_value = optimal_bid.second;
+ bool item_is_diagonal = is_item_diagonal(optimal_item_idx);
+ size_t old_owner_idx = items_to_bidders[optimal_item_idx];
+
+ //OwnerType old_owner_type = get_owner_type(old_owner_idx);
+ //std::cout << "bidder_idx = " << bidder_idx << ", item_idx = " << optimal_item_idx << ", old_owner_type = " << old_owner_type << std::endl;
+
+ assign_item_to_bidder(optimal_item_idx, bidder_idx, old_owner_idx, item_is_diagonal, false, true, bid_value);
+ sanity_check();
+ }
+
+#ifdef FOR_R_TDA
+ if ( num_rounds % 10000 == 0 ) {
+ Rcpp::check_user_interrupt();
+ }
+#endif
+ } while (not (unassigned_diag_bidders.empty() and unassigned_normal_bidders.empty()));
+ //std::cout << "run_auction_phase finished" << std::endl;
+
+#ifdef DEBUG_AUCTION
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if ( bidders_to_items[bidder_idx] < 0 or bidders_to_items[bidder_idx] >= (IdxType)num_bidders) {
+ std::cerr << "After auction terminated bidder " << bidder_idx;
+ std::cerr << " has no items assigned" << std::endl;
+ throw std::runtime_error("Auction did not give a perfect matching");
+ }
+ }
+#endif
+
+}
+
+template<class R, class AO>
+R AuctionRunnerGaussSeidelSingleDiag<R, AO>::get_item_bidder_cost(size_t item_idx, size_t bidder_idx, const bool tolerate_invalid_idx) const
+{
+ if (item_idx != k_invalid_index and bidder_idx != k_invalid_index) {
+ // skew edges are replaced by edges to projection
+ if (is_bidder_diagonal(bidder_idx) and is_item_normal(item_idx)) {
+ bidder_idx = item_idx;
+ } else if (is_bidder_normal(bidder_idx) and is_item_diagonal(item_idx)) {
+ item_idx = bidder_idx;
+ }
+ return std::pow(dist_lp(bidders[bidder_idx], items[item_idx], internal_p),
+ wasserstein_power);
+ } else {
+ if (tolerate_invalid_idx)
+ return R(0.0);
+ else
+ throw std::runtime_error("Invalid idx in get_item_bidder_cost, item_idx = " + std::to_string(item_idx) + ", bidder_idx = " + std::to_string(bidder_idx));
+ }
+}
+
+template<class R, class AO>
+R AuctionRunnerGaussSeidelSingleDiag<R, AO>::getDistanceToQthPowerInternal()
+{
+ sanity_check();
+ Real result = 0.0;
+ for(size_t bIdx = 0; bIdx < num_bidders; ++bIdx) {
+ result += get_item_bidder_cost(bidders_to_items[bIdx], bIdx);
+ }
+ wasserstein_cost = result;
+ return result;
+}
+
+template<class R, class AO>
+R AuctionRunnerGaussSeidelSingleDiag<R, AO>::get_wasserstein_distance()
+{
+ return pow(get_wasserstein_cost(), 1.0/wasserstein_power);
+}
+
+template<class R, class AO>
+R AuctionRunnerGaussSeidelSingleDiag<R, AO>::get_wasserstein_cost()
+{
+ run_auction();
+ return wasserstein_cost;
+}
+
+
+
+// Debug routines
+
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::print_debug()
+{
+#ifdef DEBUG_AUCTION
+ std::cout << "**********************" << std::endl;
+ std::cout << "Current assignment:" << std::endl;
+ for(size_t idx = 0; idx < bidders_to_items.size(); ++idx) {
+ std::cout << idx << " <--> " << bidders_to_items[idx] << std::endl;
+ }
+ std::cout << "Weights: " << std::endl;
+ //for(size_t i = 0; i < num_bidders; ++i) {
+ //for(size_t j = 0; j < num_items; ++j) {
+ //std::cout << oracle->weight_matrix[i][j] << " ";
+ //}
+ //std::cout << std::endl;
+ //}
+ std::cout << "Prices: " << std::endl;
+ for(const auto price : oracle->get_prices()) {
+ std::cout << price << std::endl;
+ }
+ std::cout << "**********************" << std::endl;
+#endif
+}
+
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::sanity_check()
+{
+#ifdef DEBUG_AUCTION
+ if (bidders_to_items.size() != num_bidders) {
+ std::cerr << "Wrong size of bidders_to_items, must be " << num_bidders << ", is " << bidders_to_items.size() << std::endl;
+ throw std::runtime_error("Wrong size of bidders_to_items");
+ }
+
+ if (items_to_bidders.size() != num_bidders) {
+ std::cerr << "Wrong size of items_to_bidders, must be " << num_bidders << ", is " << items_to_bidders.size() << std::endl;
+ throw std::runtime_error("Wrong size of items_to_bidders");
+ }
+
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ assert( bidders_to_items[bidder_idx] == k_invalid_index or ( bidders_to_items[bidder_idx] < static_cast<IdxType>(num_items) and bidders_to_items[bidder_idx] >= 0));
+
+ if ( bidders_to_items[bidder_idx] != k_invalid_index) {
+
+ if ( std::count(bidders_to_items.begin(),
+ bidders_to_items.end(),
+ bidders_to_items[bidder_idx]) > 1 ) {
+ std::cerr << "Item " << bidders_to_items[bidder_idx];
+ std::cerr << " appears in bidders_to_items more than once" << std::endl;
+ throw std::runtime_error("Duplicate in bidders_to_items");
+ }
+
+ if (items_to_bidders.at(bidders_to_items[bidder_idx]) != static_cast<int>(bidder_idx)) {
+ std::cerr << "Inconsitency: bidder_idx = " << bidder_idx;
+ std::cerr << ", item_idx in bidders_to_items = ";
+ std::cerr << bidders_to_items[bidder_idx];
+ std::cerr << ", bidder_idx in items_to_bidders = ";
+ std::cerr << items_to_bidders[bidders_to_items[bidder_idx]] << std::endl;
+ throw std::runtime_error("inconsistent mapping");
+ }
+ }
+ }
+
+ for(size_t item_idx = 0; item_idx < num_diag_items; ++item_idx) {
+ auto owner = items_to_bidders.at(item_idx);
+ if ( owner == k_invalid_index) {
+ assert((oracle->diag_unassigned_slice_.count(item_idx) == 1 and
+ oracle->diag_items_heap__iters_[item_idx] == oracle->diag_items_heap_.end() and
+ oracle->all_items_heap__iters_[item_idx] == oracle->all_items_heap_.end())
+ or
+ (oracle->diag_unassigned_slice_.count(item_idx) == 0 and
+ oracle->diag_items_heap__iters_[item_idx] != oracle->diag_items_heap_.end() and
+ oracle->all_items_heap__iters_[item_idx] != oracle->all_items_heap_.end()));
+ assert(oracle->diag_assigned_to_diag_slice_.count(item_idx) == 0);
+ } else {
+ if (is_bidder_diagonal(owner)) {
+ assert(oracle->diag_unassigned_slice_.count(item_idx) == 0);
+ assert(oracle->diag_assigned_to_diag_slice_.count(item_idx) == 1);
+ assert(oracle->diag_items_heap__iters_[item_idx] == oracle->diag_items_heap_.end());
+ assert(oracle->all_items_heap__iters_[item_idx] == oracle->all_items_heap_.end());
+ } else {
+ assert(oracle->diag_unassigned_slice_.count(item_idx) == 0);
+ assert(oracle->diag_assigned_to_diag_slice_.count(item_idx) == 0);
+ assert(oracle->diag_items_heap__iters_[item_idx] != oracle->diag_items_heap_.end());
+ assert(oracle->all_items_heap__iters_[item_idx] != oracle->all_items_heap_.end());
+ }
+ }
+ }
+
+ for(IdxType item_idx = 0; item_idx < static_cast<IdxType>(num_bidders); ++item_idx) {
+ assert( items_to_bidders[item_idx] == k_invalid_index or ( items_to_bidders[item_idx] < static_cast<IdxType>(num_items) and items_to_bidders[item_idx] >= 0));
+ if ( items_to_bidders.at(item_idx) != k_invalid_index) {
+
+ // check for uniqueness
+ if ( std::count(items_to_bidders.begin(),
+ items_to_bidders.end(),
+ items_to_bidders[item_idx]) > 1 ) {
+ std::cerr << "Bidder " << items_to_bidders[item_idx];
+ std::cerr << " appears in items_to_bidders more than once" << std::endl;
+ throw std::runtime_error("Duplicate in items_to_bidders");
+ }
+ // check for consistency
+ if (bidders_to_items.at(items_to_bidders.at(item_idx)) != static_cast<int>(item_idx)) {
+ std::cerr << "Inconsitency: item_idx = " << item_idx;
+ std::cerr << ", bidder_idx in items_to_bidders = ";
+ std::cerr << items_to_bidders[item_idx];
+ std::cerr << ", item_idx in bidders_to_items= ";
+ std::cerr << bidders_to_items[items_to_bidders[item_idx]] << std::endl;
+ throw std::runtime_error("inconsistent mapping");
+ }
+ }
+ }
+
+ oracle->sanity_check();
+#endif
+}
+
+template<class R, class AO>
+void AuctionRunnerGaussSeidelSingleDiag<R, AO>::print_matching()
+{
+#ifdef DEBUG_AUCTION
+ sanity_check();
+ for(size_t bIdx = 0; bIdx < bidders_to_items.size(); ++bIdx) {
+ if (bidders_to_items[bIdx] != k_invalid_index) {
+ auto pA = bidders[bIdx];
+ auto pB = items[bidders_to_items[bIdx]];
+ std::cout << pA << " <-> " << pB << "+" << pow(dist_lp(pA, pB, internal_p), wasserstein_power) << std::endl;
+ } else {
+ assert(false);
+ }
+ }
+#endif
+}
+
+} // ws
+} // hera
diff --git a/wasserstein/include/auction_runner_jac.h b/wasserstein/include/auction_runner_jac.h
new file mode 100644
index 0000000..252ca32
--- /dev/null
+++ b/wasserstein/include/auction_runner_jac.h
@@ -0,0 +1,230 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef HERA_AUCTION_RUNNER_JAC_H
+#define HERA_AUCTION_RUNNER_JAC_H
+
+#ifdef WASSERSTEIN_PURE_GEOM
+#undef LOG_AUCTION
+#undef ORDERED_BY_PERSISTENCE
+#endif
+
+//#define ORDERED_BY_PERSISTENCE
+
+#include <unordered_set>
+
+#include "auction_oracle.h"
+
+namespace hera {
+namespace ws {
+
+// the two parameters that you can tweak in auction algorithm are:
+// 1. epsilon_common_ratio
+// 2. max_num_phases
+
+template<class RealType_ = double, class AuctionOracle_ = AuctionOracleKDTreeRestricted<RealType_>, class PointContainer_ = std::vector<DiagramPoint<RealType_>> > // alternatively: AuctionOracleLazyHeap --- TODO
+class AuctionRunnerJac {
+public:
+
+ using Real = RealType_;
+ using AuctionOracle = AuctionOracle_;
+ using DgmPoint = typename AuctionOracle::DiagramPointR;
+ using IdxValPairR = IdxValPair<Real>;
+ using PointContainer = PointContainer_;
+
+ const Real k_lowest_bid_value = -1; // all bid values must be positive
+
+
+ AuctionRunnerJac(const PointContainer& A,
+ const PointContainer& B,
+ const AuctionParams<Real>& params,
+ const std::string& _log_filename_prefix = "");
+
+ void set_epsilon(Real new_val);
+ Real get_epsilon() const { return epsilon; }
+ void run_auction();
+ template<class Range>
+ void run_bidding_step(const Range& r);
+ bool is_done() const;
+ void decrease_epsilon();
+ Real get_wasserstein_distance();
+ Real get_wasserstein_cost();
+ Real get_relative_error(const bool debug_output = false) const;
+//private:
+ // private data
+ PointContainer bidders;
+ PointContainer items;
+ const size_t num_bidders;
+ const size_t num_items;
+ std::vector<IdxType> items_to_bidders;
+ std::vector<IdxType> bidders_to_items;
+ Real wasserstein_power;
+ Real epsilon;
+ Real delta;
+ Real internal_p;
+ Real initial_epsilon;
+ const Real epsilon_common_ratio; // next epsilon = current epsilon / epsilon_common_ratio
+ const int max_num_phases; // maximal number of phases of epsilon-scaling
+ Real weight_adj_const;
+ Real wasserstein_cost;
+ std::vector<IdxValPairR> bid_table;
+ // to get the 2 best items
+ AuctionOracle oracle;
+ std::unordered_set<size_t> unassigned_bidders;
+ std::unordered_set<size_t> items_with_bids;
+ // to imitate Gauss-Seidel
+ const size_t max_bids_per_round;
+ Real partial_cost { 0.0 };
+ bool is_distance_computed { false };
+ int num_rounds { 0 };
+ int num_phase { 0 };
+ int dimension;
+
+ size_t unassigned_threshold; // for experiments
+
+#ifndef WASSERSTEIN_PURE_GEOM
+ std::unordered_set<size_t> unassigned_normal_bidders;
+ std::unordered_set<size_t> unassigned_diag_bidders;
+ bool diag_first {true};
+ size_t batch_size { 1000 };
+#ifdef ORDERED_BY_PERSISTENCE
+ // to process unassigned by persistence
+ using RealIdxPair = std::pair<Real, size_t>;
+ std::set<RealIdxPair, std::greater<RealIdxPair>> unassigned_normal_bidders_by_persistence;
+#endif
+
+ // to stop earlier in the last phase
+ const Real total_items_persistence;
+ const Real total_bidders_persistence;
+ Real unassigned_bidders_persistence;
+ Real unassigned_items_persistence;
+ Real gamma_threshold;
+
+
+ size_t num_diag_items { 0 };
+ size_t num_normal_items { 0 };
+ size_t num_diag_bidders { 0 };
+ size_t num_normal_bidders { 0 };
+
+
+#endif
+
+
+
+ // private methods
+ void assign_item_to_bidder(const IdxType bidder_idx, const IdxType items_idx);
+ void assign_to_best_bidder(const IdxType items_idx);
+ void clear_bid_table();
+ void run_auction_phases(const int max_num_phases, const Real _initial_epsilon);
+ void run_auction_phase();
+ void submit_bid(IdxType bidder_idx, const IdxValPairR& items_bid_value_pair);
+ void flush_assignment();
+ Real get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx) const;
+#ifndef WASSERSTEIN_PURE_GEOM
+ Real get_cost_to_diagonal(const DgmPoint& pt) const;
+ Real get_gamma() const;
+#endif
+ bool continue_auction_phase() const;
+
+ void add_unassigned_bidder(const size_t bidder_idx);
+ void remove_unassigned_bidder(const size_t bidder_idx);
+ void remove_unassigned_item(const size_t item_idx);
+
+#ifndef WASSERSTEIN_PURE_GEOM
+ bool is_item_diagonal(const size_t item_idx) const { return item_idx < num_diag_items; }
+ bool is_item_normal(const size_t item_idx) const { return not is_item_diagonal(item_idx); }
+ bool is_bidder_diagonal(const size_t bidder_idx) const { return bidder_idx >= num_normal_bidders; }
+ bool is_bidder_normal(const size_t bidder_idx) const { return not is_bidder_diagonal(bidder_idx); }
+#endif
+
+
+
+ // for debug only
+ void sanity_check();
+ void print_debug();
+ void print_matching();
+
+ std::string log_filename_prefix;
+ const Real k_max_relative_error = 2.0; // if relative error cannot be estimated or is too large, use this value
+
+#ifdef LOG_AUCTION
+
+ size_t parallel_threshold { 5000 };
+ bool is_step_parallel {false};
+ std::unordered_set<size_t> unassigned_items;
+ std::unordered_set<size_t> unassigned_normal_items;
+ std::unordered_set<size_t> unassigned_diag_items;
+ std::unordered_set<size_t> never_assigned_bidders;
+ size_t all_assigned_round { 0 };
+ size_t all_assigned_round_found { false };
+
+ int num_rounds_non_cumulative { 0 }; // set to 0 in the beginning of each phase
+ int num_diag_assignments { 0 };
+ int num_diag_assignments_non_cumulative { 0 };
+ int num_diag_bids_submitted { 0 };
+ int num_diag_stole_from_diag { 0 };
+ int num_normal_assignments { 0 };
+ int num_normal_assignments_non_cumulative { 0 };
+ int num_normal_bids_submitted { 0 };
+
+ std::vector<std::vector<size_t>> price_change_cnt_vec;
+
+
+ const char* plot_logger_name = "plot_logger";
+ const char* price_state_logger_name = "price_stat_logger";
+ std::string plot_logger_file_name;
+ std::string price_stat_logger_file_name;
+ std::shared_ptr<spdlog::logger> plot_logger;
+ std::shared_ptr<spdlog::logger> price_stat_logger;
+ std::shared_ptr<spdlog::logger> console_logger;
+
+
+ int num_parallel_bids { 0 };
+ int num_total_bids { 0 };
+
+ int num_parallel_diag_bids { 0 };
+ int num_total_diag_bids { 0 };
+
+ int num_parallel_normal_bids { 0 };
+ int num_total_normal_bids { 0 };
+
+ int num_parallel_assignments { 0 };
+ int num_total_assignments { 0 };
+#endif
+
+}; // AuctionRunnerJac
+
+
+} // ws
+} // hera
+
+#include "auction_runner_jac.hpp"
+
+#undef ORDERED_BY_PERSISTENCE
+
+#endif
diff --git a/wasserstein/include/auction_runner_jac.hpp b/wasserstein/include/auction_runner_jac.hpp
new file mode 100644
index 0000000..e623f4a
--- /dev/null
+++ b/wasserstein/include/auction_runner_jac.hpp
@@ -0,0 +1,879 @@
+/*
+
+Copyright (c) 2016, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef AUCTION_RUNNER_JAC_HPP
+#define AUCTION_RUNNER_JAC_HPP
+
+#include <assert.h>
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+#include "def_debug_ws.h"
+#include "auction_runner_jac.h"
+
+
+#ifdef FOR_R_TDA
+#include "Rcpp.h"
+#undef DEBUG_AUCTION
+#endif
+
+namespace hera {
+namespace ws {
+
+
+// *****************************
+// AuctionRunnerJac
+// *****************************
+
+ template<class R, class AO, class PC>
+ AuctionRunnerJac<R, AO, PC>::AuctionRunnerJac(const PointContainer& A,
+ const PointContainer& B,
+ const AuctionParams<Real>& params,
+ const std::string &_log_filename_prefix
+ ) :
+ bidders(A),
+ items(B),
+ num_bidders(A.size()),
+ num_items(A.size()),
+ items_to_bidders(A.size(), k_invalid_index),
+ bidders_to_items(A.size(), k_invalid_index),
+ wasserstein_power(params.wasserstein_power),
+ delta(params.delta),
+ internal_p(params.internal_p),
+ initial_epsilon(params.initial_epsilon),
+ epsilon_common_ratio(params.epsilon_common_ratio == 0.0 ? 5.0 : params.epsilon_common_ratio),
+ max_num_phases(params.max_num_phases),
+ bid_table(A.size(), std::make_pair(k_invalid_index, k_lowest_bid_value)),
+ oracle(bidders, items, params),
+ max_bids_per_round(params.max_bids_per_round),
+ dimension(params.dim),
+#ifndef WASSERSTEIN_PURE_GEOM
+ total_items_persistence(std::accumulate(items.begin(),
+ items.end(),
+ R(0.0),
+ [params](const Real &ps, const DgmPoint &item) {
+ return ps + std::pow(item.persistence_lp(params.internal_p), params.wasserstein_power);
+ }
+ )),
+ total_bidders_persistence(std::accumulate(bidders.begin(),
+ bidders.end(),
+ R(0.0),
+ [params](const Real &ps, const DgmPoint &bidder) {
+ return ps + std::pow(bidder.persistence_lp(params.internal_p), params.wasserstein_power);
+ }
+ )),
+ unassigned_bidders_persistence(total_bidders_persistence),
+ unassigned_items_persistence(total_items_persistence),
+ gamma_threshold(params.gamma_threshold),
+#endif
+ log_filename_prefix(_log_filename_prefix)
+ {
+ assert(A.size() == B.size());
+
+#ifndef WASSERSTEIN_PURE_GEOM
+ for (const auto &p : bidders) {
+ if (p.is_normal()) {
+ num_normal_bidders++;
+ num_diag_items++;
+ } else {
+ num_normal_items++;
+ num_diag_bidders++;
+ }
+ }
+#endif
+ // for experiments
+ unassigned_threshold = 100;
+
+#ifdef ORDERED_BY_PERSISTENCE
+ batch_size = 1000;
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if (is_bidder_normal(bidder_idx)) {
+ unassigned_normal_bidders_by_persistence.insert(
+ std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx));
+ }
+ }
+#endif
+
+#ifdef LOG_AUCTION
+ parallel_threshold = 16;
+ console_logger = spdlog::get("console");
+ if (not console_logger) {
+ console_logger = spdlog::stdout_logger_st("console");
+ }
+ console_logger->set_pattern("[%H:%M:%S.%e] %v");
+#ifdef ORDERED_BY_PERSISTENCE
+ if (max_bids_per_round == 1) {
+ console_logger->info("Gauss-Seidel imitated by Jacobi runner, q = {0}, max_bids_per_round = {1}, batch_size = {4}, gamma_threshold = {2}, diag_first = {3} ORDERED_BY_PERSISTENCE",
+ wasserstein_power,
+ max_bids_per_round,
+ gamma_threshold,
+ diag_first,
+ batch_size);
+ } else {
+ console_logger->info("Jacobi runner, q = {0}, max_bids_per_round = {1}, batch_size = {4}, gamma_threshold = {2}, diag_first = {3} ORDERED_BY_PERSISTENCE",
+ wasserstein_power,
+ max_bids_per_round,
+ gamma_threshold,
+ diag_first,
+ batch_size);
+ }
+
+#else
+ if (max_bids_per_round == 1) {
+ console_logger->info(
+ "Gauss-Seidel imitated by Jacobi runner, q = {0}, max_bids_per_round = {1}, batch_size = {4}, gamma_threshold = {2}, diag_first = {3}",
+ wasserstein_power,
+ max_bids_per_round,
+ gamma_threshold,
+ diag_first,
+ batch_size);
+ } else {
+ console_logger->info(
+ "Jacobi runner, q = {0}, max_bids_per_round = {1}, batch_size = {4}, gamma_threshold = {2}, diag_first = {3}",
+ wasserstein_power,
+ max_bids_per_round,
+ gamma_threshold,
+ diag_first,
+ batch_size);
+ }
+#endif
+
+ plot_logger_file_name = log_filename_prefix + "_plot.txt";
+ plot_logger = spdlog::get(plot_logger_name);
+ if (not plot_logger) {
+ plot_logger = spdlog::basic_logger_st(plot_logger_name, plot_logger_file_name);
+ }
+ plot_logger->info("New plot starts here, diagram size = {0}, gamma_threshold = {1}, epsilon_common_ratio = {2}",
+ bidders.size(),
+ gamma_threshold,
+ epsilon_common_ratio);
+ plot_logger->set_pattern("%v");
+
+ price_stat_logger_file_name = log_filename_prefix + "_price_change_stat";
+ price_stat_logger = spdlog::get(price_state_logger_name);
+ if (not price_stat_logger) {
+ price_stat_logger = spdlog::basic_logger_st(price_state_logger_name,
+ price_stat_logger_file_name);
+ }
+ price_stat_logger->info(
+ "New price statistics starts here, diagram size = {0}, gamma_threshold = {1}, epsilon_common_ratio = {2}",
+ bidders.size(),
+ gamma_threshold,
+ epsilon_common_ratio);
+ price_stat_logger->set_pattern("%v");
+#endif
+ }
+
+#ifndef WASSERSTEIN_PURE_GEOM
+ template<class R, class AO, class PC>
+ typename AuctionRunnerJac<R, AO, PC>::Real
+ AuctionRunnerJac<R, AO, PC>::get_cost_to_diagonal(const DgmPoint &pt) const {
+ return std::pow(pt.persistence_lp(internal_p), wasserstein_power);
+ }
+
+ template<class R, class AO, class PC>
+ typename AuctionRunnerJac<R, AO, PC>::Real
+ AuctionRunnerJac<R, AO, PC>::get_gamma() const {
+ return std::pow(std::fabs(unassigned_items_persistence + unassigned_bidders_persistence),
+ 1.0 / wasserstein_power);
+ }
+#endif
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::assign_item_to_bidder(IdxType item_idx, IdxType bidder_idx)
+ {
+ //sanity_check();
+ // only unassigned bidders submit bids
+ assert(bidders_to_items[bidder_idx] == k_invalid_index);
+
+ IdxType old_item_owner = items_to_bidders[item_idx];
+
+ // set new owner
+ bidders_to_items[bidder_idx] = item_idx;
+ items_to_bidders[item_idx] = bidder_idx;
+
+ // remove bidder and item from the sets of unassigned bidders/items
+ remove_unassigned_bidder(bidder_idx);
+
+ if (k_invalid_index != old_item_owner) {
+ // old owner of item becomes unassigned
+ bidders_to_items[old_item_owner] = k_invalid_index;
+ add_unassigned_bidder(old_item_owner);
+ // existing edge was removed, decrease partial_cost
+ partial_cost -= get_item_bidder_cost(item_idx, old_item_owner);
+ } else {
+ // item was unassigned before
+ remove_unassigned_item(item_idx);
+ }
+
+ // new edge was added to matching, increase partial cost
+ partial_cost += get_item_bidder_cost(item_idx, bidder_idx);
+
+#ifdef LOG_AUCTION
+ if (is_item_diagonal(item_idx)) {
+ num_diag_assignments++;
+ num_diag_assignments_non_cumulative++;
+ } else {
+ num_normal_assignments++;
+ num_normal_assignments_non_cumulative++;
+ }
+
+ if (k_invalid_index != old_item_owner) {
+ if (is_bidder_diagonal(bidder_idx) and is_bidder_diagonal(old_item_owner)) {
+ num_diag_stole_from_diag++;
+ }
+ }
+#endif
+
+ //sanity_check();
+ }
+
+ template<class R, class AO, class PC>
+ typename AuctionRunnerJac<R, AO, PC>::Real
+ AuctionRunnerJac<R, AO, PC>::get_item_bidder_cost(const size_t item_idx, const size_t bidder_idx) const
+ {
+ return std::pow(dist_lp(bidders[bidder_idx], items[item_idx], internal_p, dimension),
+ wasserstein_power);
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::assign_to_best_bidder(IdxType item_idx) {
+ assert(item_idx >= 0 and item_idx < static_cast<IdxType>(num_items));
+ assert(bid_table[item_idx].first != k_invalid_index);
+ IdxValPairR best_bid{bid_table[item_idx]};
+ assign_item_to_bidder(item_idx, best_bid.first);
+ oracle.set_price(item_idx, best_bid.second);
+#ifdef LOG_AUCTION
+
+ if (is_step_parallel) {
+ num_parallel_assignments++;
+ }
+ num_total_assignments++;
+
+ price_change_cnt_vec.back()[item_idx]++;
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::clear_bid_table() {
+ auto iter = items_with_bids.begin();
+ while (iter != items_with_bids.end()) {
+ auto item_with_bid_idx = *iter;
+ bid_table[item_with_bid_idx].first = k_invalid_index;
+ bid_table[item_with_bid_idx].second = k_lowest_bid_value;
+ iter = items_with_bids.erase(iter);
+ }
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::submit_bid(IdxType bidder_idx, const IdxValPairR &bid) {
+ IdxType item_idx = bid.first;
+ Real bid_value = bid.second;
+ assert(item_idx >= 0);
+ if (bid_table[item_idx].second < bid_value) {
+ bid_table[item_idx].first = bidder_idx;
+ bid_table[item_idx].second = bid_value;
+ }
+ items_with_bids.insert(item_idx);
+
+#ifdef LOG_AUCTION
+
+ num_total_bids++;
+
+
+ if (is_bidder_diagonal(bidder_idx)) {
+ num_diag_bids_submitted++;
+ } else {
+ num_normal_bids_submitted++;
+ }
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::print_debug() {
+#ifdef DEBUG_AUCTION
+ sanity_check();
+ std::cout << "**********************" << std::endl;
+ std::cout << "Current assignment:" << std::endl;
+ for(size_t idx = 0; idx < bidders_to_items.size(); ++idx) {
+ std::cout << idx << " <--> " << bidders_to_items[idx] << std::endl;
+ }
+ std::cout << "Weights: " << std::endl;
+ //for(size_t i = 0; i < num_bidders; ++i) {
+ //for(size_t j = 0; j < num_items; ++j) {
+ //std::cout << oracle.weight_matrix[i][j] << " ";
+ //}
+ //std::cout << std::endl;
+ //}
+ std::cout << "Prices: " << std::endl;
+ for(const auto price : oracle.get_prices()) {
+ std::cout << price << std::endl;
+ }
+ //std::cout << "Value matrix: " << std::endl;
+ //for(size_t i = 0; i < num_bidders; ++i) {
+ //for(size_t j = 0; j < num_items; ++j) {
+ //std::cout << oracle.weight_matrix[i][j] - oracle.prices[j] << " ";
+ //}
+ //std::cout << std::endl;
+ //}
+ std::cout << "**********************" << std::endl;
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ typename AuctionRunnerJac<R, AO, PC>::Real
+ AuctionRunnerJac<R, AO, PC>::get_relative_error(const bool debug_output) const
+ {
+ if (partial_cost == 0.0 and unassigned_bidders.empty())
+ return 0.0;
+ Real result;
+#ifndef WASSERSTEIN_PURE_GEOM
+ Real gamma = get_gamma();
+#else
+ Real gamma = 0.0;
+#endif
+ // cost minus n epsilon
+ Real reduced_cost = partial_cost - num_bidders * get_epsilon();
+ if (reduced_cost < 0) {
+#ifdef LOG_AUCTION
+ if (debug_output) {
+ console_logger->info("Epsilon too large, reduced_cost = {0}, gamma = {1}", reduced_cost, gamma);
+ }
+#endif
+ result = k_max_relative_error;
+ } else {
+ Real denominator = std::pow(reduced_cost, 1.0 / wasserstein_power) - gamma;
+ if (denominator <= 0) {
+#ifdef LOG_AUCTION
+ if (debug_output) {
+ console_logger->info("Epsilon too large, reduced_cost = {0}, denominator = {1}, gamma = {2}",
+ reduced_cost, denominator, gamma);
+ }
+#endif
+ result = k_max_relative_error;
+ } else {
+ Real numerator = 2 * gamma +
+ std::pow(partial_cost, 1.0 / wasserstein_power) -
+ std::pow(reduced_cost, 1.0 / wasserstein_power);
+
+ result = numerator / denominator;
+#ifdef LOG_AUCTION
+ if (debug_output) {
+ console_logger->info(
+ "Reduced_cost = {0}, denominator = {1}, numerator {2}, error = {3}, gamma = {4}",
+ reduced_cost,
+ denominator,
+ numerator,
+ result,
+ gamma);
+ }
+#endif
+ }
+ }
+ return result;
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::flush_assignment() {
+ for (auto &b2i : bidders_to_items) {
+ b2i = k_invalid_index;
+ }
+ for (auto &i2b : items_to_bidders) {
+ i2b = k_invalid_index;
+ }
+
+ // all bidders and items become unassigned
+ for (size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ unassigned_bidders.insert(bidder_idx);
+ }
+
+#ifdef ORDERED_BY_PERSISTENCE
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if (is_bidder_normal(bidder_idx)) {
+ unassigned_normal_bidders_by_persistence.insert(
+ std::make_pair(bidders[bidder_idx].persistence_lp(1.0), bidder_idx));
+ }
+ }
+#endif
+ oracle.adjust_prices();
+
+ partial_cost = 0.0;
+
+
+#ifndef WASSERSTEIN_PURE_GEOM
+ for (size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if (is_bidder_normal(bidder_idx)) {
+ unassigned_normal_bidders.insert(bidder_idx);
+ } else {
+ unassigned_diag_bidders.insert(bidder_idx);
+ }
+ }
+
+ unassigned_bidders_persistence = total_bidders_persistence;
+ unassigned_items_persistence = total_items_persistence;
+
+#ifdef LOG_AUCTION
+
+ price_change_cnt_vec.push_back(std::vector<size_t>(num_items, 0));
+
+ never_assigned_bidders = unassigned_bidders;
+
+ for (size_t item_idx = 0; item_idx < items.size(); ++item_idx) {
+ unassigned_items.insert(item_idx);
+ if (is_item_normal(item_idx)) {
+ unassigned_normal_items.insert(item_idx);
+ } else {
+ unassigned_diag_items.insert(item_idx);
+ }
+ }
+
+ num_diag_bids_submitted = 0;
+ num_normal_bids_submitted = 0;
+ num_diag_assignments = 0;
+ num_normal_assignments = 0;
+
+ all_assigned_round = 0;
+ all_assigned_round_found = false;
+ num_rounds_non_cumulative = 0;
+#endif
+#endif
+
+ } // flush_assignment
+
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::set_epsilon(Real new_val) {
+ assert(new_val > 0.0);
+ epsilon = new_val;
+ oracle.set_epsilon(new_val);
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::run_auction_phases(const int max_num_phases, const Real _initial_epsilon) {
+ set_epsilon(_initial_epsilon);
+ assert(oracle.get_epsilon() > 0);
+ for (int phase_num = 0; phase_num < max_num_phases; ++phase_num) {
+ flush_assignment();
+ run_auction_phase();
+
+#ifdef LOG_AUCTION
+ console_logger->info(
+ "Phase {0} done, current_result = {1}, eps = {2}, error = {7}, num_rounds = {3}, num_assignments = {4}, num_bids_submitted = {5}, # unassigned = {6}",
+ num_phase,
+ partial_cost,
+ get_epsilon(),
+ format_int<>(num_rounds),
+ format_int<>(num_normal_assignments + num_diag_assignments),
+ format_int<>(num_normal_bids_submitted + num_diag_bids_submitted),
+ unassigned_bidders.size(),
+ get_relative_error(num_phase == 1)
+ );
+
+// console_logger->info("num_rounds (non-cumulative)= {0}, num_diag_assignments = {1}, num_normal_assignments = {2}, num_diag_bids_submitted = {3}, num_normal_bids_submitted = {4}",
+// format_int<>(num_rounds_non_cumulative),
+// format_int<>(num_diag_assignments),
+// format_int<>(num_normal_assignments),
+// format_int<>(num_diag_bids_submitted),
+// format_int<>(num_normal_bids_submitted)
+// );
+
+ console_logger->info(
+ "num_parallel_bids / num_total_bids = {0} / {1} = {2}, num_parallel_assignments / num_total_aassignments = {3} / {4} = {5}",
+ format_int<>(num_parallel_bids),
+ format_int<>(num_total_bids),
+ static_cast<double>(num_parallel_bids) / static_cast<double>(num_total_bids),
+ format_int<>(num_parallel_assignments),
+ format_int<>(num_total_assignments),
+ static_cast<double>(num_parallel_assignments) / static_cast<double>(num_total_assignments)
+ );
+
+ console_logger->info(
+ "num_parallel_diag_bids / num_total_diag_bids = {0} / {1} = {2}, num_parallel_normal_bids / num_total_normal_bids = {3} / {4} = {5}",
+ format_int<>(num_parallel_diag_bids),
+ format_int<>(num_total_diag_bids),
+ static_cast<double>(num_parallel_diag_bids) / static_cast<double>(num_total_diag_bids),
+ format_int<>(num_parallel_normal_bids),
+ format_int<>(num_total_normal_bids),
+ static_cast<double>(num_parallel_normal_bids) / static_cast<double>(num_total_normal_bids)
+ );
+
+// console_logger->info("num_rounds before all biders assigned = {0}, num_rounds (non-cumulative)= {1}, fraction = {2}",
+// format_int<>(all_assigned_round),
+// format_int<>(num_rounds_non_cumulative),
+// static_cast<double>(all_assigned_round) / static_cast<double>(num_rounds_non_cumulative)
+// );
+
+ for (size_t item_idx = 0; item_idx < num_items; ++item_idx) {
+ price_stat_logger->info("{0} {1} {2} {3} {4}",
+ phase_num,
+ item_idx,
+ items[item_idx][0],
+ items[item_idx][1],
+ price_change_cnt_vec.back()[item_idx]
+ );
+ }
+#endif
+
+
+ if (is_done())
+ break;
+ else
+ decrease_epsilon();
+
+ }
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::decrease_epsilon() {
+ set_epsilon(get_epsilon() / epsilon_common_ratio);
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::run_auction()
+ {
+ if (num_bidders == 1) {
+ assign_item_to_bidder(0, 0);
+ wasserstein_cost = get_item_bidder_cost(0,0);
+ is_distance_computed = true;
+ return;
+ }
+ R init_eps = (initial_epsilon > 0.0) ? initial_epsilon : oracle.max_val_ / 4.0;
+ run_auction_phases(max_num_phases, init_eps);
+ is_distance_computed = true;
+ wasserstein_cost = partial_cost;
+ if (not is_done()) {
+#ifndef FOR_R_TDA
+ std::cerr << "Maximum iteration number exceeded, exiting. Current result is: ";
+ std::cerr << get_wasserstein_distance() << std::endl;
+#endif
+ throw std::runtime_error("Maximum iteration number exceeded");
+ }
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::add_unassigned_bidder(const size_t bidder_idx)
+ {
+ unassigned_bidders.insert(bidder_idx);
+
+#ifndef WASSERSTEIN_PURE_GEOM
+ const auto &bidder = bidders[bidder_idx];
+ unassigned_bidders_persistence += get_cost_to_diagonal(bidder);
+
+ if (is_bidder_diagonal(bidder_idx)) {
+ unassigned_diag_bidders.insert(bidder_idx);
+ } else {
+ unassigned_normal_bidders.insert(bidder_idx);
+ }
+#ifdef ORDERED_BY_PERSISTENCE
+ if (is_bidder_normal(bidder_idx)) {
+ unassigned_normal_bidders_by_persistence.insert(std::make_pair(bidder.persistence_lp(1.0), bidder_idx));
+ }
+#endif
+
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::remove_unassigned_bidder(const size_t bidder_idx)
+ {
+ unassigned_bidders.erase(bidder_idx);
+#ifndef WASSERSTEIN_PURE_GEOM
+ const auto &bidder = bidders[bidder_idx];
+ unassigned_bidders_persistence -= get_cost_to_diagonal(bidder);
+
+#ifdef ORDERED_BY_PERSISTENCE
+ if (is_bidder_normal(bidder_idx)) {
+ unassigned_normal_bidders_by_persistence.erase(std::make_pair(bidder.persistence_lp(1.0), bidder_idx));
+ }
+#endif
+
+ if (is_bidder_diagonal(bidder_idx)) {
+ unassigned_diag_bidders.erase(bidder_idx);
+ } else {
+ unassigned_normal_bidders.erase(bidder_idx);
+ }
+
+
+#ifdef LOG_AUCTION
+ never_assigned_bidders.erase(bidder_idx);
+ if (never_assigned_bidders.empty() and not all_assigned_round_found) {
+ all_assigned_round = num_rounds_non_cumulative;
+ all_assigned_round_found = true;
+ }
+#endif
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::remove_unassigned_item(const size_t item_idx) {
+#ifndef WASSERSTEIN_PURE_GEOM
+ unassigned_items_persistence -= get_cost_to_diagonal(items[item_idx]);
+
+#ifdef LOG_AUCTION
+ unassigned_items.erase(item_idx);
+
+ if (is_item_normal(item_idx)) {
+ unassigned_normal_items.erase(item_idx);
+ } else {
+ unassigned_diag_items.erase(item_idx);
+ }
+#endif
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ template<class Range>
+ void AuctionRunnerJac<R, AO, PC>::run_bidding_step(const Range &active_bidders)
+ {
+#ifdef LOG_AUCTION
+ is_step_parallel = false;
+ size_t diag_bids_submitted = 0;
+ size_t normal_bids_submitted = 0;
+#endif
+
+ clear_bid_table();
+ size_t bids_submitted = 0;
+ for (const auto bidder_idx : active_bidders) {
+
+ ++bids_submitted;
+
+ submit_bid(bidder_idx, oracle.get_optimal_bid(bidder_idx));
+
+#ifdef LOG_AUCTION
+ if (is_bidder_diagonal(bidder_idx)) {
+ diag_bids_submitted++;
+ } else {
+ normal_bids_submitted++;
+ }
+
+ if (bids_submitted >= parallel_threshold) {
+ is_step_parallel = true;
+ }
+
+ if (bids_submitted >= max_bids_per_round) {
+ break;
+ }
+ if (diag_first and not unassigned_diag_bidders.empty() and
+ diag_bids_submitted >= oracle.get_heap_top_size()) {
+ continue;
+ }
+#endif
+ }
+
+#ifdef LOG_AUCTION
+ num_total_diag_bids += diag_bids_submitted;
+ num_total_normal_bids += normal_bids_submitted;
+ if (is_step_parallel) {
+ num_parallel_bids += bids_submitted;
+ num_parallel_diag_bids += diag_bids_submitted;
+ num_parallel_normal_bids += normal_bids_submitted;
+ }
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ bool AuctionRunnerJac<R, AO, PC>::is_done() const
+ {
+ return get_relative_error() <= delta;
+ }
+
+ template<class R, class AO, class PC>
+ bool AuctionRunnerJac<R, AO, PC>::continue_auction_phase() const
+ {
+#ifdef WASSERSTEIN_PURE_GEOM
+ return not unassigned_bidders.empty();
+#else
+ return not unassigned_bidders.empty() and not is_done();
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::run_auction_phase()
+ {
+ num_phase++;
+ //console_logger->debug("Entered run_auction_phase");
+
+ do {
+ num_rounds++;
+#ifdef LOG_AUCTION
+ num_diag_stole_from_diag = 0;
+ num_normal_assignments_non_cumulative = 0;
+ num_diag_assignments_non_cumulative = 0;
+ num_rounds_non_cumulative++;
+#endif
+
+ // bidding
+#ifdef ORDERED_BY_PERSISTENCE
+ if (not unassigned_diag_bidders.empty()) {
+ run_bidding_step(unassigned_diag_bidders);
+ } else {
+ std::vector<size_t> active_bidders;
+ active_bidders.reserve(batch_size);
+ for (auto iter = unassigned_normal_bidders_by_persistence.begin(); iter != unassigned_normal_bidders_by_persistence.end(); ++iter) {
+ active_bidders.push_back(iter->second);
+ if (active_bidders.size() >= batch_size) {
+ break;
+ }
+ }
+ run_bidding_step(active_bidders);
+ }
+#elif defined WASSERSTEIN_PURE_GEOM
+ run_bidding_step(unassigned_bidders);
+#else
+ if (diag_first and not unassigned_diag_bidders.empty()) {
+ run_bidding_step(unassigned_diag_bidders);
+ } else {
+ run_bidding_step(unassigned_bidders);
+ }
+#endif
+
+ // assignment
+ for (auto item_idx : items_with_bids) {
+ assign_to_best_bidder(item_idx);
+ }
+#ifdef LOG_AUCTION
+ plot_logger->info("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14}",
+ num_phase,
+ num_rounds,
+ unassigned_bidders.size(),
+ get_gamma(),
+ partial_cost,
+ oracle.get_epsilon(),
+ unassigned_normal_bidders.size(),
+ unassigned_diag_bidders.size(),
+ unassigned_normal_items.size(),
+ unassigned_diag_items.size(),
+ num_normal_assignments_non_cumulative,
+ num_diag_assignments_non_cumulative,
+ oracle.get_heap_top_size(),
+ get_relative_error(false),
+ num_diag_stole_from_diag
+ );
+#endif
+ //sanity_check();
+ } while (continue_auction_phase());
+ }
+
+ template<class R, class AO, class PC>
+ typename AuctionRunnerJac<R, AO, PC>::Real
+ AuctionRunnerJac<R, AO, PC>::get_wasserstein_distance()
+ {
+ assert(is_distance_computed);
+ return std::pow(wasserstein_cost, 1.0 / wasserstein_power);
+ }
+
+ template<class R, class AO, class PC>
+ typename AuctionRunnerJac<R, AO, PC>::Real
+ AuctionRunnerJac<R, AO, PC>::get_wasserstein_cost()
+ {
+ assert(is_distance_computed);
+ return wasserstein_cost;
+ }
+
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::sanity_check()
+ {
+#ifdef DEBUG_AUCTION
+ if (bidders_to_items.size() != num_bidders) {
+ std::cerr << "Wrong size of bidders_to_items, must be " << num_bidders << ", is " << bidders_to_items.size() << std::endl;
+ throw "Wrong size of bidders_to_items";
+ }
+
+ if (items_to_bidders.size() != num_bidders) {
+ std::cerr << "Wrong size of items_to_bidders, must be " << num_bidders << ", is " << items_to_bidders.size() << std::endl;
+ throw "Wrong size of items_to_bidders";
+ }
+
+ for(size_t bidder_idx = 0; bidder_idx < num_bidders; ++bidder_idx) {
+ if ( bidders_to_items[bidder_idx] >= 0) {
+
+ if ( std::count(bidders_to_items.begin(),
+ bidders_to_items.end(),
+ bidders_to_items[bidder_idx]) > 1 ) {
+ std::cerr << "Good " << bidders_to_items[bidder_idx];
+ std::cerr << " appears in bidders_to_items more than once" << std::endl;
+ throw "Duplicate in bidders_to_items";
+ }
+
+ if (items_to_bidders.at(bidders_to_items[bidder_idx]) != static_cast<int>(bidder_idx)) {
+ std::cerr << "Inconsitency: bidder_idx = " << bidder_idx;
+ std::cerr << ", item_idx in bidders_to_items = ";
+ std::cerr << bidders_to_items[bidder_idx];
+ std::cerr << ", bidder_idx in items_to_bidders = ";
+ std::cerr << items_to_bidders[bidders_to_items[bidder_idx]] << std::endl;
+ throw "inconsistent mapping";
+ }
+ }
+ }
+
+ for(IdxType item_idx = 0; item_idx < static_cast<IdxType>(num_bidders); ++item_idx) {
+ if ( items_to_bidders[item_idx] >= 0) {
+
+ // check for uniqueness
+ if ( std::count(items_to_bidders.begin(),
+ items_to_bidders.end(),
+ items_to_bidders[item_idx]) > 1 ) {
+ std::cerr << "Bidder " << items_to_bidders[item_idx];
+ std::cerr << " appears in items_to_bidders more than once" << std::endl;
+ throw "Duplicate in items_to_bidders";
+ }
+ // check for consistency
+ if (bidders_to_items.at(items_to_bidders[item_idx]) != static_cast<int>(item_idx)) {
+ std::cerr << "Inconsitency: item_idx = " << item_idx;
+ std::cerr << ", bidder_idx in items_to_bidders = ";
+ std::cerr << items_to_bidders[item_idx];
+ std::cerr << ", item_idx in bidders_to_items= ";
+ std::cerr << bidders_to_items[items_to_bidders[item_idx]] << std::endl;
+ throw "inconsistent mapping";
+ }
+ }
+ }
+#endif
+ }
+
+ template<class R, class AO, class PC>
+ void AuctionRunnerJac<R, AO, PC>::print_matching() {
+#ifdef DEBUG_AUCTION
+ sanity_check();
+ for(size_t bidder_idx = 0; bidder_idx < bidders_to_items.size(); ++bidder_idx) {
+ if (bidders_to_items[bidder_idx] >= 0) {
+ auto pA = bidders[bidder_idx];
+ auto pB = items[bidders_to_items[bidder_idx]];
+ std::cout << pA << " <-> " << pB << "+" << pow(dist_lp(pA, pB, internal_p, dimension), wasserstein_power) << std::endl;
+ } else {
+ assert(false);
+ }
+ }
+#endif
+ }
+
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/basic_defs_ws.h b/wasserstein/include/basic_defs_ws.h
new file mode 100644
index 0000000..bdcfd75
--- /dev/null
+++ b/wasserstein/include/basic_defs_ws.h
@@ -0,0 +1,321 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef BASIC_DEFS_WS_H
+#define BASIC_DEFS_WS_H
+
+#include <vector>
+#include <math.h>
+#include <cstddef>
+#include <unordered_map>
+#include <unordered_set>
+#include <string>
+#include <iomanip>
+#include <locale>
+#include <cassert>
+#include <limits>
+#include <ostream>
+#include <typeinfo>
+
+#ifdef _WIN32
+#include <ciso646>
+#endif
+
+#include "hera_infinity.h"
+#include "dnn/geometry/euclidean-dynamic.h"
+#include "def_debug_ws.h"
+
+#define MIN_VALID_ID 10
+
+namespace hera
+{
+
+//template<class Real = double>
+//inline bool is_infinity(const Real& x)
+//{
+// return x == Real(-1);
+//};
+//
+//template<class Real = double>
+//inline Real get_infinity()
+//{
+// return Real( -1 );
+//}
+
+template<class Real = double>
+inline bool is_p_valid_norm(const Real& p)
+{
+ return is_infinity<Real>(p) or p >= Real(1);
+}
+
+template<class Real = double>
+struct AuctionParams
+{
+ Real wasserstein_power { 1.0 };
+ Real delta { 0.01 }; // relative error
+ Real internal_p { get_infinity<Real>() };
+ Real initial_epsilon { 0.0 }; // 0.0 means maxVal / 4.0
+ Real epsilon_common_ratio { 5.0 };
+ Real gamma_threshold { 0.0 }; // for experiments, not in use now
+ int max_num_phases { std::numeric_limits<decltype(max_num_phases)>::max() };
+ int max_bids_per_round { 1 }; // imitate Gauss-Seidel is default behaviour
+ unsigned int dim { 2 }; // for pure geometric version only; ignored in persistence diagrams
+ Real final_relative_error; // out parameter - after auction terminates, contains the real relative error
+ bool tolerate_max_iter_exceeded { false }; // whether auction should throw an exception on max. iterations exceeded
+};
+
+namespace ws
+{
+
+ using IdxType = int;
+
+ constexpr size_t k_invalid_index = std::numeric_limits<IdxType>::max();
+
+ template<class Real = double>
+ using IdxValPair = std::pair<IdxType, Real>;
+
+ template<class R>
+ inline std::ostream& operator<<(std::ostream& output, const IdxValPair<R> p)
+ {
+ output << "(" << p.first << ", " << p.second << ")";
+ return output;
+ }
+
+ enum class OwnerType { k_none, k_normal, k_diagonal };
+
+ inline std::ostream& operator<<(std::ostream& s, const OwnerType t)
+ {
+ switch(t)
+ {
+ case OwnerType::k_none : s << "NONE"; break;
+ case OwnerType::k_normal: s << "NORMAL"; break;
+ case OwnerType::k_diagonal: s << "DIAGONAL"; break;
+ }
+ return s;
+ }
+
+ template<class Real = double>
+ struct Point {
+ Real x, y;
+ bool operator==(const Point& other) const;
+ bool operator!=(const Point& other) const;
+ Point(Real _x, Real _y) : x(_x), y(_y) {}
+ Point() : x(0.0), y(0.0) {}
+ };
+
+#ifndef FOR_R_TDA
+ template<class Real = double>
+ std::ostream& operator<<(std::ostream& output, const Point<Real> p);
+#endif
+
+ template <class T>
+ inline void hash_combine(std::size_t & seed, const T & v)
+ {
+ std::hash<T> hasher;
+ seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+
+ template<class Real_ = double>
+ struct DiagramPoint
+ {
+ using Real = Real_;
+ // data members
+ // Points above the diagonal have type NORMAL
+ // Projections onto the diagonal have type DIAG
+ // for DIAG points only x-coordinate is relevant
+ enum Type { NORMAL, DIAG};
+ Real x, y;
+ Type type;
+ // methods
+ DiagramPoint(Real xx, Real yy, Type ttype);
+ bool is_diagonal() const { return type == DIAG; }
+ bool is_normal() const { return type == NORMAL; }
+ Real getRealX() const; // return the x-coord
+ Real getRealY() const; // return the y-coord
+ Real persistence_lp(const Real p) const;
+ struct LexicographicCmp
+ {
+ bool operator()(const DiagramPoint& p1, const DiagramPoint& p2) const
+ { return p1.type < p2.type || (p1.type == p2.type && (p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y))); }
+ };
+
+ const Real& operator[](const int idx) const
+ {
+ switch(idx)
+ {
+ case 0 : return x;
+ break;
+ case 1 : return y;
+ break;
+ default: throw std::out_of_range("DiagramPoint has dimension 2");
+ }
+ }
+
+ Real& operator[](const int idx)
+ {
+ switch(idx)
+ {
+ case 0 : return x;
+ break;
+ case 1 : return y;
+ break;
+ default: throw std::out_of_range("DiagramPoint has dimension 2");
+ }
+ }
+
+ };
+
+
+ template<class Real>
+ struct DiagramPointHash {
+ size_t operator()(const DiagramPoint<Real> &p) const
+ {
+ std::size_t seed = 0;
+ hash_combine(seed, std::hash<Real>(p.x));
+ hash_combine(seed, std::hash<Real>(p.y));
+ hash_combine(seed, std::hash<bool>(p.is_diagonal()));
+ return seed;
+ }
+ };
+
+
+#ifndef FOR_R_TDA
+ template <class Real = double>
+ inline std::ostream& operator<<(std::ostream& output, const DiagramPoint<Real> p);
+#endif
+
+ template<class Real, class Pt>
+ struct DistImpl
+ {
+ Real operator()(const Pt& a, const Pt& b, const Real p, const int dim)
+ {
+ Real result = 0.0;
+ if (hera::is_infinity(p)) {
+ for(int d = 0; d < dim; ++d) {
+ result = std::max(result, std::fabs(a[d] - b[d]));
+ }
+ } else if (p == 1.0) {
+ for(int d = 0; d < dim; ++d) {
+ result += std::fabs(a[d] - b[d]);
+ }
+ } else {
+ assert(p > 1.0);
+ for(int d = 0; d < dim; ++d) {
+ result += std::pow(std::fabs(a[d] - b[d]), p);
+ }
+ result = std::pow(result, 1.0 / p);
+ }
+ return result;
+ }
+ };
+
+ template<class Real>
+ struct DistImpl<Real, DiagramPoint<Real>>
+ {
+ Real operator()(const DiagramPoint<Real>& a, const DiagramPoint<Real>& b, const Real p, const int dim)
+ {
+ Real result = 0.0;
+ if ( a.is_diagonal() and b.is_diagonal()) {
+ return result;
+ } else if (hera::is_infinity(p)) {
+ result = std::max(std::fabs(a.getRealX() - b.getRealX()), std::fabs(a.getRealY() - b.getRealY()));
+ } else if (p == 1.0) {
+ result = std::fabs(a.getRealX() - b.getRealX()) + std::fabs(a.getRealY() - b.getRealY());
+ } else {
+ assert(p > 1.0);
+ result = std::pow(std::pow(std::fabs(a.getRealX() - b.getRealX()), p) + std::pow(std::fabs(a.getRealY() - b.getRealY()), p), 1.0 / p);
+ }
+ return result;
+ }
+ };
+
+ template<class R, class Pt>
+ inline R dist_lp(const Pt& a, const Pt& b, const R p, const int dim)
+ {
+ return DistImpl<R, Pt>()(a, b, p, dim);
+ }
+
+ // TODO
+ template<class Real, typename DiagPointContainer>
+ inline double getFurthestDistance3Approx(DiagPointContainer& A, DiagPointContainer& B, const Real p)
+ {
+ int dim = 2;
+ Real result { 0.0 };
+ DiagramPoint<Real> begA = *(A.begin());
+ DiagramPoint<Real> optB = *(B.begin());
+ for(const auto& pointB : B) {
+ if (dist_lp(begA, pointB, p, dim) > result) {
+ result = dist_lp(begA, pointB, p, dim);
+ optB = pointB;
+ }
+ }
+ for(const auto& pointA : A) {
+ if (dist_lp(pointA, optB, p, dim) > result) {
+ result = dist_lp(pointA, optB, p, dim);
+ }
+ }
+ return result;
+ }
+
+ template<class Real>
+ inline Real getFurthestDistance3Approx_pg(const hera::ws::dnn::DynamicPointVector<Real>& A, const hera::ws::dnn::DynamicPointVector<Real>& B, const Real p, const int dim)
+ {
+ Real result { 0.0 };
+ int opt_b_idx = 0;
+ for(size_t b_idx = 0; b_idx < B.size(); ++b_idx) {
+ if (dist_lp(A[0], B[b_idx], p, dim) > result) {
+ result = dist_lp(A[0], B[b_idx], p, dim);
+ opt_b_idx = b_idx;
+ }
+ }
+
+ for(size_t a_idx = 0; a_idx < A.size(); ++a_idx) {
+ result = std::max(result, dist_lp(A[a_idx], B[opt_b_idx], p, dim));
+ }
+
+ return result;
+ }
+
+
+ template<class Container>
+ inline std::string format_container_to_log(const Container& cont);
+
+ template<class Real, class IndexContainer>
+ inline std::string format_point_set_to_log(const IndexContainer& indices, const std::vector<DiagramPoint<Real>>& points);
+
+ template<class T>
+ inline std::string format_int(T i);
+
+} // ws
+} // hera
+
+
+
+#include "basic_defs_ws.hpp"
+
+
+#endif
diff --git a/wasserstein/include/basic_defs_ws.hpp b/wasserstein/include/basic_defs_ws.hpp
new file mode 100644
index 0000000..a1153af
--- /dev/null
+++ b/wasserstein/include/basic_defs_ws.hpp
@@ -0,0 +1,220 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+Copyright (c) 2018, G. Spreemann
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#pragma once
+
+#include <algorithm>
+#include <cfloat>
+#include <set>
+#include <algorithm>
+#include <istream>
+#include <cstdint>
+#include "basic_defs_ws.h"
+
+#ifndef FOR_R_TDA
+#include <iostream>
+#endif
+
+#include <sstream>
+
+namespace hera {
+static const int64_t DIPHA_MAGIC = 8067171840;
+static const int64_t DIPHA_PERSISTENCE_DIAGRAM = 2;
+
+namespace ws {
+// Point
+
+template <class Real>
+bool Point<Real>::operator==(const Point<Real>& other) const
+{
+ return ((this->x == other.x) and (this->y == other.y));
+}
+
+template <class Real>
+bool Point<Real>::operator!=(const Point<Real>& other) const
+{
+ return !(*this == other);
+}
+
+
+#ifndef FOR_R_TDA
+template <class Real>
+inline std::ostream& operator<<(std::ostream& output, const Point<Real> p)
+{
+ output << "(" << p.x << ", " << p.y << ")";
+ return output;
+}
+#endif
+
+template <class Real>
+inline Real sqr_dist(const Point<Real>& a, const Point<Real>& b)
+{
+ return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
+}
+
+template <class Real>
+inline Real dist(const Point<Real>& a, const Point<Real>& b)
+{
+ return sqrt(sqr_dist(a, b));
+}
+
+
+template <class Real>
+inline Real DiagramPoint<Real>::persistence_lp(const Real p) const
+{
+ if (is_diagonal())
+ return 0.0;
+ else {
+ Real u { (getRealY() + getRealX())/2 };
+ int dim = 2;
+ DiagramPoint<Real> a_proj(u, u, DiagramPoint<Real>::DIAG);
+ return dist_lp(*this, a_proj, p, dim);
+ }
+}
+
+
+#ifndef FOR_R_TDA
+template <class Real>
+inline std::ostream& operator<<(std::ostream& output, const DiagramPoint<Real> p)
+{
+ if ( p.type == DiagramPoint<Real>::DIAG ) {
+ output << "(" << p.x << ", " << p.y << ", " << 0.5 * (p.x + p.y) << " DIAG )";
+ } else {
+ output << "(" << p.x << ", " << p.y << ", " << " NORMAL)";
+ }
+ return output;
+}
+#endif
+
+template <class Real>
+DiagramPoint<Real>::DiagramPoint(Real xx, Real yy, Type ttype) :
+ x(xx),
+ y(yy),
+ type(ttype)
+{
+ //if ( yy < xx )
+ //throw "Point is below the diagonal";
+ //if ( yy == xx and ttype != DiagramPoint<Real>::DIAG)
+ //throw "Point on the main diagonal must have DIAG type";
+}
+
+template <class Real>
+Real DiagramPoint<Real>::getRealX() const
+{
+ if (is_normal())
+ return x;
+ else
+ return Real(0.5) * (x + y);
+}
+
+template <class Real>
+Real DiagramPoint<Real>::getRealY() const
+{
+ if (is_normal())
+ return y;
+ else
+ return Real(0.5) * (x + y);
+}
+
+template<class Container>
+inline std::string format_container_to_log(const Container& cont)
+{
+ std::stringstream result;
+ result << "[";
+ for(auto iter = cont.begin(); iter != cont.end(); ++iter) {
+ result << *iter;
+ if (std::next(iter) != cont.end()) {
+ result << ", ";
+ }
+ }
+ result << "]";
+ return result.str();
+}
+
+template<class Container>
+inline std::string format_pair_container_to_log(const Container& cont)
+{
+ std::stringstream result;
+ result << "[";
+ for(auto iter = cont.begin(); iter != cont.end(); ++iter) {
+ result << "(" << iter->first << ", " << iter->second << ")";
+ if (std::next(iter) != cont.end()) {
+ result << ", ";
+ }
+ }
+ result << "]";
+ return result.str();
+}
+
+
+template<class Real, class IndexContainer>
+inline std::string format_point_set_to_log(const IndexContainer& indices,
+ const std::vector<DiagramPoint<Real>>& points)
+{
+ std::stringstream result;
+ result << "[";
+ for(auto iter = indices.begin(); iter != indices.end(); ++iter) {
+ DiagramPoint<Real> p = points[*iter];
+ result << "(" << p.getRealX() << ", " << p.getRealY() << ")";
+ if (std::next(iter) != indices.end())
+ result << ", ";
+ }
+ result << "]";
+ return result.str();
+}
+
+template<class T>
+inline std::string format_int(T i)
+{
+ std::stringstream ss;
+ ss.imbue(std::locale(""));
+ ss << std::fixed << i;
+ return ss.str();
+}
+
+
+} // end of namespace ws
+
+
+template <typename T> inline void reverse_endianness(T & x)
+{
+ uint8_t * p = reinterpret_cast<uint8_t *>(&x);
+ std::reverse(p, p + sizeof(T));
+}
+
+template <typename T> inline T read_le(std::istream & s)
+{
+ T result;
+ s.read(reinterpret_cast<char *>(&result), sizeof(T));
+ #ifdef BIGENDIAN
+ reverse_endianness(result);
+ #endif
+ return result;
+}
+
+} // hera
diff --git a/wasserstein/include/def_debug_ws.h b/wasserstein/include/def_debug_ws.h
new file mode 100644
index 0000000..791ce1d
--- /dev/null
+++ b/wasserstein/include/def_debug_ws.h
@@ -0,0 +1,44 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef DEF_DEBUG_WS_H
+#define DEF_DEBUG_WS_H
+
+//#define DEBUG_BOUND_MATCH
+//#define DEBUG_NEIGHBOUR_ORACLE
+//#define DEBUG_MATCHING
+//#define DEBUG_AUCTION
+// This symbol should be defined only in the version
+// for R package TDA, to comply with some CRAN rules
+// like no usage of cout, cerr, cin, exit, etc.
+//#define FOR_R_TDA
+//
+//#define DEBUG_KDTREE_RESTR_ORACLE
+//#define DEBUG_STUPID_SPARSE_RESTR_ORACLE
+//#define DEBUG_FR_AUCTION
+
+#endif
diff --git a/wasserstein/include/diagonal_heap.h b/wasserstein/include/diagonal_heap.h
new file mode 100644
index 0000000..3b3c8bc
--- /dev/null
+++ b/wasserstein/include/diagonal_heap.h
@@ -0,0 +1,149 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef DIAGONAL_HEAP_H
+#define DIAGONAL_HEAP_H
+
+//#define USE_BOOST_HEAP
+
+#include <map>
+#include <memory>
+#include <set>
+#include <list>
+
+#ifdef USE_BOOST_HEAP
+#include <boost/heap/d_ary_heap.hpp>
+#endif
+
+#include "basic_defs_ws.h"
+
+namespace hera {
+namespace ws {
+
+template <typename T>
+struct CompPairsBySecondLexStruct {
+ bool operator()(const IdxValPair<T>& a, const IdxValPair<T>& b) const
+ {
+ return a.second < b.second or (a.second == b.second and a.first > b.first);
+ }
+};
+
+
+template <typename T>
+struct CompPairsBySecondGreaterStruct {
+ bool operator()(const IdxValPair<T>& a, const IdxValPair<T>& b) const
+ {
+ return a.second > b.second;
+ }
+};
+
+#ifdef USE_BOOST_HEAP
+template <class Real>
+using LossesHeapOld = boost::heap::d_ary_heap<IdxValPair<Real>, boost::heap::arity<2>, boost::heap::mutable_<true>, boost::heap::compare<CompPairsBySecondGreaterStruct<Real>>>;
+#else
+template<typename T, class ComparisonStruct>
+class IdxValHeap {
+public:
+ using InternalKeeper = std::set<IdxValPair<T>, ComparisonStruct>;
+ using handle_type = typename InternalKeeper::iterator;
+ using const_handle_type = typename InternalKeeper::const_iterator;
+ // methods
+ handle_type push(const IdxValPair<T>& val)
+ {
+ auto res_pair = _heap.insert(val);
+ assert(res_pair.second);
+ assert(res_pair.first != _heap.end());
+ return res_pair.first;
+ }
+
+ void decrease(handle_type& handle, const IdxValPair<T>& new_val)
+ {
+ _heap.erase(handle);
+ handle = push(new_val);
+ }
+
+ void increase(handle_type& handle, const IdxValPair<T>& new_val)
+ {
+ _heap.erase(handle);
+ handle = push(new_val);
+ }
+
+ size_t size() const
+ {
+ return _heap.size();
+ }
+
+ handle_type ordered_begin()
+ {
+ return _heap.begin();
+ }
+
+ handle_type ordered_end()
+ {
+ return _heap.end();
+ }
+
+ const_handle_type ordered_begin() const
+ {
+ return _heap.cbegin();
+ }
+
+ const_handle_type ordered_end() const
+ {
+ return _heap.cend();
+ }
+
+
+private:
+ std::set<IdxValPair<T>, ComparisonStruct> _heap;
+};
+
+// if we store losses, the minimal value should come first
+template <class Real>
+using LossesHeapOld = IdxValHeap<Real, CompPairsBySecondLexStruct<Real>>;
+#endif
+
+template <class Real>
+inline std::string losses_heap_to_string(const LossesHeapOld<Real>& h)
+{
+ std::stringstream result;
+ result << "[";
+ for(auto iter = h.ordered_begin(); iter != h.ordered_end(); ++iter) {
+ result << *iter;
+ if (std::next(iter) != h.ordered_end()) {
+ result << ", ";
+ }
+ }
+ result << "]";
+ return result.str();
+}
+
+} // ws
+} // hera
+
+#endif // DIAGONAL_HEAP_H
diff --git a/wasserstein/include/diagram_reader.h b/wasserstein/include/diagram_reader.h
new file mode 100644
index 0000000..b52fcbd
--- /dev/null
+++ b/wasserstein/include/diagram_reader.h
@@ -0,0 +1,447 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+Copyright (c) 2018, G. Spreemann
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+*/
+
+#ifndef HERA_DIAGRAM_READER_H
+#define HERA_DIAGRAM_READER_H
+
+#ifndef FOR_R_TDA
+#include <iostream>
+#endif
+
+#include <iomanip>
+#include <locale>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cctype>
+#include <algorithm>
+#include <map>
+#include <limits>
+
+#include "basic_defs_ws.hpp"
+
+#ifdef WASSERSTEIN_PURE_GEOM
+#include "dnn/geometry/euclidean-dynamic.h"
+#endif
+
+namespace hera {
+
+// cannot choose stod, stof or stold based on RealType,
+// lazy solution: partial specialization
+template<class RealType = double>
+inline RealType parse_real_from_str(const std::string& s);
+
+template <>
+inline double parse_real_from_str<double>(const std::string& s)
+{
+ return std::stod(s);
+}
+
+
+template <>
+inline long double parse_real_from_str<long double>(const std::string& s)
+{
+ return std::stold(s);
+}
+
+
+template <>
+inline float parse_real_from_str<float>(const std::string& s)
+{
+ return std::stof(s);
+}
+
+
+template<class RealType>
+inline RealType parse_real_from_str(const std::string& s)
+{
+ static_assert(sizeof(RealType) != sizeof(RealType), "Must be specialized for each type you want to use, see above");
+}
+
+// fill in result with points from file fname
+// return false if file can't be opened
+// or error occurred while reading
+// decPrecision is the maximal decimal precision in the input,
+// it is zero if all coordinates in the input are integers
+template<class RealType = double, class ContType_ = std::vector<std::pair<RealType, RealType>>>
+inline bool read_diagram_point_set(const char* fname, ContType_& result, int& decPrecision)
+{
+ size_t lineNumber { 0 };
+ result.clear();
+ std::ifstream f(fname);
+ if (!f.good()) {
+#ifndef FOR_R_TDA
+ std::cerr << "Cannot open file " << fname << std::endl;
+#endif
+ return false;
+ }
+ std::locale loc;
+ std::string line;
+ while(std::getline(f, line)) {
+ lineNumber++;
+ // process comments: remove everything after hash
+ auto hashPos = line.find_first_of("#", 0);
+ if( std::string::npos != hashPos) {
+ line = std::string(line.begin(), line.begin() + hashPos);
+ }
+ if (line.empty()) {
+ continue;
+ }
+ // trim whitespaces
+ auto whiteSpaceFront = std::find_if_not(line.begin(),line.end(),isspace);
+ auto whiteSpaceBack = std::find_if_not(line.rbegin(),line.rend(),isspace).base();
+ if (whiteSpaceBack <= whiteSpaceFront) {
+ // line consists of spaces only - move to the next line
+ continue;
+ }
+ line = std::string(whiteSpaceFront,whiteSpaceBack);
+
+ // transform line to lower case
+ // to parse Infinity
+ for(auto& c : line) {
+ c = std::tolower(c, loc);
+ }
+
+ bool fracPart = false;
+ int currDecPrecision = 0;
+ for(auto c : line) {
+ if (c == '.') {
+ fracPart = true;
+ } else if (fracPart) {
+ if (isdigit(c)) {
+ currDecPrecision++;
+ } else {
+ fracPart = false;
+ if (currDecPrecision > decPrecision)
+ decPrecision = currDecPrecision;
+ currDecPrecision = 0;
+ }
+ }
+ }
+
+ RealType x, y;
+ std::string str_x, str_y;
+ std::istringstream iss(line);
+ try {
+ iss >> str_x >> str_y;
+
+ x = parse_real_from_str<RealType>(str_x);
+ y = parse_real_from_str<RealType>(str_y);
+
+ if (x != y) {
+ result.push_back(std::make_pair(x, y));
+ } else {
+#ifndef FOR_R_TDA
+ std::cerr << "Warning: point with 0 persistence ignored in " << fname << ":" << lineNumber << "\n";
+#endif
+ }
+ }
+ catch (const std::invalid_argument& e) {
+#ifndef FOR_R_TDA
+ std::cerr << "Error in file " << fname << ", line number " << lineNumber << ": cannot parse \"" << line << "\"" << std::endl;
+#endif
+ return false;
+ }
+ catch (const std::out_of_range&) {
+#ifndef FOR_R_TDA
+ std::cerr << "Error while reading file " << fname << ", line number " << lineNumber << ": value too large in \"" << line << "\"" << std::endl;
+#endif
+ return false;
+ }
+ }
+ f.close();
+ return true;
+}
+
+
+// wrappers
+template<class RealType = double, class ContType_ = std::vector<std::pair<RealType, RealType>>>
+inline bool read_diagram_point_set(const std::string& fname, ContType_& result, int& decPrecision)
+{
+ return read_diagram_point_set<RealType, ContType_>(fname.c_str(), result, decPrecision);
+}
+
+// these two functions are now just wrappers for the previous ones,
+// in case someone needs them; decPrecision is ignored
+template<class RealType = double, class ContType_ = std::vector<std::pair<RealType, RealType>>>
+inline bool read_diagram_point_set(const char* fname, ContType_& result)
+{
+ int decPrecision;
+ return read_diagram_point_set<RealType, ContType_>(fname, result, decPrecision);
+}
+
+template<class RealType = double, class ContType_ = std::vector<std::pair<RealType, RealType>>>
+inline bool read_diagram_point_set(const std::string& fname, ContType_& result)
+{
+ int decPrecision;
+ return read_diagram_point_set<RealType, ContType_>(fname.c_str(), result, decPrecision);
+}
+
+template<class RealType = double, class ContType_ = std::vector<std::pair<RealType, RealType> > >
+inline bool read_diagram_dipha(const std::string& fname, unsigned int dim, ContType_& result)
+{
+ std::ifstream file;
+ file.open(fname, std::ios::in | std::ios::binary);
+
+ if (!file.is_open()) {
+#ifndef FOR_R_TDA
+ std::cerr << "Could not open file " << fname << "." << std::endl;
+#endif
+ return false;
+ }
+
+ if (read_le<int64_t>(file) != DIPHA_MAGIC) {
+#ifndef FOR_R_TDA
+ std::cerr << "File " << fname << " is not a valid DIPHA file." << std::endl;
+#endif
+ file.close();
+ return false;
+ }
+
+ if (read_le<int64_t>(file) != DIPHA_PERSISTENCE_DIAGRAM) {
+#ifndef FOR_R_TDA
+ std::cerr << "File " << fname << " is not a valid DIPHA persistence diagram file." << std::endl;
+#endif
+ file.close();
+ return false;
+ }
+
+ result.clear();
+
+ int n = read_le<int64_t>(file);
+
+ for (int i = 0; i < n; ++i) {
+ int tmp_d = read_le<int64_t>(file);
+ double birth = read_le<double>(file);
+ double death = read_le<double>(file);
+
+ if (death < birth) {
+#ifndef FOR_R_TDA
+ std::cerr << "File " << fname << " is malformed." << std::endl;
+#endif
+ file.close();
+ return false;
+ }
+
+ int d = 0;
+ if (tmp_d < 0) {
+ d = -tmp_d - 1;
+ death = std::numeric_limits<double>::infinity();
+ } else
+ d = tmp_d;
+
+ if ((unsigned int)d == dim) {
+ if (death == birth) {
+#ifndef FOR_R_TDA
+ std::cerr << "Warning: point with 0 persistence ignored in " << fname << "." << std::endl;
+#endif
+ } else {
+ result.push_back(std::make_pair(birth, death));
+ }
+ }
+ }
+
+ file.close();
+
+ return true;
+}
+
+
+template<class RealType, class ContType>
+inline void remove_duplicates(ContType& dgm_A, ContType& dgm_B)
+{
+ std::map<std::pair<RealType, RealType>, int> map_A, map_B;
+ // copy points to maps
+ for(const auto& ptA : dgm_A) {
+ map_A[ptA]++;
+ }
+ for(const auto& ptB : dgm_B) {
+ map_B[ptB]++;
+ }
+ // clear vectors
+ dgm_A.clear();
+ dgm_B.clear();
+ // remove duplicates from maps
+ // loop over the smaller one
+ if (map_A.size() <= map_B.size()) {
+ for(auto& point_multiplicity_pair : map_A) {
+ auto iter_B = map_B.find(point_multiplicity_pair.first);
+ if (iter_B != map_B.end()) {
+ int duplicate_multiplicity = std::min(point_multiplicity_pair.second, iter_B->second);
+ point_multiplicity_pair.second -= duplicate_multiplicity;
+ iter_B->second -= duplicate_multiplicity;
+ }
+ }
+ } else {
+ for(auto& point_multiplicity_pair : map_B) {
+ auto iter_A = map_A.find(point_multiplicity_pair.first);
+ if (iter_A != map_A.end()) {
+ int duplicate_multiplicity = std::min(point_multiplicity_pair.second, iter_A->second);
+ point_multiplicity_pair.second -= duplicate_multiplicity;
+ iter_A->second -= duplicate_multiplicity;
+ }
+ }
+ }
+ // copy points back to vectors
+ for(const auto& pointMultiplicityPairA : map_A) {
+ assert( pointMultiplicityPairA.second >= 0);
+ for(int i = 0; i < pointMultiplicityPairA.second; ++i) {
+ dgm_A.push_back(pointMultiplicityPairA.first);
+ }
+ }
+
+ for(const auto& pointMultiplicityPairB : map_B) {
+ assert( pointMultiplicityPairB.second >= 0);
+ for(int i = 0; i < pointMultiplicityPairB.second; ++i) {
+ dgm_B.push_back(pointMultiplicityPairB.first);
+ }
+ }
+}
+
+
+#ifdef WASSERSTEIN_PURE_GEOM
+
+template<class Real>
+inline int get_point_dimension(const std::string& line)
+{
+ Real x;
+ int dim = 0;
+ std::istringstream iss(line);
+ while(iss >> x) {
+ dim++;
+ }
+ return dim;
+}
+
+
+template<class RealType = double >
+inline bool read_point_cloud(const char* fname, hera::ws::dnn::DynamicPointVector<RealType>& result, int& dimension, int& decPrecision)
+{
+ using DynamicPointTraitsR = typename hera::ws::dnn::DynamicPointTraits<RealType>;
+
+ size_t lineNumber { 0 };
+ result.clear();
+ std::ifstream f(fname);
+ if (!f.good()) {
+#ifndef FOR_R_TDA
+ std::cerr << "Cannot open file " << fname << std::endl;
+#endif
+ return false;
+ }
+ std::string line;
+ DynamicPointTraitsR traits;
+ bool dim_computed = false;
+ int point_idx = 0;
+ while(std::getline(f, line)) {
+ lineNumber++;
+ // process comments: remove everything after hash
+ auto hashPos = line.find_first_of("#", 0);
+ if( std::string::npos != hashPos) {
+ line = std::string(line.begin(), line.begin() + hashPos);
+ }
+ if (line.empty()) {
+ continue;
+ }
+ // trim whitespaces
+ auto whiteSpaceFront = std::find_if_not(line.begin(),line.end(),isspace);
+ auto whiteSpaceBack = std::find_if_not(line.rbegin(),line.rend(),isspace).base();
+ if (whiteSpaceBack <= whiteSpaceFront) {
+ // line consists of spaces only - move to the next line
+ continue;
+ }
+
+ line = std::string(whiteSpaceFront,whiteSpaceBack);
+
+ if (not dim_computed) {
+ dimension = get_point_dimension<RealType>(line);
+ traits = hera::ws::dnn::DynamicPointTraits<RealType>(dimension);
+ result = traits.container();
+ result.clear();
+ dim_computed = true;
+ }
+
+ bool fracPart = false;
+ int currDecPrecision = 0;
+ for(auto c : line) {
+ if (c == '.') {
+ fracPart = true;
+ } else if (fracPart) {
+ if (isdigit(c)) {
+ currDecPrecision++;
+ } else {
+ fracPart = false;
+ if (currDecPrecision > decPrecision)
+ decPrecision = currDecPrecision;
+ currDecPrecision = 0;
+ }
+ }
+ }
+
+ result.resize(result.size() + 1);
+ RealType x;
+ std::istringstream iss(line);
+ for(int d = 0; d < dimension; ++d) {
+ if (not(iss >> x)) {
+#ifndef FOR_R_TDA
+ std::cerr << "Error in file " << fname << ", line number " << lineNumber << ": cannot parse \"" << line << "\"" << std::endl;
+#endif
+ return false;
+ }
+ result[point_idx][d] = x;
+ }
+ point_idx++;
+ }
+ f.close();
+ return true;
+}
+
+// wrappers
+template<class RealType = double >
+inline bool read_point_cloud(const char* fname, hera::ws::dnn::DynamicPointVector<RealType>& result, int& dimension)
+{
+ int dec_precision;
+ return read_point_cloud<RealType>(fname, result, dimension, dec_precision);
+}
+
+template<class RealType = double >
+inline bool read_point_cloud(std::string fname, hera::ws::dnn::DynamicPointVector<RealType>& result, int& dimension, int& dec_precision)
+{
+ return read_point_cloud<RealType>(fname.c_str(), result, dimension, dec_precision);
+}
+
+template<class RealType = double >
+inline bool read_point_cloud(std::string fname, hera::ws::dnn::DynamicPointVector<RealType>& result, int& dimension)
+{
+ return read_point_cloud<RealType>(fname.c_str(), result, dimension);
+}
+
+#endif // WASSERSTEIN_PURE_GEOM
+
+} // end namespace hera
+#endif // HERA_DIAGRAM_READER_H
diff --git a/wasserstein/include/dnn/geometry/euclidean-dynamic.h b/wasserstein/include/dnn/geometry/euclidean-dynamic.h
new file mode 100644
index 0000000..b003906
--- /dev/null
+++ b/wasserstein/include/dnn/geometry/euclidean-dynamic.h
@@ -0,0 +1,270 @@
+#ifndef DNN_GEOMETRY_EUCLIDEAN_DYNAMIC_H
+#define DNN_GEOMETRY_EUCLIDEAN_DYNAMIC_H
+
+#include <vector>
+#include <algorithm>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/vector.hpp>
+#include <cmath>
+
+#include "hera_infinity.h"
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+
+template<class Real_>
+class DynamicPointVector
+{
+ public:
+ using Real = Real_;
+ struct PointType
+ {
+ void* p;
+
+ Real& operator[](const int i)
+ {
+ return (static_cast<Real*>(p))[i];
+ }
+
+ const Real& operator[](const int i) const
+ {
+ return (static_cast<Real*>(p))[i];
+ }
+
+ };
+ struct iterator;
+ typedef iterator const_iterator;
+
+ public:
+ DynamicPointVector(size_t point_capacity = 0):
+ point_capacity_(point_capacity) {}
+
+
+ PointType operator[](size_t i) const { return {(void*) &storage_[i*point_capacity_]}; }
+ inline void push_back(PointType p);
+
+ inline iterator begin();
+ inline iterator end();
+ inline const_iterator begin() const;
+ inline const_iterator end() const;
+
+ size_t size() const { return storage_.size() / point_capacity_; }
+
+ void clear() { storage_.clear(); }
+ void swap(DynamicPointVector& other) { storage_.swap(other.storage_); std::swap(point_capacity_, other.point_capacity_); }
+ void reserve(size_t sz) { storage_.reserve(sz * point_capacity_); }
+ void resize(size_t sz) { storage_.resize(sz * point_capacity_); }
+
+ private:
+ size_t point_capacity_;
+ std::vector<char> storage_;
+
+ private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int version) { ar & point_capacity_ & storage_; }
+};
+
+template<typename Real>
+struct DynamicPointTraits
+{
+ typedef DynamicPointVector<Real> PointContainer;
+ typedef typename PointContainer::PointType PointType;
+ struct PointHandle
+ {
+ void* p;
+ bool operator==(const PointHandle& other) const { return p == other.p; }
+ bool operator!=(const PointHandle& other) const { return !(*this == other); }
+ bool operator<(const PointHandle& other) const { return p < other.p; }
+ bool operator>(const PointHandle& other) const { return p > other.p; }
+ };
+
+ typedef Real Coordinate;
+ typedef Real DistanceType;
+
+ DynamicPointTraits(unsigned dim = 0):
+ dim_(dim) {}
+
+ DistanceType distance(PointType p1, PointType p2) const
+ {
+ Real result = 0.0;
+ if (hera::is_infinity(internal_p)) {
+ // max norm
+ for (unsigned i = 0; i < dimension(); ++i)
+ result = std::max(result, fabs(coordinate(p1,i) - coordinate(p2,i)));
+ } else if (internal_p == Real(1.0)) {
+ // l1-norm
+ for (unsigned i = 0; i < dimension(); ++i)
+ result += fabs(coordinate(p1,i) - coordinate(p2,i));
+ } else if (internal_p == Real(2.0)) {
+ result = sqrt(sq_distance(p1,p2));
+ } else {
+ assert(internal_p > 1.0);
+ for (unsigned i = 0; i < dimension(); ++i)
+ result += std::pow(fabs(coordinate(p1,i) - coordinate(p2,i)), internal_p);
+ result = std::pow(result, Real(1.0) / internal_p);
+ }
+ return result;
+ }
+ DistanceType distance(PointHandle p1, PointHandle p2) const { return distance(PointType({p1.p}), PointType({p2.p})); }
+ DistanceType sq_distance(PointType p1, PointType p2) const { Real res = 0; for (unsigned i = 0; i < dimension(); ++i) { Real c1 = coordinate(p1,i), c2 = coordinate(p2,i); res += (c1 - c2)*(c1 - c2); } return res; }
+ DistanceType sq_distance(PointHandle p1, PointHandle p2) const { return sq_distance(PointType({p1.p}), PointType({p2.p})); }
+ unsigned dimension() const { return dim_; }
+ Real& coordinate(PointType p, unsigned i) const { return ((Real*) p.p)[i]; }
+ Real& coordinate(PointHandle h, unsigned i) const { return ((Real*) h.p)[i]; }
+
+ // it's non-standard to return a reference, but we can rely on it for code that assumes this particular point type
+ size_t& id(PointType p) const { return *((size_t*) ((Real*) p.p + dimension())); }
+ size_t& id(PointHandle h) const { return *((size_t*) ((Real*) h.p + dimension())); }
+ PointHandle handle(PointType p) const { return {p.p}; }
+ PointType point(PointHandle h) const { return {h.p}; }
+
+ void swap(PointType p1, PointType p2) const { std::swap_ranges((char*) p1.p, ((char*) p1.p) + capacity(), (char*) p2.p); }
+ bool cmp(PointType p1, PointType p2) const { return std::lexicographical_compare((Real*) p1.p, ((Real*) p1.p) + dimension(), (Real*) p2.p, ((Real*) p2.p) + dimension()); }
+ bool eq(PointType p1, PointType p2) const { return std::equal((Real*) p1.p, ((Real*) p1.p) + dimension(), (Real*) p2.p); }
+
+ // non-standard, and possibly a weird name
+ size_t capacity() const { return sizeof(Real)*dimension() + sizeof(size_t); }
+
+ PointContainer container(size_t n = 0) const { PointContainer c(capacity()); c.resize(n); return c; }
+ PointContainer container(size_t n, const PointType& p) const;
+
+ typename PointContainer::iterator
+ iterator(PointContainer& c, PointHandle ph) const;
+ typename PointContainer::const_iterator
+ iterator(const PointContainer& c, PointHandle ph) const;
+
+ Real internal_p;
+
+ private:
+ unsigned dim_;
+
+ private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int version) { ar & dim_; }
+};
+
+} // dnn
+
+template<class Real>
+struct dnn::DynamicPointVector<Real>::iterator:
+ public boost::iterator_facade<iterator,
+ PointType,
+ std::random_access_iterator_tag,
+ PointType,
+ std::ptrdiff_t>
+{
+ typedef boost::iterator_facade<iterator,
+ PointType,
+ std::random_access_iterator_tag,
+ PointType,
+ std::ptrdiff_t> Parent;
+
+
+ public:
+ typedef typename Parent::value_type value_type;
+ typedef typename Parent::difference_type difference_type;
+ typedef typename Parent::reference reference;
+
+ iterator(size_t point_capacity = 0):
+ point_capacity_(point_capacity) {}
+
+ iterator(void* p, size_t point_capacity):
+ p_(p), point_capacity_(point_capacity) {}
+
+ private:
+ void increment() { p_ = ((char*) p_) + point_capacity_; }
+ void decrement() { p_ = ((char*) p_) - point_capacity_; }
+ void advance(difference_type n) { p_ = ((char*) p_) + n*point_capacity_; }
+ difference_type
+ distance_to(iterator other) const { return (((char*) other.p_) - ((char*) p_))/(int) point_capacity_; }
+ bool equal(const iterator& other) const { return p_ == other.p_; }
+ reference dereference() const { return {p_}; }
+
+ friend class ::boost::iterator_core_access;
+
+ private:
+ void* p_;
+ size_t point_capacity_;
+};
+
+template<class Real>
+void dnn::DynamicPointVector<Real>::push_back(PointType p)
+{
+ if (storage_.capacity() < storage_.size() + point_capacity_)
+ storage_.reserve(1.5*storage_.capacity());
+
+ storage_.resize(storage_.size() + point_capacity_);
+
+ std::copy((char*) p.p, (char*) p.p + point_capacity_, storage_.end() - point_capacity_);
+}
+
+template<class Real>
+typename dnn::DynamicPointVector<Real>::iterator dnn::DynamicPointVector<Real>::begin() { return iterator((void*) &*storage_.begin(), point_capacity_); }
+
+template<class Real>
+typename dnn::DynamicPointVector<Real>::iterator dnn::DynamicPointVector<Real>::end() { return iterator((void*) &*storage_.end(), point_capacity_); }
+
+template<class Real>
+typename dnn::DynamicPointVector<Real>::const_iterator dnn::DynamicPointVector<Real>::begin() const { return const_iterator((void*) &*storage_.begin(), point_capacity_); }
+
+template<class Real>
+typename dnn::DynamicPointVector<Real>::const_iterator dnn::DynamicPointVector<Real>::end() const { return const_iterator((void*) &*storage_.end(), point_capacity_); }
+
+template<typename R>
+typename dnn::DynamicPointTraits<R>::PointContainer
+dnn::DynamicPointTraits<R>::container(size_t n, const PointType& p) const
+{
+ PointContainer c = container(n);
+ for (auto x : c)
+ std::copy((char*) p.p, (char*) p.p + capacity(), (char*) x.p);
+ return c;
+}
+
+template<typename R>
+typename dnn::DynamicPointTraits<R>::PointContainer::iterator
+dnn::DynamicPointTraits<R>::iterator(PointContainer& c, PointHandle ph) const
+{ return typename PointContainer::iterator(ph.p, capacity()); }
+
+template<typename R>
+typename dnn::DynamicPointTraits<R>::PointContainer::const_iterator
+dnn::DynamicPointTraits<R>::iterator(const PointContainer& c, PointHandle ph) const
+{ return typename PointContainer::const_iterator(ph.p, capacity()); }
+
+} // ws
+} // hera
+
+namespace std {
+ template<>
+ struct hash<typename hera::ws::dnn::DynamicPointTraits<double>::PointHandle>
+ {
+ using PointHandle = typename hera::ws::dnn::DynamicPointTraits<double>::PointHandle;
+ size_t operator()(const PointHandle& ph) const
+ {
+ return std::hash<void*>()(ph.p);
+ }
+ };
+
+ template<>
+ struct hash<typename hera::ws::dnn::DynamicPointTraits<float>::PointHandle>
+ {
+ using PointHandle = typename hera::ws::dnn::DynamicPointTraits<float>::PointHandle;
+ size_t operator()(const PointHandle& ph) const
+ {
+ return std::hash<void*>()(ph.p);
+ }
+ };
+
+
+} // std
+
+
+#endif
diff --git a/wasserstein/include/dnn/geometry/euclidean-fixed.h b/wasserstein/include/dnn/geometry/euclidean-fixed.h
new file mode 100644
index 0000000..3e38baf
--- /dev/null
+++ b/wasserstein/include/dnn/geometry/euclidean-fixed.h
@@ -0,0 +1,196 @@
+#ifndef HERA_WS_DNN_GEOMETRY_EUCLIDEAN_FIXED_H
+#define HERA_WS_DNN_GEOMETRY_EUCLIDEAN_FIXED_H
+
+#include <boost/operators.hpp>
+#include <boost/array.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/base_object.hpp>
+
+//#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <cmath>
+
+#include "../parallel/tbb.h" // for dnn::vector<...>
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+ // TODO: wrap in another namespace (e.g., euclidean)
+
+ template<size_t D, typename Real = double>
+ struct Point:
+ boost::addable< Point<D,Real>,
+ boost::subtractable< Point<D,Real>,
+ boost::dividable2< Point<D, Real>, Real,
+ boost::multipliable2< Point<D, Real>, Real > > > >,
+ public boost::array<Real, D>
+ {
+ public:
+ typedef Real Coordinate;
+ typedef Real DistanceType;
+
+
+ public:
+ Point(size_t id = 0): id_(id) {}
+ template<size_t DD>
+ Point(const Point<DD,Real>& p, size_t id = 0):
+ id_(id) { *this = p; }
+
+ static size_t dimension() { return D; }
+
+ // Assign a point of different dimension
+ template<size_t DD>
+ Point& operator=(const Point<DD,Real>& p) { for (size_t i = 0; i < (D < DD ? D : DD); ++i) (*this)[i] = p[i]; if (DD < D) for (size_t i = DD; i < D; ++i) (*this)[i] = 0; return *this; }
+
+ Point& operator+=(const Point& p) { for (size_t i = 0; i < D; ++i) (*this)[i] += p[i]; return *this; }
+ Point& operator-=(const Point& p) { for (size_t i = 0; i < D; ++i) (*this)[i] -= p[i]; return *this; }
+ Point& operator/=(Real r) { for (size_t i = 0; i < D; ++i) (*this)[i] /= r; return *this; }
+ Point& operator*=(Real r) { for (size_t i = 0; i < D; ++i) (*this)[i] *= r; return *this; }
+
+ Real norm2() const { Real n = 0; for (size_t i = 0; i < D; ++i) n += (*this)[i] * (*this)[i]; return n; }
+ Real max_norm() const
+ {
+ Real res = std::fabs((*this)[0]);
+ for (size_t i = 1; i < D; ++i)
+ if (std::fabs((*this)[i]) > res)
+ res = std::fabs((*this)[i]);
+ return res;
+ }
+
+ Real l1_norm() const
+ {
+ Real res = std::fabs((*this)[0]);
+ for (size_t i = 1; i < D; ++i)
+ res += std::fabs((*this)[i]);
+ return res;
+ }
+
+ Real lp_norm(const Real p) const
+ {
+ assert( !std::isinf(p) );
+ if ( p == 1.0 )
+ return l1_norm();
+ Real res = std::pow(std::fabs((*this)[0]), p);
+ for (size_t i = 1; i < D; ++i)
+ res += std::pow(std::fabs((*this)[i]), p);
+ return std::pow(res, 1.0 / p);
+ }
+
+ // quick and dirty for now; make generic later
+ //DistanceType distance(const Point& other) const { return sqrt(sq_distance(other)); }
+ //DistanceType sq_distance(const Point& other) const { return (other - *this).norm2(); }
+
+ DistanceType distance(const Point& other) const { return (other - *this).max_norm(); }
+ DistanceType p_distance(const Point& other, const double p) const { return (other - *this).lp_norm(p); }
+
+ size_t id() const { return id_; }
+ size_t& id() { return id_; }
+
+ private:
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object< boost::array<Real,D> >(*this) & id_; }
+
+ private:
+ size_t id_;
+ };
+
+ template<size_t D, typename Real>
+ std::ostream&
+ operator<<(std::ostream& out, const Point<D,Real>& p)
+ { out << p[0]; for (size_t i = 1; i < D; ++i) out << " " << p[i]; return out; }
+
+
+ template<class Point>
+ struct PointTraits; // intentionally undefined; should be specialized for each type
+
+
+ template<size_t D, typename Real>
+ struct PointTraits< Point<D, Real> > // specialization for dnn::Point
+ {
+ typedef Point<D,Real> PointType;
+ typedef const PointType* PointHandle;
+ typedef std::vector<PointType> PointContainer;
+
+ typedef typename PointType::Coordinate Coordinate;
+ typedef typename PointType::DistanceType DistanceType;
+
+
+ static DistanceType
+ distance(const PointType& p1, const PointType& p2) { if (hera::is_infinity(internal_p)) return p1.distance(p2); else return p1.p_distance(p2, internal_p); }
+
+ static DistanceType
+ distance(PointHandle p1, PointHandle p2) { return distance(*p1,*p2); }
+
+ static size_t dimension() { return D; }
+ static Real coordinate(const PointType& p, size_t i) { return p[i]; }
+ static Real& coordinate(PointType& p, size_t i) { return p[i]; }
+ static Real coordinate(PointHandle p, size_t i) { return coordinate(*p,i); }
+
+ static size_t id(const PointType& p) { return p.id(); }
+ static size_t& id(PointType& p) { return p.id(); }
+ static size_t id(PointHandle p) { return id(*p); }
+
+ static PointHandle
+ handle(const PointType& p) { return &p; }
+ static const PointType&
+ point(PointHandle ph) { return *ph; }
+
+ void swap(PointType& p1, PointType& p2) const { return std::swap(p1, p2); }
+
+ static PointContainer
+ container(size_t n = 0, const PointType& p = PointType()) { return PointContainer(n, p); }
+ static typename PointContainer::iterator
+ iterator(PointContainer& c, PointHandle ph) { return c.begin() + (ph - &c[0]); }
+ static typename PointContainer::const_iterator
+ iterator(const PointContainer& c, PointHandle ph) { return c.begin() + (ph - &c[0]); }
+
+ // Internal_p determines which norm will be used in Wasserstein metric (not to
+ // be confused with wassersteinPower parameter:
+ // we raise \| p - q \|_{internal_p} to wassersteinPower.
+ static Real internal_p;
+
+ private:
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int version) {}
+
+ };
+
+ template<size_t D, typename Real>
+ Real PointTraits< Point<D, Real> >::internal_p = hera::get_infinity<Real>();
+
+
+ template<class PointContainer>
+ void read_points(const std::string& filename, PointContainer& points)
+ {
+ typedef typename boost::range_value<PointContainer>::type Point;
+ typedef typename PointTraits<Point>::Coordinate Coordinate;
+
+ std::ifstream in(filename.c_str());
+ std::string line;
+ while(std::getline(in, line))
+ {
+ if (line[0] == '#') continue; // comment line in the file
+ std::stringstream linestream(line);
+ Coordinate x;
+ points.push_back(Point());
+ size_t i = 0;
+ while (linestream >> x)
+ points.back()[i++] = x;
+ }
+ }
+} // dnn
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/dnn/local/kd-tree.h b/wasserstein/include/dnn/local/kd-tree.h
new file mode 100644
index 0000000..8e52a5c
--- /dev/null
+++ b/wasserstein/include/dnn/local/kd-tree.h
@@ -0,0 +1,97 @@
+#ifndef HERA_WS_DNN_LOCAL_KD_TREE_H
+#define HERA_WS_DNN_LOCAL_KD_TREE_H
+
+#include "../utils.h"
+#include "search-functors.h"
+
+#include <unordered_map>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/range/value_type.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+ // Weighted KDTree
+ // Traits_ provides Coordinate, DistanceType, PointType, dimension(), distance(p1,p2), coordinate(p,i)
+ template< class Traits_ >
+ class KDTree
+ {
+ public:
+ typedef Traits_ Traits;
+ typedef dnn::HandleDistance<KDTree> HandleDistance;
+
+ typedef typename Traits::PointType Point;
+ typedef typename Traits::PointHandle PointHandle;
+ typedef typename Traits::Coordinate Coordinate;
+ typedef typename Traits::DistanceType DistanceType;
+ typedef std::vector<PointHandle> HandleContainer;
+ typedef std::vector<HandleDistance> HDContainer; // TODO: use tbb::scalable_allocator
+ typedef HDContainer Result;
+ typedef std::vector<DistanceType> DistanceContainer;
+ typedef std::unordered_map<PointHandle, size_t> HandleMap;
+
+ BOOST_STATIC_ASSERT_MSG(has_coordinates<Traits, PointHandle, int>::value, "KDTree requires coordinates");
+
+ public:
+ KDTree(const Traits& traits):
+ traits_(traits) {}
+
+ KDTree(const Traits& traits, HandleContainer&& handles, double _wassersteinPower = 1.0);
+
+ template<class Range>
+ KDTree(const Traits& traits, const Range& range, double _wassersteinPower = 1.0);
+
+ template<class Range>
+ void init(const Range& range);
+
+ DistanceType weight(PointHandle p) { return weights_[indices_[p]]; }
+ void change_weight(PointHandle p, DistanceType w);
+ void adjust_weights(DistanceType delta); // subtract delta from all weights
+
+ HandleDistance find(PointHandle q) const;
+ Result findR(PointHandle q, DistanceType r) const; // all neighbors within r
+ Result findK(PointHandle q, size_t k) const; // k nearest neighbors
+
+ HandleDistance find(const Point& q) const { return find(traits().handle(q)); }
+ Result findR(const Point& q, DistanceType r) const { return findR(traits().handle(q), r); }
+ Result findK(const Point& q, size_t k) const { return findK(traits().handle(q), k); }
+
+ template<class ResultsFunctor>
+ void search(PointHandle q, ResultsFunctor& rf) const;
+
+ const Traits& traits() const { return traits_; }
+
+ void printWeights(void);
+
+ private:
+ void init();
+
+ typedef typename HandleContainer::iterator HCIterator;
+ typedef std::tuple<HCIterator, HCIterator, size_t> KDTreeNode;
+
+ struct CoordinateComparison;
+ struct OrderTree;
+
+ private:
+ Traits traits_;
+ HandleContainer tree_;
+ DistanceContainer weights_; // point weight
+ DistanceContainer subtree_weights_; // min weight in the subtree
+ HandleMap indices_;
+ double wassersteinPower;
+ };
+} // dnn
+} // ws
+} // hera
+
+#include "kd-tree.hpp"
+
+#endif
diff --git a/wasserstein/include/dnn/local/kd-tree.hpp b/wasserstein/include/dnn/local/kd-tree.hpp
new file mode 100644
index 0000000..bdeef45
--- /dev/null
+++ b/wasserstein/include/dnn/local/kd-tree.hpp
@@ -0,0 +1,330 @@
+#include <boost/range/counting_range.hpp>
+#include <boost/range/algorithm_ext/push_back.hpp>
+#include <boost/range.hpp>
+
+#include <queue>
+#include <stack>
+
+#include "../parallel/tbb.h"
+#include "def_debug_ws.h"
+
+template<class T>
+hera::ws::dnn::KDTree<T>::
+KDTree(const Traits& traits, HandleContainer&& handles, double _wassersteinPower):
+ traits_(traits), tree_(std::move(handles)), wassersteinPower(_wassersteinPower)
+{ assert(wassersteinPower >= 1.0); init(); }
+
+template<class T>
+template<class Range>
+hera::ws::dnn::KDTree<T>::
+KDTree(const Traits& traits, const Range& range, double _wassersteinPower):
+ traits_(traits), wassersteinPower(_wassersteinPower)
+{
+ assert( wassersteinPower >= 1.0);
+ init(range);
+}
+
+template<class T>
+template<class Range>
+void
+hera::ws::dnn::KDTree<T>::
+init(const Range& range)
+{
+ size_t sz = std::distance(std::begin(range), std::end(range));
+ tree_.reserve(sz);
+ weights_.resize(sz, 0);
+ subtree_weights_.resize(sz, 0);
+ for (PointHandle h : range)
+ tree_.push_back(h);
+ init();
+}
+
+template<class T>
+void
+hera::ws::dnn::KDTree<T>::
+init()
+{
+ if (tree_.empty())
+ return;
+
+#if defined(TBB)
+ task_group g;
+ g.run(OrderTree(tree_.begin(), tree_.end(), 0, traits()));
+ g.wait();
+#else
+ OrderTree(tree_.begin(), tree_.end(), 0, traits()).serial();
+#endif
+
+ for (size_t i = 0; i < tree_.size(); ++i)
+ indices_[tree_[i]] = i;
+}
+
+template<class T>
+struct
+hera::ws::dnn::KDTree<T>::OrderTree
+{
+ OrderTree(HCIterator b_, HCIterator e_, size_t i_, const Traits& traits_):
+ b(b_), e(e_), i(i_), traits(traits_) {}
+
+ void operator()() const
+ {
+ if (e - b < 1000)
+ {
+ serial();
+ return;
+ }
+
+ HCIterator m = b + (e - b)/2;
+ CoordinateComparison cmp(i, traits);
+ std::nth_element(b,m,e, cmp);
+ size_t next_i = (i + 1) % traits.dimension();
+
+ task_group g;
+ if (b < m - 1) g.run(OrderTree(b, m, next_i, traits));
+ if (e > m + 2) g.run(OrderTree(m+1, e, next_i, traits));
+ g.wait();
+ }
+
+ void serial() const
+ {
+ std::queue<KDTreeNode> q;
+ q.push(KDTreeNode(b,e,i));
+ while (!q.empty())
+ {
+ HCIterator b, e; size_t i;
+ std::tie(b,e,i) = q.front();
+ q.pop();
+ HCIterator m = b + (e - b)/2;
+
+ CoordinateComparison cmp(i, traits);
+ std::nth_element(b,m,e, cmp);
+ size_t next_i = (i + 1) % traits.dimension();
+
+ // Replace with a size condition instead?
+ if (m - b > 1) q.push(KDTreeNode(b, m, next_i));
+ if (e - m > 2) q.push(KDTreeNode(m+1, e, next_i));
+ }
+ }
+
+ HCIterator b, e;
+ size_t i;
+ const Traits& traits;
+};
+
+template<class T>
+template<class ResultsFunctor>
+void
+hera::ws::dnn::KDTree<T>::
+search(PointHandle q, ResultsFunctor& rf) const
+{
+ typedef typename HandleContainer::const_iterator HCIterator;
+ typedef std::tuple<HCIterator, HCIterator, size_t> KDTreeNode;
+
+ if (tree_.empty())
+ return;
+
+ DistanceType D = std::numeric_limits<DistanceType>::max();
+
+ // TODO: use tbb::scalable_allocator for the queue
+ std::queue<KDTreeNode> nodes;
+
+ nodes.push(KDTreeNode(tree_.begin(), tree_.end(), 0));
+
+ while (!nodes.empty())
+ {
+ HCIterator b, e; size_t i;
+ std::tie(b,e,i) = nodes.front();
+ nodes.pop();
+
+ CoordinateComparison cmp(i, traits());
+ i = (i + 1) % traits().dimension();
+
+ HCIterator m = b + (e - b)/2;
+
+ DistanceType dist = (wassersteinPower == 1.0) ? traits().distance(q, *m) + weights_[m - tree_.begin()] : std::pow(traits().distance(q, *m), wassersteinPower) + weights_[m - tree_.begin()];
+
+
+ D = rf(*m, dist);
+
+ // we are really searching w.r.t L_\infty ball; could prune better with an L_2 ball
+ Coordinate diff = cmp.diff(q, *m); // diff returns signed distance
+
+ DistanceType diffToWasserPower = (wassersteinPower == 1.0) ? diff : ((diff > 0 ? 1.0 : -1.0) * std::pow(fabs(diff), wassersteinPower));
+
+ size_t lm = m + 1 + (e - (m+1))/2 - tree_.begin();
+ if (e > m + 1 && diffToWasserPower - subtree_weights_[lm] >= -D) {
+ nodes.push(KDTreeNode(m+1, e, i));
+ }
+
+ size_t rm = b + (m - b) / 2 - tree_.begin();
+ if (b < m && diffToWasserPower + subtree_weights_[rm] <= D) {
+ nodes.push(KDTreeNode(b, m, i));
+ }
+ }
+}
+
+template<class T>
+void
+hera::ws::dnn::KDTree<T>::
+adjust_weights(DistanceType delta)
+{
+ for(auto& w : weights_)
+ w -= delta;
+
+ for(auto& sw : subtree_weights_)
+ sw -= delta;
+}
+
+
+template<class T>
+void
+hera::ws::dnn::KDTree<T>::
+change_weight(PointHandle p, DistanceType w)
+{
+ size_t idx = indices_[p];
+
+ if ( weights_[idx] == w ) {
+ return;
+ }
+
+ bool weight_increases = ( weights_[idx] < w );
+ weights_[idx] = w;
+
+ typedef std::tuple<HCIterator, HCIterator> KDTreeNode;
+
+ // find the path down the tree to this node
+ // not an ideal strategy, but // it's not clear how to move up from the node in general
+ std::stack<KDTreeNode> s;
+ s.push(KDTreeNode(tree_.begin(),tree_.end()));
+
+ do
+ {
+ HCIterator b,e;
+ std::tie(b,e) = s.top();
+
+ size_t im = b + (e - b)/2 - tree_.begin();
+
+ if (idx == im)
+ break;
+ else if (idx < im)
+ s.push(KDTreeNode(b, tree_.begin() + im));
+ else // idx > im
+ s.push(KDTreeNode(tree_.begin() + im + 1, e));
+ } while(1);
+
+ // update subtree_weights_ on the path to the root
+ DistanceType min_w = w;
+ while (!s.empty())
+ {
+ HCIterator b,e;
+ std::tie(b,e) = s.top();
+ HCIterator m = b + (e - b)/2;
+ size_t im = m - tree_.begin();
+ s.pop();
+
+
+ // left and right children
+ if (b < m)
+ {
+ size_t lm = b + (m - b)/2 - tree_.begin();
+ if (subtree_weights_[lm] < min_w)
+ min_w = subtree_weights_[lm];
+ }
+
+ if (e > m + 1)
+ {
+ size_t rm = m + 1 + (e - (m+1))/2 - tree_.begin();
+ if (subtree_weights_[rm] < min_w)
+ min_w = subtree_weights_[rm];
+ }
+
+ if (weights_[im] < min_w) {
+ min_w = weights_[im];
+ }
+
+ if (weight_increases) {
+
+ if (subtree_weights_[im] < min_w ) // increase weight
+ subtree_weights_[im] = min_w;
+ else
+ break;
+
+ } else {
+
+ if (subtree_weights_[im] > min_w ) // decrease weight
+ subtree_weights_[im] = min_w;
+ else
+ break;
+
+ }
+ }
+}
+
+template<class T>
+typename hera::ws::dnn::KDTree<T>::HandleDistance
+hera::ws::dnn::KDTree<T>::
+find(PointHandle q) const
+{
+ hera::ws::dnn::NNRecord<HandleDistance> nn;
+ search(q, nn);
+ return nn.result;
+}
+
+template<class T>
+typename hera::ws::dnn::KDTree<T>::Result
+hera::ws::dnn::KDTree<T>::
+findR(PointHandle q, DistanceType r) const
+{
+ hera::ws::dnn::rNNRecord<HandleDistance> rnn(r);
+ search(q, rnn);
+ std::sort(rnn.result.begin(), rnn.result.end());
+ return rnn.result;
+}
+
+template<class T>
+typename hera::ws::dnn::KDTree<T>::Result
+hera::ws::dnn::KDTree<T>::
+findK(PointHandle q, size_t k) const
+{
+ hera::ws::dnn::kNNRecord<HandleDistance> knn(k);
+ search(q, knn);
+ std::sort(knn.result.begin(), knn.result.end());
+ return knn.result;
+}
+
+
+template<class T>
+struct hera::ws::dnn::KDTree<T>::CoordinateComparison
+{
+ CoordinateComparison(size_t i, const Traits& traits):
+ i_(i), traits_(traits) {}
+
+ bool operator()(PointHandle p1, PointHandle p2) const { return coordinate(p1) < coordinate(p2); }
+ Coordinate diff(PointHandle p1, PointHandle p2) const { return coordinate(p1) - coordinate(p2); }
+
+ Coordinate coordinate(PointHandle p) const { return traits_.coordinate(p, i_); }
+ size_t axis() const { return i_; }
+
+ private:
+ size_t i_;
+ const Traits& traits_;
+};
+
+template<class T>
+void
+hera::ws::dnn::KDTree<T>::
+printWeights(void)
+{
+#ifndef FOR_R_TDA
+ std::cout << "weights_:" << std::endl;
+ for(const auto ph : indices_) {
+ std::cout << "idx = " << ph.second << ": (" << (ph.first)->at(0) << ", " << (ph.first)->at(1) << ") weight = " << weights_[ph.second] << std::endl;
+ }
+ std::cout << "subtree_weights_:" << std::endl;
+ for(size_t idx = 0; idx < subtree_weights_.size(); ++idx) {
+ std::cout << idx << " : " << subtree_weights_[idx] << std::endl;
+ }
+#endif
+}
+
+
diff --git a/wasserstein/include/dnn/local/search-functors.h b/wasserstein/include/dnn/local/search-functors.h
new file mode 100644
index 0000000..1419f22
--- /dev/null
+++ b/wasserstein/include/dnn/local/search-functors.h
@@ -0,0 +1,95 @@
+#ifndef HERA_WS_DNN_LOCAL_SEARCH_FUNCTORS_H
+#define HERA_WS_DNN_LOCAL_SEARCH_FUNCTORS_H
+
+#include <boost/range/algorithm/heap_algorithm.hpp>
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+
+template<class NN>
+struct HandleDistance
+{
+ typedef typename NN::PointHandle PointHandle;
+ typedef typename NN::DistanceType DistanceType;
+ typedef typename NN::HDContainer HDContainer;
+
+ HandleDistance() {}
+ HandleDistance(PointHandle pp, DistanceType dd):
+ p(pp), d(dd) {}
+ bool operator<(const HandleDistance& other) const { return d < other.d; }
+
+ PointHandle p;
+ DistanceType d;
+};
+
+template<class HandleDistance>
+struct NNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+
+ NNRecord() { result.d = std::numeric_limits<DistanceType>::max(); }
+ DistanceType operator()(PointHandle p, DistanceType d) { if (d < result.d) { result.p = p; result.d = d; } return result.d; }
+ HandleDistance result;
+};
+
+template<class HandleDistance>
+struct rNNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+ typedef typename HandleDistance::HDContainer HDContainer;
+
+ rNNRecord(DistanceType r_): r(r_) {}
+ DistanceType operator()(PointHandle p, DistanceType d)
+ {
+ if (d <= r)
+ result.push_back(HandleDistance(p,d));
+ return r;
+ }
+
+ DistanceType r;
+ HDContainer result;
+};
+
+template<class HandleDistance>
+struct kNNRecord
+{
+ typedef typename HandleDistance::PointHandle PointHandle;
+ typedef typename HandleDistance::DistanceType DistanceType;
+ typedef typename HandleDistance::HDContainer HDContainer;
+
+ kNNRecord(unsigned k_): k(k_) {}
+ DistanceType operator()(PointHandle p, DistanceType d)
+ {
+ if (result.size() < k)
+ {
+ result.push_back(HandleDistance(p,d));
+ boost::push_heap(result);
+ if (result.size() < k)
+ return std::numeric_limits<DistanceType>::max();
+ } else if (d < result[0].d)
+ {
+ boost::pop_heap(result);
+ result.back() = HandleDistance(p,d);
+ boost::push_heap(result);
+ }
+ if ( result.size() > 1 ) {
+ assert( result[0].d >= result[1].d );
+ }
+ return result[0].d;
+ }
+
+ unsigned k;
+ HDContainer result;
+};
+
+} // dnn
+} // ws
+} // hera
+
+#endif // DNN_LOCAL_SEARCH_FUNCTORS_H
diff --git a/wasserstein/include/dnn/parallel/tbb.h b/wasserstein/include/dnn/parallel/tbb.h
new file mode 100644
index 0000000..712f812
--- /dev/null
+++ b/wasserstein/include/dnn/parallel/tbb.h
@@ -0,0 +1,235 @@
+#ifndef HERA_WS_PARALLEL_H
+#define HERA_WS_PARALLEL_H
+
+#include <vector>
+
+#include <boost/range.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+
+#ifdef TBB
+
+#include <tbb/tbb.h>
+#include <tbb/concurrent_hash_map.h>
+#include <tbb/scalable_allocator.h>
+
+#include <boost/serialization/split_free.hpp>
+#include <boost/serialization/collections_load_imp.hpp>
+#include <boost/serialization/collections_save_imp.hpp>
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+ using tbb::mutex;
+ using tbb::task_scheduler_init;
+ using tbb::task_group;
+ using tbb::task;
+
+ template<class T>
+ struct vector
+ {
+ typedef tbb::concurrent_vector<T> type;
+ };
+
+ template<class T>
+ struct atomic
+ {
+ typedef tbb::atomic<T> type;
+ static T compare_and_swap(type& v, T n, T o) { return v.compare_and_swap(n,o); }
+ };
+
+ template<class Iterator, class F>
+ void do_foreach(Iterator begin, Iterator end, const F& f) { tbb::parallel_do(begin, end, f); }
+
+ template<class Range, class F>
+ void for_each_range_(const Range& r, const F& f)
+ {
+ for (typename Range::iterator cur = r.begin(); cur != r.end(); ++cur)
+ f(*cur);
+ }
+
+ template<class F>
+ void for_each_range(size_t from, size_t to, const F& f)
+ {
+ //static tbb::affinity_partitioner ap;
+ //tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f), ap);
+ tbb::parallel_for(from, to, f);
+ }
+
+ template<class Container, class F>
+ void for_each_range(const Container& c, const F& f)
+ {
+ //static tbb::affinity_partitioner ap;
+ //tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f), ap);
+ tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::const_range_type, F>, _1, f));
+ }
+
+ template<class Container, class F>
+ void for_each_range(Container& c, const F& f)
+ {
+ //static tbb::affinity_partitioner ap;
+ //tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f), ap);
+ tbb::parallel_for(c.range(), boost::bind(&for_each_range_<typename Container::range_type, F>, _1, f));
+ }
+
+ template<class ID, class NodePointer, class IDTraits, class Allocator>
+ struct map_traits
+ {
+ typedef tbb::concurrent_hash_map<ID, NodePointer, IDTraits, Allocator> type;
+ typedef typename type::range_type range;
+ };
+
+ struct progress_timer
+ {
+ progress_timer(): start(tbb::tick_count::now()) {}
+ ~progress_timer()
+ { std::cout << (tbb::tick_count::now() - start).seconds() << " s" << std::endl; }
+
+ tbb::tick_count start;
+ };
+} // dnn
+} // ws
+} // hera
+
+// Serialization for tbb::concurrent_vector<...>
+namespace boost
+{
+ namespace serialization
+ {
+ template<class Archive, class T, class A>
+ void save(Archive& ar, const tbb::concurrent_vector<T,A>& v, const unsigned int file_version)
+ { stl::save_collection(ar, v); }
+
+ template<class Archive, class T, class A>
+ void load(Archive& ar, tbb::concurrent_vector<T,A>& v, const unsigned int file_version)
+ {
+ stl::load_collection<Archive,
+ tbb::concurrent_vector<T,A>,
+ stl::archive_input_seq< Archive, tbb::concurrent_vector<T,A> >,
+ stl::reserve_imp< tbb::concurrent_vector<T,A> >
+ >(ar, v);
+ }
+
+ template<class Archive, class T, class A>
+ void serialize(Archive& ar, tbb::concurrent_vector<T,A>& v, const unsigned int file_version)
+ { split_free(ar, v, file_version); }
+
+ template<class Archive, class T>
+ void save(Archive& ar, const tbb::atomic<T>& v, const unsigned int file_version)
+ { T v_ = v; ar << v_; }
+
+ template<class Archive, class T>
+ void load(Archive& ar, tbb::atomic<T>& v, const unsigned int file_version)
+ { T v_; ar >> v_; v = v_; }
+
+ template<class Archive, class T>
+ void serialize(Archive& ar, tbb::atomic<T>& v, const unsigned int file_version)
+ { split_free(ar, v, file_version); }
+ }
+}
+
+#else
+
+#include <algorithm>
+#include <map>
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+ template<class T>
+ struct vector
+ {
+ typedef ::std::vector<T> type;
+ };
+
+ template<class T>
+ struct atomic
+ {
+ typedef T type;
+ static T compare_and_swap(type& v, T n, T o) { if (v != o) return v; v = n; return o; }
+ };
+
+ template<class Iterator, class F>
+ void do_foreach(Iterator begin, Iterator end, const F& f) { std::for_each(begin, end, f); }
+
+ template<class F>
+ void for_each_range(size_t from, size_t to, const F& f)
+ {
+ for (size_t i = from; i < to; ++i)
+ f(i);
+ }
+
+ template<class Container, class F>
+ void for_each_range(Container& c, const F& f)
+ {
+ BOOST_FOREACH(const typename Container::value_type& i, c)
+ f(i);
+ }
+
+ template<class Container, class F>
+ void for_each_range(const Container& c, const F& f)
+ {
+ BOOST_FOREACH(const typename Container::value_type& i, c)
+ f(i);
+ }
+
+ struct mutex
+ {
+ struct scoped_lock
+ {
+ scoped_lock() {}
+ scoped_lock(mutex& ) {}
+ void acquire(mutex& ) const {}
+ void release() const {}
+ };
+ };
+
+ struct task_scheduler_init
+ {
+ task_scheduler_init(unsigned) {}
+ void initialize(unsigned) {}
+ static const unsigned automatic = 0;
+ static const unsigned deferred = 0;
+ };
+
+ struct task_group
+ {
+ template<class Functor>
+ void run(const Functor& f) const { f(); }
+ void wait() const {}
+ };
+
+ template<class ID, class NodePointer, class IDTraits, class Allocator>
+ struct map_traits
+ {
+ typedef std::map<ID, NodePointer,
+ typename IDTraits::Comparison,
+ Allocator> type;
+ typedef type range;
+ };
+
+} // dnn
+} // ws
+} // hera
+
+#endif // TBB
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+ template<class Range, class F>
+ void do_foreach(const Range& range, const F& f) { do_foreach(boost::begin(range), boost::end(range), f); }
+} // dnn
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/dnn/parallel/utils.h b/wasserstein/include/dnn/parallel/utils.h
new file mode 100644
index 0000000..7104ec3
--- /dev/null
+++ b/wasserstein/include/dnn/parallel/utils.h
@@ -0,0 +1,100 @@
+#ifndef HERA_WS_PARALLEL_UTILS_H
+#define HERA_WS_PARALLEL_UTILS_H
+
+#include "../utils.h"
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+ // Assumes rng is synchronized across ranks
+ template<class DataVector, class RNGType, class SwapFunctor>
+ void shuffle(mpi::communicator& world, DataVector& data, RNGType& rng, const SwapFunctor& swap, DataVector empty = DataVector());
+
+ template<class DataVector, class RNGType>
+ void shuffle(mpi::communicator& world, DataVector& data, RNGType& rng)
+ {
+ typedef decltype(data[0]) T;
+ shuffle(world, data, rng, [](T& x, T& y) { std::swap(x,y); });
+ }
+} // dnn
+} // ws
+} // hera
+
+template<class DataVector, class RNGType, class SwapFunctor>
+void
+hera::ws::dnn::shuffle(mpi::communicator& world, DataVector& data, RNGType& rng, const SwapFunctor& swap, DataVector empty)
+{
+ // This is not a perfect shuffle: it dishes out data in chunks of 1/size.
+ // (It can be interpreted as generating a bistochastic matrix by taking the
+ // sum of size random permutation matrices.) Hopefully, it works for our purposes.
+
+ typedef typename RNGType::result_type RNGResult;
+
+ int size = world.size();
+ int rank = world.rank();
+
+ // Generate local seeds
+ boost::uniform_int<RNGResult> uniform;
+ RNGResult seed;
+ for (size_t i = 0; i < size; ++i)
+ {
+ RNGResult v = uniform(rng);
+ if (i == rank)
+ seed = v;
+ }
+ RNGType local_rng(seed);
+
+ // Shuffle local data
+ hera::ws::dnn::random_shuffle(data.begin(), data.end(), local_rng, swap);
+
+ // Decide how much of our data goes to i-th processor
+ std::vector<size_t> out_counts(size);
+ std::vector<int> ranks(boost::counting_iterator<int>(0),
+ boost::counting_iterator<int>(size));
+ for (size_t i = 0; i < size; ++i)
+ {
+ hera::ws::dnn::random_shuffle(ranks.begin(), ranks.end(), rng);
+ ++out_counts[ranks[rank]];
+ }
+
+ // Fill the outgoing array
+ size_t total = 0;
+ std::vector< DataVector > outgoing(size, empty);
+ for (size_t i = 0; i < size; ++i)
+ {
+ size_t count = data.size()*out_counts[i]/size;
+ if (total + count > data.size())
+ count = data.size() - total;
+
+ outgoing[i].reserve(count);
+ for (size_t j = total; j < total + count; ++j)
+ outgoing[i].push_back(data[j]);
+
+ total += count;
+ }
+
+ boost::uniform_int<size_t> uniform_outgoing(0,size-1); // in range [0,size-1]
+ while(total < data.size()) // send leftover to random processes
+ {
+ outgoing[uniform_outgoing(local_rng)].push_back(data[total]);
+ ++total;
+ }
+ data.clear();
+
+ // Exchange the data
+ std::vector< DataVector > incoming(size, empty);
+ mpi::all_to_all(world, outgoing, incoming);
+ outgoing.clear();
+
+ // Assemble our data
+ for(const DataVector& vec : incoming)
+ for (size_t i = 0; i < vec.size(); ++i)
+ data.push_back(vec[i]);
+ hera::ws::dnn::random_shuffle(data.begin(), data.end(), local_rng, swap);
+ // XXX: the final shuffle is irrelevant for our purposes. But it's also cheap.
+}
+
+#endif
diff --git a/wasserstein/include/dnn/utils.h b/wasserstein/include/dnn/utils.h
new file mode 100644
index 0000000..bbce793
--- /dev/null
+++ b/wasserstein/include/dnn/utils.h
@@ -0,0 +1,47 @@
+#ifndef HERA_WS_DNN_UTILS_H
+#define HERA_WS_DNN_UTILS_H
+
+#include <boost/random/uniform_int.hpp>
+#include <boost/foreach.hpp>
+#include <boost/typeof/typeof.hpp>
+
+namespace hera
+{
+namespace ws
+{
+namespace dnn
+{
+
+template <typename T, typename... Args>
+struct has_coordinates
+{
+ template <typename C, typename = decltype( std::declval<C>().coordinate(std::declval<Args>()...) )>
+ static std::true_type test(int);
+
+ template <typename C>
+ static std::false_type test(...);
+
+ static constexpr bool value = decltype(test<T>(0))::value;
+};
+
+template<class RandomIt, class UniformRandomNumberGenerator, class SwapFunctor>
+void random_shuffle(RandomIt first, RandomIt last, UniformRandomNumberGenerator& g, const SwapFunctor& swap)
+{
+ size_t n = last - first;
+ boost::uniform_int<size_t> uniform(0,n);
+ for (size_t i = n-1; i > 0; --i)
+ swap(first[i], first[uniform(g,i+1)]); // picks a random number in [0,i] range
+}
+
+template<class RandomIt, class UniformRandomNumberGenerator>
+void random_shuffle(RandomIt first, RandomIt last, UniformRandomNumberGenerator& g)
+{
+ typedef decltype(*first) T;
+ random_shuffle(first, last, g, [](T& x, T& y) { std::swap(x,y); });
+}
+
+} // dnn
+} // ws
+} // hera
+
+#endif
diff --git a/wasserstein/include/hera_infinity.h b/wasserstein/include/hera_infinity.h
new file mode 100644
index 0000000..8d86dbb
--- /dev/null
+++ b/wasserstein/include/hera_infinity.h
@@ -0,0 +1,22 @@
+#ifndef WASSERSTEIN_HERA_INFINITY_H
+#define WASSERSTEIN_HERA_INFINITY_H
+
+// we cannot assume that template parameter Real will always provide infinity() value,
+// so value -1.0 is used to encode infinity (l_inf norm is used by default)
+
+namespace hera {
+
+ template<class Real = double>
+ inline bool is_infinity(const Real& x)
+ {
+ return x == Real(-1);
+ };
+
+ template<class Real = double>
+ inline constexpr Real get_infinity()
+ {
+ return Real(-1);
+ }
+}
+
+#endif //WASSERSTEIN_HERA_INFINITY_H
diff --git a/wasserstein/include/opts/opts.h b/wasserstein/include/opts/opts.h
new file mode 100755
index 0000000..74e788b
--- /dev/null
+++ b/wasserstein/include/opts/opts.h
@@ -0,0 +1,353 @@
+/**
+ * Author: Dmitriy Morozov <dmitriy@mrzv.org>
+ * The interface is heavily influenced by GetOptPP (https://code.google.com/p/getoptpp/).
+ */
+
+#ifndef OPTS_OPTS_H
+#define OPTS_OPTS_H
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <list>
+#include <vector>
+
+namespace opts {
+
+// Converters
+template<class T>
+struct Converter
+{
+ Converter() {}
+ static
+ T convert(const std::string& val) { std::istringstream iss(val); T res; iss >> res; return res; }
+};
+
+// Type
+template<class T>
+struct Traits
+{
+ static std::string type_string() { return "UNKNOWN TYPE"; }
+};
+
+template<>
+struct Traits<int>
+{
+ static std::string type_string() { return "INT"; }
+};
+
+template<>
+struct Traits<short int>
+{
+ static std::string type_string() { return "SHORT INT"; }
+};
+
+template<>
+struct Traits<unsigned>
+{
+ static std::string type_string() { return "UNSIGNED INT"; }
+};
+
+template<>
+struct Traits<short unsigned>
+{
+ static std::string type_string() { return "SHORT UNSIGNED INT"; }
+};
+
+template<>
+struct Traits<float>
+{
+ static std::string type_string() { return "FLOAT"; }
+};
+
+template<>
+struct Traits<double>
+{
+ static std::string type_string() { return "DOUBLE"; }
+};
+
+template<>
+struct Traits<std::string>
+{
+ static std::string type_string() { return "STRING"; }
+};
+
+
+struct BasicOption
+{
+ BasicOption(char s_,
+ std::string l_,
+ std::string default_,
+ std::string type_,
+ std::string help_):
+ s(s_), l(l_), d(default_), t(type_), help(help_) {}
+
+ int long_size() const { return l.size() + 1 + t.size(); }
+
+ void output(std::ostream& out, int max_long) const
+ {
+ out << " ";
+ if (s)
+ out << '-' << s << ", ";
+ else
+ out << " ";
+
+ out << "--" << l << ' ';
+
+ if (!t.empty())
+ out << t;
+
+ for (int i = long_size(); i < max_long; ++i)
+ out << ' ';
+
+ out << " " << help;
+
+ if (!d.empty())
+ {
+ out << " [default: " << d << "]";
+ }
+ out << '\n';
+ }
+
+ char s;
+ std::string l;
+ std::string d;
+ std::string t;
+ std::string help;
+};
+
+// Option
+template<class T>
+struct OptionContainer: public BasicOption
+{
+ OptionContainer(char s_,
+ const std::string& l_,
+ T& var_,
+ const std::string& help_,
+ const std::string& type_ = Traits<T>::type_string()):
+ BasicOption(s_, l_, default_value(var_), type_, help_),
+ var(&var_) {}
+
+ static
+ std::string default_value(const T& def)
+ {
+ std::ostringstream oss;
+ oss << def;
+ return oss.str();
+ }
+
+ void parse(std::list<std::string>& args) const
+ {
+ std::string short_opt = "-"; short_opt += s;
+ std::string long_opt = "--" + l;
+ for (std::list<std::string>::iterator cur = args.begin(); cur != args.end(); ++cur)
+ {
+ if (*cur == short_opt || *cur == long_opt)
+ {
+ cur = args.erase(cur);
+ if (cur != args.end())
+ {
+ *var = Converter<T>::convert(*cur);
+ cur = args.erase(cur);
+ break; // finds first occurrence
+ }
+ else
+ break; // if the last option's value is missing, it remains default
+
+ }
+ }
+ }
+
+ T* var;
+};
+
+template<class T>
+struct OptionContainer< std::vector<T> >: public BasicOption
+{
+ OptionContainer(char s_,
+ const std::string& l_,
+ std::vector<T>& var_,
+ const std::string& help_,
+ const std::string& type_ = "SEQUENCE"):
+ BasicOption(s_, l_, default_value(var_), type_, help_),
+ var(&var_) { }
+
+ static
+ std::string default_value(const std::vector<T>& def)
+ {
+ std::ostringstream oss;
+ oss << "(";
+ if (def.size())
+ oss << def[0];
+ for (int i = 1; i < def.size(); ++i)
+ oss << ", " << def[i];
+ oss << ")";
+ return oss.str();
+ }
+
+ void parse(std::list<std::string>& args) const
+ {
+ std::string short_opt = "-"; short_opt += s;
+ std::string long_opt = "--" + l;
+ for (std::list<std::string>::iterator cur = args.begin(); cur != args.end(); ++cur)
+ {
+ if (*cur == short_opt || *cur == long_opt)
+ {
+ cur = args.erase(cur);
+ if (cur != args.end())
+ {
+ var->push_back(Converter<T>::convert(*cur));
+ cur = args.erase(cur);
+ }
+ --cur;
+ }
+ }
+ }
+
+ std::vector<T>* var;
+};
+
+
+template<class T>
+OptionContainer<T>
+Option(char s, const std::string& l, T& var, const std::string& help) { return OptionContainer<T>(s, l, var, help); }
+
+template<class T>
+OptionContainer<T>
+Option(char s, const std::string& l, T& var,
+ const std::string& type, const std::string& help) { return OptionContainer<T>(s, l, var, help, type); }
+
+template<class T>
+OptionContainer<T>
+Option(const std::string& l, T& var, const std::string& help) { return OptionContainer<T>(0, l, var, help); }
+
+template<class T>
+OptionContainer<T>
+Option(const std::string& l, T& var,
+ const std::string& type, const std::string& help) { return OptionContainer<T>(0, l, var, help, type); }
+
+// Present
+struct PresentContainer: public BasicOption
+{
+ PresentContainer(char s, const std::string& l, const std::string& help):
+ BasicOption(s,l,"","",help) {}
+};
+
+inline
+PresentContainer
+Present(char s, const std::string& l, const std::string& help) { return PresentContainer(s, l, help); }
+
+inline
+PresentContainer
+Present(const std::string& l, const std::string& help) { return PresentContainer(0, l, help); }
+
+// PosOption
+template<class T>
+struct PosOptionContainer
+{
+ PosOptionContainer(T& var_):
+ var(&var_) {}
+
+ bool parse(std::list<std::string>& args) const
+ {
+ if (args.empty())
+ return false;
+
+ *var = Converter<T>::convert(args.front());
+ args.pop_front();
+ return true;
+ }
+
+ T* var;
+};
+
+template<class T>
+PosOptionContainer<T>
+PosOption(T& var) { return PosOptionContainer<T>(var); }
+
+
+// Options
+struct Options
+{
+ Options(int argc_, char** argv_):
+ args(argv_ + 1, argv_ + argc_),
+ failed(false) {}
+
+ template<class T>
+ Options& operator>>(const OptionContainer<T>& oc);
+ bool operator>>(const PresentContainer& pc);
+ template<class T>
+ Options& operator>>(const PosOptionContainer<T>& poc);
+
+ operator bool() { return !failed; }
+
+
+ friend
+ std::ostream&
+ operator<<(std::ostream& out, const Options& ops)
+ {
+ int max_long = 0;
+ for (std::list<BasicOption>::const_iterator cur = ops.options.begin();
+ cur != ops.options.end();
+ ++cur)
+ {
+ int cur_long = cur->long_size();
+ if (cur_long > max_long)
+ max_long = cur_long;
+ }
+
+ out << "Options:\n";
+ for (std::list<BasicOption>::const_iterator cur = ops.options.begin();
+ cur != ops.options.end();
+ ++cur)
+ cur->output(out, max_long);
+
+ return out;
+ }
+
+
+ private:
+ std::list<std::string> args;
+ std::list<BasicOption> options;
+ bool failed;
+};
+
+template<class T>
+Options&
+Options::operator>>(const OptionContainer<T>& oc)
+{
+ options.push_back(oc);
+ oc.parse(args);
+ return *this;
+}
+
+inline
+bool
+Options::operator>>(const PresentContainer& pc)
+{
+ options.push_back(pc);
+
+ for(std::list<std::string>::iterator cur = args.begin(); cur != args.end(); ++cur)
+ {
+ std::string short_opt = "-"; short_opt += pc.s;
+ std::string long_opt = "--" + pc.l;
+ if (*cur == short_opt || *cur == long_opt)
+ {
+ args.erase(cur);
+ return true;
+ }
+ }
+ return false;
+}
+
+template<class T>
+Options&
+Options::operator>>(const PosOptionContainer<T>& poc)
+{
+ failed = !poc.parse(args);
+ return *this;
+}
+
+}
+
+#endif
diff --git a/wasserstein/include/wasserstein.h b/wasserstein/include/wasserstein.h
new file mode 100644
index 0000000..db6ce11
--- /dev/null
+++ b/wasserstein/include/wasserstein.h
@@ -0,0 +1,346 @@
+/*
+
+Copyright (c) 2015, M. Kerber, D. Morozov, A. Nigmetov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+You are under no obligation whatsoever to provide any bug fixes, patches, or
+upgrades to the features, functionality or performance of the source code
+(Enhancements) to anyone; however, if you choose to make your Enhancements
+available either publicly, or directly to copyright holder,
+without imposing a separate written license agreement for such Enhancements,
+then you hereby grant the following license: a non-exclusive, royalty-free
+perpetual license to install, use, modify, prepare derivative works, incorporate
+into other computer software, distribute, and sublicense such enhancements or
+derivative works thereof, in binary and source code form.
+
+ */
+
+#ifndef HERA_WASSERSTEIN_H
+#define HERA_WASSERSTEIN_H
+
+#include <vector>
+#include <map>
+#include <math.h>
+
+#include "def_debug_ws.h"
+#include "basic_defs_ws.h"
+#include "diagram_reader.h"
+#include "auction_runner_gs.h"
+#include "auction_runner_gs_single_diag.h"
+#include "auction_runner_jac.h"
+#include "auction_runner_fr.h"
+
+
+namespace hera
+{
+
+template<class PairContainer_, class PointType_ = typename std::remove_reference< decltype(*std::declval<PairContainer_>().begin())>::type >
+struct DiagramTraits
+{
+ using PointType = PointType_;
+ using RealType = typename std::remove_reference< decltype(std::declval<PointType>()[0]) >::type;
+
+ static RealType get_x(const PointType& p) { return p[0]; }
+ static RealType get_y(const PointType& p) { return p[1]; }
+};
+
+template<class PairContainer_, class RealType_>
+struct DiagramTraits<PairContainer_, std::pair<RealType_, RealType_>>
+{
+ using RealType = RealType_;
+ using PointType = std::pair<RealType, RealType>;
+
+ static RealType get_x(const PointType& p) { return p.first; }
+ static RealType get_y(const PointType& p) { return p.second; }
+};
+
+
+namespace ws
+{
+
+ // compare as multisets
+ template<class PairContainer>
+ inline bool are_equal(const PairContainer& dgm1, const PairContainer& dgm2)
+ {
+ if (dgm1.size() != dgm2.size()) {
+ return false;
+ }
+
+ using Traits = typename hera::DiagramTraits<PairContainer>;
+ using PointType = typename Traits::PointType;
+
+ std::map<PointType, int> m1, m2;
+
+ for(auto&& pair1 : dgm1) {
+ m1[pair1]++;
+ }
+
+ for(auto&& pair2 : dgm2) {
+ m2[pair2]++;
+ }
+
+ return m1 == m2;
+ }
+
+ // to handle points with one coordinate = infinity
+ template<class RealType>
+ inline RealType get_one_dimensional_cost(std::vector<RealType>& set_A,
+ std::vector<RealType>& set_B,
+ const RealType wasserstein_power)
+ {
+ if (set_A.size() != set_B.size()) {
+ return std::numeric_limits<RealType>::infinity();
+ }
+ std::sort(set_A.begin(), set_A.end());
+ std::sort(set_B.begin(), set_B.end());
+ RealType result = 0.0;
+ for(size_t i = 0; i < set_A.size(); ++i) {
+ result += std::pow(std::fabs(set_A[i] - set_B[i]), wasserstein_power);
+ }
+ return result;
+ }
+
+
+ template<class RealType>
+ struct SplitProblemInput
+ {
+ std::vector<DiagramPoint<RealType>> A_1;
+ std::vector<DiagramPoint<RealType>> B_1;
+ std::vector<DiagramPoint<RealType>> A_2;
+ std::vector<DiagramPoint<RealType>> B_2;
+
+ std::unordered_map<size_t, size_t> A_1_indices;
+ std::unordered_map<size_t, size_t> A_2_indices;
+ std::unordered_map<size_t, size_t> B_1_indices;
+ std::unordered_map<size_t, size_t> B_2_indices;
+
+ RealType mid_coord { 0.0 };
+ RealType strip_width { 0.0 };
+
+ void init_vectors(size_t n)
+ {
+
+ A_1_indices.clear();
+ A_2_indices.clear();
+ B_1_indices.clear();
+ B_2_indices.clear();
+
+ A_1.clear();
+ A_2.clear();
+ B_1.clear();
+ B_2.clear();
+
+ A_1.reserve(n / 2);
+ B_1.reserve(n / 2);
+ A_2.reserve(n / 2);
+ B_2.reserve(n / 2);
+ }
+
+ void init(const std::vector<DiagramPoint<RealType>>& A,
+ const std::vector<DiagramPoint<RealType>>& B)
+ {
+ using DiagramPointR = DiagramPoint<RealType>;
+
+ init_vectors(A.size());
+
+ RealType min_sum = std::numeric_limits<RealType>::max();
+ RealType max_sum = -std::numeric_limits<RealType>::max();
+ for(const auto& p_A : A) {
+ RealType s = p_A[0] + p_A[1];
+ if (s > max_sum)
+ max_sum = s;
+ if (s < min_sum)
+ min_sum = s;
+ mid_coord += s;
+ }
+
+ mid_coord /= A.size();
+
+ strip_width = 0.25 * (max_sum - min_sum);
+
+ auto first_diag_iter = std::upper_bound(A.begin(), A.end(), 0, [](const int& a, const DiagramPointR& p) { return a < (int)(p.is_diagonal()); });
+ size_t num_normal_A_points = std::distance(A.begin(), first_diag_iter);
+
+ // process all normal points in A,
+ // projections follow normal points
+ for(size_t i = 0; i < A.size(); ++i) {
+
+ assert(i < num_normal_A_points and A.is_normal() or i >= num_normal_A_points and A.is_diagonal());
+ assert(i < num_normal_A_points and B.is_diagonal() or i >= num_normal_A_points and B.is_normal());
+
+ RealType s = i < num_normal_A_points ? A[i][0] + A[i][1] : B[i][0] + B[i][1];
+
+ if (s < mid_coord + strip_width) {
+ // add normal point and its projection to the
+ // left half
+ A_1.push_back(A[i]);
+ B_1.push_back(B[i]);
+ A_1_indices[i] = A_1.size() - 1;
+ B_1_indices[i] = B_1.size() - 1;
+ }
+
+ if (s > mid_coord - strip_width) {
+ // to the right half
+ A_2.push_back(A[i]);
+ B_2.push_back(B[i]);
+ A_2_indices[i] = A_2.size() - 1;
+ B_2_indices[i] = B_2.size() - 1;
+ }
+
+ }
+ } // end init
+
+ };
+
+
+ // CAUTION:
+ // this function assumes that all coordinates are finite
+ // points at infinity are processed in wasserstein_cost
+ template<class RealType>
+ inline RealType wasserstein_cost_vec(const std::vector<DiagramPoint<RealType>>& A,
+ const std::vector<DiagramPoint<RealType>>& B,
+ AuctionParams<RealType>& params,
+ const std::string& _log_filename_prefix)
+ {
+ if (params.wasserstein_power < 1.0) {
+ throw std::runtime_error("Bad q in Wasserstein " + std::to_string(params.wasserstein_power));
+ }
+ if (params.delta < 0.0) {
+ throw std::runtime_error("Bad delta in Wasserstein " + std::to_string(params.delta));
+ }
+ if (params.initial_epsilon < 0.0) {
+ throw std::runtime_error("Bad initial epsilon in Wasserstein" + std::to_string(params.initial_epsilon));
+ }
+ if (params.epsilon_common_ratio < 0.0) {
+ throw std::runtime_error("Bad epsilon factor in Wasserstein " + std::to_string(params.epsilon_common_ratio));
+ }
+
+ if (A.empty() and B.empty())
+ return 0.0;
+
+ RealType result;
+
+ // just use Gauss-Seidel
+ AuctionRunnerGS<RealType> auction(A, B, params, _log_filename_prefix);
+ auction.run_auction();
+ result = auction.get_wasserstein_cost();
+ params.final_relative_error = auction.get_relative_error();
+ return result;
+ }
+
+} // ws
+
+
+
+template<class PairContainer>
+inline typename DiagramTraits<PairContainer>::RealType
+wasserstein_cost(const PairContainer& A,
+ const PairContainer& B,
+ AuctionParams< typename DiagramTraits<PairContainer>::RealType >& params,
+ const std::string& _log_filename_prefix = "")
+{
+ using Traits = DiagramTraits<PairContainer>;
+
+ //using PointType = typename Traits::PointType;
+ using RealType = typename Traits::RealType;
+
+ if (hera::ws::are_equal(A, B)) {
+ return 0.0;
+ }
+
+ bool a_empty = true;
+ bool b_empty = true;
+ RealType total_cost_A = 0.0;
+ RealType total_cost_B = 0.0;
+
+ using DgmPoint = hera::ws::DiagramPoint<RealType>;
+
+ std::vector<DgmPoint> dgm_A, dgm_B;
+ // coordinates of points at infinity
+ std::vector<RealType> x_plus_A, x_minus_A, y_plus_A, y_minus_A;
+ std::vector<RealType> x_plus_B, x_minus_B, y_plus_B, y_minus_B;
+ // loop over A, add projections of A-points to corresponding positions
+ // in B-vector
+ for(auto&& pair_A : A) {
+ a_empty = false;
+ RealType x = Traits::get_x(pair_A);
+ RealType y = Traits::get_y(pair_A);
+ if ( x == std::numeric_limits<RealType>::infinity()) {
+ y_plus_A.push_back(y);
+ } else if (x == -std::numeric_limits<RealType>::infinity()) {
+ y_minus_A.push_back(y);
+ } else if (y == std::numeric_limits<RealType>::infinity()) {
+ x_plus_A.push_back(x);
+ } else if (y == -std::numeric_limits<RealType>::infinity()) {
+ x_minus_A.push_back(x);
+ } else {
+ dgm_A.emplace_back(x, y, DgmPoint::NORMAL);
+ dgm_B.emplace_back(x, y, DgmPoint::DIAG);
+ total_cost_A += std::pow(dgm_A.back().persistence_lp(params.internal_p), params.wasserstein_power);
+ }
+ }
+ // the same for B
+ for(auto&& pair_B : B) {
+ b_empty = false;
+ RealType x = Traits::get_x(pair_B);
+ RealType y = Traits::get_y(pair_B);
+ if (x == std::numeric_limits<RealType>::infinity()) {
+ y_plus_B.push_back(y);
+ } else if (x == -std::numeric_limits<RealType>::infinity()) {
+ y_minus_B.push_back(y);
+ } else if (y == std::numeric_limits<RealType>::infinity()) {
+ x_plus_B.push_back(x);
+ } else if (y == -std::numeric_limits<RealType>::infinity()) {
+ x_minus_B.push_back(x);
+ } else {
+ dgm_A.emplace_back(x, y, DgmPoint::DIAG);
+ dgm_B.emplace_back(x, y, DgmPoint::NORMAL);
+ total_cost_B += std::pow(dgm_B.back().persistence_lp(params.internal_p), params.wasserstein_power);
+ }
+ }
+
+ RealType infinity_cost = ws::get_one_dimensional_cost(x_plus_A, x_plus_B, params.wasserstein_power);
+ infinity_cost += ws::get_one_dimensional_cost(x_minus_A, x_minus_B, params.wasserstein_power);
+ infinity_cost += ws::get_one_dimensional_cost(y_plus_A, y_plus_B, params.wasserstein_power);
+ infinity_cost += ws::get_one_dimensional_cost(y_minus_A, y_minus_B, params.wasserstein_power);
+
+ if (a_empty)
+ return total_cost_B + infinity_cost;
+
+ if (b_empty)
+ return total_cost_A + infinity_cost;
+
+
+ if (infinity_cost == std::numeric_limits<RealType>::infinity()) {
+ return infinity_cost;
+ } else {
+ return infinity_cost + wasserstein_cost_vec(dgm_A, dgm_B, params, _log_filename_prefix);
+ }
+
+}
+
+template<class PairContainer>
+inline typename DiagramTraits<PairContainer>::RealType
+wasserstein_dist(const PairContainer& A,
+ const PairContainer& B,
+ AuctionParams<typename DiagramTraits<PairContainer>::RealType>& params,
+ const std::string& _log_filename_prefix = "")
+{
+ using Real = typename DiagramTraits<PairContainer>::RealType;
+ return std::pow(hera::wasserstein_cost(A, B, params, _log_filename_prefix), Real(1.)/params.wasserstein_power);
+}
+
+} // end of namespace hera
+
+#endif
diff --git a/wasserstein/include/wasserstein_pure_geom.hpp b/wasserstein/include/wasserstein_pure_geom.hpp
new file mode 100644
index 0000000..096d95d
--- /dev/null
+++ b/wasserstein/include/wasserstein_pure_geom.hpp
@@ -0,0 +1,86 @@
+#ifndef WASSERSTEIN_PURE_GEOM_HPP
+#define WASSERSTEIN_PURE_GEOM_HPP
+
+#define WASSERSTEIN_PURE_GEOM
+
+
+#include "diagram_reader.h"
+#include "auction_oracle_kdtree_pure_geom.h"
+#include "auction_runner_gs.h"
+#include "auction_runner_jac.h"
+
+namespace hera
+{
+namespace ws
+{
+
+ template <class Real>
+ using DynamicTraits = typename hera::ws::dnn::DynamicPointTraits<Real>;
+
+ template <class Real>
+ using DynamicPoint = typename hera::ws::dnn::DynamicPointTraits<Real>::PointType;
+
+ template <class Real>
+ using DynamicPointVector = typename hera::ws::dnn::DynamicPointVector<Real>;
+
+ template <class Real>
+ using AuctionRunnerGSR = typename hera::ws::AuctionRunnerGS<Real, hera::ws::AuctionOracleKDTreePureGeom<Real>, hera::ws::dnn::DynamicPointVector<Real>>;
+
+ template <class Real>
+ using AuctionRunnerJacR = typename hera::ws::AuctionRunnerJac<Real, hera::ws::AuctionOracleKDTreePureGeom<Real>, hera::ws::dnn::DynamicPointVector<Real>>;
+
+
+inline double wasserstein_cost(const DynamicPointVector<double>& set_A, const DynamicPointVector<double>& set_B, const AuctionParams<double>& params)
+{
+ if (params.wasserstein_power < 1.0) {
+ throw std::runtime_error("Bad q in Wasserstein " + std::to_string(params.wasserstein_power));
+ }
+
+ if (params.delta < 0.0) {
+ throw std::runtime_error("Bad delta in Wasserstein " + std::to_string(params.delta));
+ }
+
+ if (params.initial_epsilon < 0.0) {
+ throw std::runtime_error("Bad initial epsilon in Wasserstein" + std::to_string(params.initial_epsilon));
+ }
+
+ if (params.epsilon_common_ratio < 0.0) {
+ throw std::runtime_error("Bad epsilon factor in Wasserstein " + std::to_string(params.epsilon_common_ratio));
+ }
+
+ if (set_A.size() != set_B.size()) {
+ throw std::runtime_error("Different cardinalities of point clouds: " + std::to_string(set_A.size()) + " != " + std::to_string(set_B.size()));
+ }
+
+ DynamicTraits<double> traits(params.dim);
+
+ DynamicPointVector<double> set_A_copy(set_A);
+ DynamicPointVector<double> set_B_copy(set_B);
+
+ // set point id to the index in vector
+ for(size_t i = 0; i < set_A.size(); ++i) {
+ traits.id(set_A_copy[i]) = i;
+ traits.id(set_B_copy[i]) = i;
+ }
+
+ if (params.max_bids_per_round == 1) {
+ hera::ws::AuctionRunnerGSR<double> auction(set_A_copy, set_B_copy, params);
+ auction.run_auction();
+ return auction.get_wasserstein_cost();
+ } else {
+ hera::ws::AuctionRunnerJacR<double> auction(set_A_copy, set_B_copy, params);
+ auction.run_auction();
+ return auction.get_wasserstein_cost();
+ }
+}
+
+inline double wasserstein_dist(const DynamicPointVector<double>& set_A, const DynamicPointVector<double>& set_B, const AuctionParams<double>& params)
+{
+ return std::pow(wasserstein_cost(set_A, set_B, params), 1.0 / params.wasserstein_power);
+}
+
+} // ws
+} // hera
+
+
+#endif
diff --git a/wasserstein/tests/data/test_100_A b/wasserstein/tests/data/test_100_A
new file mode 100644
index 0000000..8d126f0
--- /dev/null
+++ b/wasserstein/tests/data/test_100_A
@@ -0,0 +1,100 @@
+7.50638 7.78005
+0.991758 2.12178
+5.18481 6.61702
+6.14703 7.08581
+4.09936 4.83024
+3.79915 4.51283
+3.17645 3.75321
+0.61305 0.998622
+0.445643 1.13781
+6.38205 6.53669
+5.96392 6.44093
+7.21047 7.26005
+0.6703 1.26593
+0.529933 1.7027
+7.92495 8.83023
+2.1382 2.71695
+3.79209 4.5197
+5.23354 5.82214
+-0.395097 2.18831
+3.22028 3.88648
+5.56262 5.79949
+8.39623 9.37185
+2.7452 3.84539
+9.5022 10.2414
+1.01374 1.40504
+3.2029 3.89559
+7.61236 8.28485
+6.4371 6.909
+4.45616 5.35067
+1.57802 1.77895
+6.5991 7.76339
+6.66729 6.71714
+6.11898 6.57121
+2.60663 4.36396
+-0.259613 1.17683
+7.72857 9.48862
+4.68398 5.51521
+4.87447 5.4233
+6.86301 6.88244
+4.17814 4.25886
+8.70558 9.72902
+4.40873 4.57389
+6.1824 7.05049
+7.97557 8.79739
+8.52591 8.6985
+5.15336 5.27796
+9.70144 9.77031
+0.561778 1.39045
+9.32553 10.2456
+7.01495 7.74521
+6.83355 7.28255
+1.96721 3.01504
+5.78411 7.59464
+5.64012 6.10721
+3.7249 5.17086
+4.33297 5.91657
+7.11793 7.2545
+5.109 6.76878
+3.02787 3.04077
+0.999365 2.05566
+8.81392 8.9086
+6.20106 6.78943
+6.7987 7.05794
+0.438805 0.449602
+8.71793 9.79853
+-0.150282 0.51997
+5.72257 5.93156
+5.71098 6.09535
+9.0378 9.45942
+0.534987 0.872885
+7.72276 8.57754
+9.26069 9.40289
+4.148 4.80519
+1.04579 3.18109
+0.259767 0.93215
+0.250608 0.511569
+4.88108 5.62239
+4.6731 5.3348
+7.84979 7.93545
+0.912521 1.48142
+4.82553 5.38108
+6.02179 7.61665
+3.85848 6.39418
+5.10754 6.02118
+1.71956 1.86238
+6.47336 6.74034
+-0.0371018 0.212738
+3.97259 4.15465
+2.17413 3.20188
+4.49098 6.09812
+6.62445 7.84196
+6.57541 7.432
+6.81052 9.6653
+3.67502 4.69734
+3.92378 4.14743
+5.93127 6.46154
+0.63424 0.705454
+7.60129 9.23263
+4.23064 4.74575
+0.397705 1.24458
diff --git a/wasserstein/tests/data/test_100_A.pd.dipha b/wasserstein/tests/data/test_100_A.pd.dipha
new file mode 100644
index 0000000..e94f5fe
--- /dev/null
+++ b/wasserstein/tests/data/test_100_A.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_100_B b/wasserstein/tests/data/test_100_B
new file mode 100644
index 0000000..852799d
--- /dev/null
+++ b/wasserstein/tests/data/test_100_B
@@ -0,0 +1,100 @@
+5.8232 6.36308
+2.16066 2.48668
+2.38754 4.91418
+4.77403 5.43982
+0.291412 1.11147
+3.77337 5.2686
+8.31344 9.05384
+0.734064 1.14844
+7.57606 7.8521
+3.16719 3.86953
+2.55072 2.64932
+9.51707 9.6071
+0.304643 2.41784
+2.79925 3.28234
+5.32901 7.7576
+5.19903 6.30449
+1.87819 2.99454
+8.92272 9.67105
+4.62414 5.05592
+4.0079 4.64148
+2.26369 3.44573
+2.69335 3.13426
+1.90706 2.42652
+2.68113 2.79133
+1.41065 1.56018
+6.55282 7.18725
+5.72986 6.37151
+7.26968 8.22623
+3.32643 3.73606
+3.77325 4.63115
+1.05457 1.83651
+8.6815 8.85251
+3.91285 4.17139
+0.380936 0.842109
+7.33227 7.69334
+8.45635 8.923
+4.1769 5.08373
+0.501374 2.23328
+-0.161782 1.28908
+3.44716 3.4662
+3.15394 4.30243
+8.71416 9.3781
+6.3034 8.62893
+6.53824 7.04611
+0.6386 1.35269
+0.862088 0.960371
+5.12963 5.20203
+1.58695 2.0452
+6.57698 6.63228
+3.87747 4.45669
+1.51273 3.25669
+-0.0992804 0.667302
+4.7489 4.80059
+0.0280559 1.90471
+6.7462 8.27612
+0.915652 1.30007
+2.79556 3.77404
+9.87989 10.0722
+9.39105 9.84229
+7.57235 9.37122
+5.09426 6.44266
+6.3994 6.72037
+5.73441 6.99341
+6.9079 7.88049
+4.2003 4.41933
+-1.72447 2.25877
+9.04907 9.64323
+4.40473 5.3593
+9.31201 9.96079
+7.28343 8.74163
+3.0172 6.23779
+8.08422 8.56069
+6.83038 6.99863
+2.32038 3.1289
+7.42302 8.26286
+6.66905 7.18496
+0.730748 1.61335
+4.00564 5.73993
+2.81231 3.67489
+2.33178 2.37845
+9.03302 9.68681
+0.567816 0.755485
+7.89783 8.7621
+0.177662 0.332833
+-0.181569 1.36821
+6.22158 6.55787
+4.67115 5.16995
+0.806432 0.820738
+7.69636 7.87402
+4.40933 4.54995
+9.1329 9.15037
+8.87416 9.04329
+1.14349 1.8993
+3.29756 4.7172
+6.67873 8.31364
+6.91238 7.1654
+0.483084 1.55006
+2.66058 3.86294
+5.93347 6.06085
+7.40514 9.05071
diff --git a/wasserstein/tests/data/test_100_B.pd.dipha b/wasserstein/tests/data/test_100_B.pd.dipha
new file mode 100644
index 0000000..25d6734
--- /dev/null
+++ b/wasserstein/tests/data/test_100_B.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_200_A b/wasserstein/tests/data/test_200_A
new file mode 100644
index 0000000..164b71d
--- /dev/null
+++ b/wasserstein/tests/data/test_200_A
@@ -0,0 +1,200 @@
+0.471299 1.89241
+2.82136 3.97846
+8.81923 9.20678
+1.42474 1.65425
+8.36963 9.16097
+-0.236476 0.692489
+7.57182 8.06148
+2.89878 3.21958
+7.1285 7.51707
+5.75496 7.09461
+6.00081 6.10914
+9.60869 9.64676
+7.42889 8.97174
+7.26061 8.55944
+2.41226 2.5146
+8.5616 9.44847
+7.4946 8.86962
+5.42244 6.98028
+9.62386 9.96039
+7.70591 9.92849
+1.34119 3.2048
+3.92169 5.15228
+8.82955 9.60318
+7.94213 9.39997
+2.6716 4.02057
+0.375206 0.497663
+1.94572 3.65599
+1.03366 1.46356
+8.91855 10.1838
+7.11087 8.64425
+2.63266 2.78706
+8.93611 10.2943
+8.51999 9.28356
+1.31436 3.13725
+1.92871 4.00178
+8.30503 8.45555
+2.58739 2.82076
+3.20419 5.29453
+7.4015 8.13225
+9.07991 9.74729
+0.822366 0.938371
+2.90508 4.29367
+4.32385 5.4787
+3.63054 4.6918
+8.52962 9.87004
+1.16994 2.39465
+2.61903 3.33772
+4.15505 4.52942
+8.7068 9.66579
+8.10373 9.31351
+0.7954 1.23001
+7.82253 8.69505
+4.59616 5.91996
+1.02032 1.93931
+6.98421 8.46017
+8.42263 11.3447
+2.63444 3.7158
+7.49059 9.1137
+-0.122109 1.41074
+8.29578 8.81161
+6.24793 6.32368
+4.07212 4.39695
+5.32453 7.457
+8.3892 9.82048
+4.35981 4.78063
+5.49932 6.08321
+1.0107 1.53369
+2.48759 2.94139
+4.24977 5.52034
+1.93104 3.35207
+-0.733247 1.22412
+-0.354283 2.36812
+6.34728 6.44213
+5.98172 7.8753
+5.47963 6.82986
+6.01986 6.6588
+4.62793 5.22134
+7.73923 8.29761
+8.85565 9.51494
+5.55307 6.15804
+6.30963 7.17248
+9.4775 10.2636
+7.45333 7.74006
+1.79317 2.33273
+7.73056 8.44999
+3.94172 5.02778
+8.36177 9.85172
+5.91765 8.12935
+7.95436 8.97583
+5.06238 5.37907
+4.56153 4.97175
+9.47572 9.65038
+9.54745 9.922
+7.82271 8.66299
+4.19056 4.75156
+4.15657 5.72352
+0.213845 0.312444
+2.30944 2.6806
+2.42391 3.41888
+6.00512 6.88274
+6.64546 7.61145
+-0.204229 2.78228
+-0.417104 0.667252
+8.18696 8.67785
+9.27818 9.67924
+-0.0174685 0.21355
+5.91137 6.39606
+9.49268 10.1457
+2.11362 4.36526
+6.51084 7.82167
+6.07066 6.44843
+-0.653518 1.08588
+7.46736 7.87137
+5.26045 7.92188
+6.4171 6.8133
+6.73709 7.70383
+3.46451 4.23679
+0.122365 0.809853
+7.98627 8.0505
+1.71192 2.63047
+1.20624 2.12087
+4.6812 5.51566
+2.62672 2.67648
+4.203 5.1052
+5.26482 6.5186
+3.68166 3.74701
+2.72011 3.98338
+3.41652 3.71477
+2.26211 2.90374
+0.930209 1.43211
+1.98603 3.36662
+4.55838 5.9933
+5.66292 6.59838
+3.12432 3.87457
+6.54384 8.38959
+0.205059 0.331022
+8.70617 9.34121
+7.02182 7.38679
+2.36908 2.84197
+9.13221 9.76563
+7.50113 9.49245
+8.15671 8.45093
+1.9517 2.20923
+3.23368 3.43695
+2.97273 4.10133
+7.36338 8.96733
+4.77525 5.18347
+9.47774 10.3537
+1.75218 1.97051
+5.42544 6.18939
+9.75801 10.0151
+6.31285 6.38327
+8.43389 8.721
+7.6108 7.81113
+8.72029 10.3153
+5.18655 7.1101
+7.96243 8.43151
+0.798103 0.860125
+1.1289 2.77549
+5.91084 6.03085
+4.95884 5.46913
+5.88125 6.49667
+7.9394 8.9545
+5.07492 5.55063
+5.92251 6.08548
+3.88602 5.41487
+1.40122 2.15276
+8.74244 8.83223
+4.75577 6.60338
+0.921272 1.44873
+3.77361 3.90348
+8.8999 9.8518
+3.11077 4.85674
+8.56185 10.6345
+8.76335 9.00169
+6.8734 8.60197
+4.54408 4.93892
+5.57849 6.31727
+7.95161 8.30843
+1.55798 2.4957
+3.86082 3.97131
+6.45433 7.17065
+0.96021 2.32897
+6.84576 6.89531
+8.59095 8.70199
+3.57754 4.26457
+5.27979 5.74385
+2.06602 2.90525
+3.0856 4.18179
+2.76214 3.9982
+2.11943 5.4285
+3.1197 3.24389
+0.495798 1.23632
+3.18253 3.99433
+7.02072 8.37949
+2.77905 3.42643
+1.57093 2.30655
+7.10979 7.14006
+6.20994 6.72092
+8.15136 8.33899
diff --git a/wasserstein/tests/data/test_200_B b/wasserstein/tests/data/test_200_B
new file mode 100644
index 0000000..761943d
--- /dev/null
+++ b/wasserstein/tests/data/test_200_B
@@ -0,0 +1,200 @@
+1.17434 1.46837
+2.58198 4.16589
+0.234041 0.968658
+1.52703 1.59579
+6.7103 7.44033
+3.19227 4.41539
+5.42556 5.57369
+3.45417 4.86089
+3.82256 4.1092
+7.82551 7.90784
+3.9384 4.71796
+5.60335 5.9054
+7.96663 9.8987
+6.30305 6.64853
+7.33246 10.5316
+0.623312 1.09008
+2.63041 2.64616
+5.36028 6.28956
+4.64202 5.91858
+7.55219 7.96304
+7.73736 9.18221
+1.67114 1.84851
+5.07514 5.12159
+7.03732 7.05228
+7.5006 7.59212
+0.244947 1.55875
+0.0170454 1.10485
+1.95394 3.53669
+5.66015 6.01949
+5.88211 7.64639
+7.46698 9.27085
+6.37429 7.10154
+4.54535 4.81932
+8.21203 9.35896
+4.89933 6.20802
+3.68683 4.17831
+0.477467 0.828394
+6.17871 6.77834
+9.77523 9.92676
+0.854808 2.38709
+7.93326 8.3553
+2.10917 2.27771
+4.07045 4.72793
+8.2016 8.8011
+2.9205 3.95746
+2.89806 4.39725
+5.5654 5.78669
+9.5219 9.98543
+7.08591 7.19588
+8.35359 9.57893
+9.81348 10.0345
+8.5994 9.71835
+5.43903 7.25234
+1.82768 2.92724
+4.44952 6.79754
+5.66747 7.34386
+5.88153 6.39253
+3.34008 4.22032
+2.46068 2.76051
+0.370778 2.61681
+6.02508 6.26809
+4.32654 4.93262
+7.41536 7.99616
+8.84229 9.87911
+3.8551 5.84353
+1.56832 2.34694
+6.96099 7.42028
+8.15753 8.72014
+9.23141 10.3815
+7.4484 7.80228
+0.473671 0.874895
+3.15689 3.50687
+3.58122 4.09945
+3.55022 3.74767
+4.42708 5.80211
+4.40956 4.68699
+3.80576 4.61856
+7.29965 8.28614
+7.40582 8.15308
+1.69789 1.77669
+1.66419 3.44308
+0.473997 0.872506
+7.83959 8.52898
+6.22416 6.36949
+-0.187159 0.871822
+0.232336 0.585965
+9.29905 9.44357
+1.4459 2.40589
+2.83008 3.19758
+1.15291 2.12112
+2.58686 3.33896
+6.79362 7.88068
+0.228178 1.48318
+5.60001 6.20258
+4.97803 7.10992
+1.70429 1.962
+2.72659 3.13886
+9.22714 9.25889
+3.84694 3.88778
+-0.282077 1.48155
+9.28756 9.58517
+4.34069 5.59751
+8.63909 8.76839
+8.86236 10.7642
+6.77597 8.41888
+7.30621 8.64164
+0.685607 1.22755
+2.91514 3.22638
+2.72098 3.66837
+8.17528 8.32638
+5.19632 5.7506
+7.34177 8.70639
+5.74082 6.35524
+5.95975 6.69284
+9.40187 10.4488
+2.92761 3.36735
+0.399531 3.13082
+4.83399 4.92635
+7.74539 8.56852
+1.76322 3.5086
+6.54479 6.72963
+7.64362 8.12404
+1.35542 1.45313
+0.214385 0.718085
+1.7006 3.21962
+5.91009 6.47862
+2.21093 2.34636
+5.96919 6.79365
+6.59951 8.22203
+1.54571 1.59397
+3.27012 3.79128
+0.32455 0.622995
+1.73926 2.78017
+9.81035 9.84077
+7.38441 7.85171
+8.90372 9.34186
+7.26323 8.41174
+5.7363 5.97348
+8.25473 10.1281
+2.3981 2.52096
+8.53783 9.63442
+8.51755 9.2735
+6.48614 6.773
+3.40182 3.65137
+2.1353 3.04852
+2.95397 3.73285
+6.98063 7.4963
+4.50189 5.26384
+0.21416 1.49363
+0.632196 1.36307
+6.57833 6.60481
+8.0634 9.33903
+2.79759 2.94462
+4.43747 4.58861
+6.48733 6.86569
+2.28008 3.47037
+6.87452 7.77431
+-0.156821 2.71557
+0.72595 1.78862
+1.97586 2.38196
+8.61839 9.1468
+4.55496 5.68986
+0.26923 1.15728
+9.63757 9.7236
+1.39497 1.96698
+4.8643 5.04172
+6.64675 7.66435
+2.56256 2.6015
+-0.381989 0.611211
+0.676336 1.26896
+8.95304 9.03243
+5.62058 6.07997
+3.36522 4.04276
+8.64868 10.5024
+4.75813 5.19834
+1.96608 2.05864
+9.01449 9.10397
+3.72786 4.51921
+5.6938 6.96584
+1.73499 2.9314
+2.73099 3.41409
+8.77171 9.07665
+4.63865 4.67649
+8.6698 9.30782
+-0.168259 2.09581
+9.29672 9.56
+0.372544 2.60567
+0.450487 1.32919
+6.95341 7.6399
+3.4403 5.24993
+5.53469 6.97831
+-0.79664 1.21306
+5.68831 6.14413
+8.85601 8.95444
+3.83309 5.211
+5.51573 6.5114
+3.64009 3.99648
+4.40759 4.99283
+1.85198 2.6457
+2.72645 3.74803
diff --git a/wasserstein/tests/data/test_5000_A b/wasserstein/tests/data/test_5000_A
new file mode 100644
index 0000000..094c6e0
--- /dev/null
+++ b/wasserstein/tests/data/test_5000_A
@@ -0,0 +1,5000 @@
+0.471299 1.89241
+2.82136 3.97846
+8.81923 9.20678
+1.42474 1.65425
+8.36963 9.16097
+-0.236476 0.692489
+7.57182 8.06148
+2.89878 3.21958
+7.1285 7.51707
+5.75496 7.09461
+6.00081 6.10914
+9.60869 9.64676
+7.42889 8.97174
+7.26061 8.55944
+2.41226 2.5146
+8.5616 9.44847
+7.4946 8.86962
+5.42244 6.98028
+9.62386 9.96039
+7.70591 9.92849
+1.34119 3.2048
+3.92169 5.15228
+8.82955 9.60318
+7.94213 9.39997
+2.6716 4.02057
+0.375206 0.497663
+1.94572 3.65599
+1.03366 1.46356
+8.91855 10.1838
+7.11087 8.64425
+2.63266 2.78706
+8.93611 10.2943
+8.51999 9.28356
+1.31436 3.13725
+1.92871 4.00178
+8.30503 8.45555
+2.58739 2.82076
+3.20419 5.29453
+7.4015 8.13225
+9.07991 9.74729
+0.822366 0.938371
+2.90508 4.29367
+4.32385 5.4787
+3.63054 4.6918
+8.52962 9.87004
+1.16994 2.39465
+2.61903 3.33772
+4.15505 4.52942
+8.7068 9.66579
+8.10373 9.31351
+0.7954 1.23001
+7.82253 8.69505
+4.59616 5.91996
+1.02032 1.93931
+6.98421 8.46017
+8.42263 11.3447
+2.63444 3.7158
+7.49059 9.1137
+-0.122109 1.41074
+8.29578 8.81161
+6.24793 6.32368
+4.07212 4.39695
+5.32453 7.457
+8.3892 9.82048
+4.35981 4.78063
+5.49932 6.08321
+1.0107 1.53369
+2.48759 2.94139
+4.24977 5.52034
+1.93104 3.35207
+-0.733247 1.22412
+-0.354283 2.36812
+6.34728 6.44213
+5.98172 7.8753
+5.47963 6.82986
+6.01986 6.6588
+4.62793 5.22134
+7.73923 8.29761
+8.85565 9.51494
+5.55307 6.15804
+6.30963 7.17248
+9.4775 10.2636
+7.45333 7.74006
+1.79317 2.33273
+7.73056 8.44999
+3.94172 5.02778
+8.36177 9.85172
+5.91765 8.12935
+7.95436 8.97583
+5.06238 5.37907
+4.56153 4.97175
+9.47572 9.65038
+9.54745 9.922
+7.82271 8.66299
+4.19056 4.75156
+4.15657 5.72352
+0.213845 0.312444
+2.30944 2.6806
+2.42391 3.41888
+6.00512 6.88274
+6.64546 7.61145
+-0.204229 2.78228
+-0.417104 0.667252
+8.18696 8.67785
+9.27818 9.67924
+-0.0174685 0.21355
+5.91137 6.39606
+9.49268 10.1457
+2.11362 4.36526
+6.51084 7.82167
+6.07066 6.44843
+-0.653518 1.08588
+7.46736 7.87137
+5.26045 7.92188
+6.4171 6.8133
+6.73709 7.70383
+3.46451 4.23679
+0.122365 0.809853
+7.98627 8.0505
+1.71192 2.63047
+1.20624 2.12087
+4.6812 5.51566
+2.62672 2.67648
+4.203 5.1052
+5.26482 6.5186
+3.68166 3.74701
+2.72011 3.98338
+3.41652 3.71477
+2.26211 2.90374
+0.930209 1.43211
+1.98603 3.36662
+4.55838 5.9933
+5.66292 6.59838
+3.12432 3.87457
+6.54384 8.38959
+0.205059 0.331022
+8.70617 9.34121
+7.02182 7.38679
+2.36908 2.84197
+9.13221 9.76563
+7.50113 9.49245
+8.15671 8.45093
+1.9517 2.20923
+3.23368 3.43695
+2.97273 4.10133
+7.36338 8.96733
+4.77525 5.18347
+9.47774 10.3537
+1.75218 1.97051
+5.42544 6.18939
+9.75801 10.0151
+6.31285 6.38327
+8.43389 8.721
+7.6108 7.81113
+8.72029 10.3153
+5.18655 7.1101
+7.96243 8.43151
+0.798103 0.860125
+1.1289 2.77549
+5.91084 6.03085
+4.95884 5.46913
+5.88125 6.49667
+7.9394 8.9545
+5.07492 5.55063
+5.92251 6.08548
+3.88602 5.41487
+1.40122 2.15276
+8.74244 8.83223
+4.75577 6.60338
+0.921272 1.44873
+3.77361 3.90348
+8.8999 9.8518
+3.11077 4.85674
+8.56185 10.6345
+8.76335 9.00169
+6.8734 8.60197
+4.54408 4.93892
+5.57849 6.31727
+7.95161 8.30843
+1.55798 2.4957
+3.86082 3.97131
+6.45433 7.17065
+0.96021 2.32897
+6.84576 6.89531
+8.59095 8.70199
+3.57754 4.26457
+5.27979 5.74385
+2.06602 2.90525
+3.0856 4.18179
+2.76214 3.9982
+2.11943 5.4285
+3.1197 3.24389
+0.495798 1.23632
+3.18253 3.99433
+7.02072 8.37949
+2.77905 3.42643
+1.57093 2.30655
+7.10979 7.14006
+6.20994 6.72092
+8.15136 8.33899
+0.903753 1.57921
+0.380744 1.88053
+1.3164 1.79885
+0.199366 0.576639
+5.53683 6.49433
+8.8705 9.14396
+3.1401 3.98761
+4.82675 6.69396
+7.28593 8.08916
+8.11312 9.92914
+3.25737 3.42109
+2.58413 4.57223
+2.65202 2.77196
+-0.31616 1.51568
+4.1621 5.29563
+4.49155 5.21037
+7.28481 7.31722
+9.70568 10.0406
+2.39057 2.85874
+2.30626 3.16244
+1.15896 2.09616
+5.91343 7.33024
+-0.172181 0.177363
+5.08934 6.10928
+7.15508 7.55315
+4.43036 4.68093
+6.00772 6.49566
+7.9247 8.43809
+1.57028 2.52328
+3.45458 4.43692
+3.18257 4.83824
+1.48243 1.91225
+2.59025 2.99596
+6.93059 8.34359
+4.53752 7.51216
+6.42857 6.51513
+5.5663 6.13877
+7.54367 7.56485
+9.01229 9.19913
+2.84158 3.23347
+0.42959 0.620618
+8.77033 9.33787
+8.06103 8.30989
+6.48425 7.83668
+4.66949 6.00205
+4.46683 4.66247
+8.96738 9.07714
+0.463093 0.514808
+7.72986 9.44537
+6.31391 6.8289
+0.883295 1.70946
+3.73278 3.98015
+6.73453 6.92514
+3.58434 4.43262
+0.236286 1.4601
+2.00505 2.38684
+3.845 4.20708
+1.18852 3.04911
+0.766784 1.00641
+7.38781 8.11216
+8.9396 9.27589
+0.369822 1.53322
+8.76527 9.23987
+0.663408 0.803445
+9.69209 10.1455
+9.73379 10.234
+3.47602 4.89968
+4.12754 5.45249
+7.31984 8.57369
+0.989101 1.47678
+5.57662 5.83292
+4.99092 6.85044
+4.35272 4.3683
+0.0517815 1.92227
+7.2694 7.80634
+1.35565 1.42783
+8.5638 8.91707
+1.74557 2.74123
+2.18226 2.19664
+-0.901334 1.32691
+0.866613 1.03788
+5.30895 6.31774
+7.70178 8.5675
+4.06894 4.16071
+2.59697 3.53162
+4.30201 5.34212
+4.08762 4.19091
+-0.516192 0.848397
+9.85911 10.1066
+0.472991 1.40069
+6.26012 7.0054
+0.707801 2.15445
+1.73825 1.87193
+0.206301 0.831746
+7.77872 7.92715
+4.94477 5.60361
+3.86216 5.16839
+1.35166 1.54482
+2.91721 3.56193
+4.57242 4.75913
+7.09303 8.29678
+8.18431 8.92151
+6.80303 10.87
+1.29208 1.72027
+1.22224 1.31693
+5.26756 6.26459
+2.55221 3.94397
+6.58902 6.78354
+7.85917 8.89791
+6.59279 7.63115
+4.45787 7.26828
+3.48759 5.33991
+2.13838 3.86589
+1.53368 3.57313
+1.41722 3.19336
+3.48388 4.11958
+1.53756 2.98451
+7.29083 8.22109
+1.2713 2.16915
+6.94685 7.31029
+6.2494 7.04676
+3.00376 3.02028
+1.25232 1.43301
+1.50413 2.25
+2.89098 4.77198
+4.50766 5.89294
+5.5403 6.07893
+-0.101858 0.409209
+3.87963 6.1053
+-0.19564 1.46589
+-0.342077 0.694623
+6.63875 7.42223
+7.89982 9.05857
+4.91121 5.48031
+5.90743 8.35815
+7.13881 8.21597
+4.11493 5.08147
+3.59673 3.77176
+8.08236 8.3237
+1.35842 1.48934
+5.42963 5.85906
+4.60778 4.9734
+-0.607198 0.91225
+5.40263 5.7017
+5.08624 5.63236
+7.34529 9.02233
+7.30013 8.12907
+6.56106 6.75585
+6.82576 7.25434
+2.96037 3.56454
+3.60283 4.09137
+6.35408 6.71888
+-0.688103 0.84579
+8.45128 8.69771
+6.31749 7.3294
+5.82223 6.04761
+1.72983 2.38205
+6.94974 7.76985
+9.681 10.0141
+8.65394 9.2456
+2.52904 3.39548
+6.66609 7.35785
+4.18963 4.5473
+3.58643 3.80513
+2.88796 3.82413
+0.992066 1.1477
+4.57942 5.15419
+3.02826 4.32268
+5.91565 6.82087
+4.13694 5.13393
+6.28717 6.53257
+1.3149 2.36944
+0.488974 0.981461
+4.32763 4.98272
+-0.420836 0.63619
+7.13406 7.31362
+0.367782 1.91138
+6.14763 6.16713
+0.837933 1.92794
+9.3781 10.0609
+3.22887 5.44584
+5.91554 6.65974
+5.68608 6.02435
+7.99715 8.55953
+5.37106 5.38574
+0.254544 0.374268
+0.184701 0.917061
+9.38005 9.54042
+6.86741 7.35628
+0.87398 1.69093
+7.75845 8.53773
+0.370425 1.35335
+0.699837 0.810893
+3.73223 4.32089
+3.81804 3.85752
+4.85936 5.10097
+2.70381 3.10519
+3.82523 5.27699
+9.13422 10.3317
+4.62775 4.77988
+7.91139 7.95504
+2.72614 4.79958
+0.863357 1.88643
+4.14155 5.02327
+2.49683 4.11585
+1.06741 1.11516
+6.20979 8.38443
+0.936362 2.46703
+6.58231 7.85063
+1.89469 2.31422
+8.70668 9.14006
+5.76486 6.1122
+3.15778 3.76679
+0.248282 2.19881
+1.25317 1.92694
+7.81837 9.53067
+-0.582906 0.818904
+8.34194 8.37845
+4.4913 5.10164
+3.86376 5.5453
+6.94054 7.68699
+2.07462 2.5811
+0.518698 2.1529
+3.51773 4.60946
+8.39915 8.98446
+1.63685 2.19755
+6.60737 9.05917
+2.06667 3.23994
+3.18822 3.31219
+2.44332 3.22088
+4.755 4.87118
+4.34245 4.91565
+4.64562 4.8104
+2.73282 3.35646
+9.48057 9.86441
+0.640899 1.03356
+0.789475 0.925731
+1.4247 1.58347
+1.47747 2.25408
+8.8612 9.81597
+8.44147 10.6885
+9.07046 10.0877
+0.350125 1.15765
+4.45375 5.73964
+4.06526 4.26457
+7.50776 8.23491
+1.55452 1.63786
+2.8399 4.52559
+1.34319 1.47951
+5.21572 5.65702
+5.85695 6.75574
+8.21826 10.657
+-0.0479956 1.79162
+1.72905 1.78113
+3.35685 4.03797
+3.7123 5.82296
+8.56751 10.2992
+4.07987 4.25273
+5.8347 6.07253
+3.25283 3.99065
+9.31995 10.3647
+0.649025 1.14496
+1.06966 2.04182
+7.59831 7.85826
+3.35263 3.84374
+4.91371 5.10148
+8.0875 9.23421
+3.00484 5.14282
+8.60448 9.09442
+5.61429 6.24037
+3.4729 4.17907
+7.18702 7.26274
+0.729966 0.928899
+2.27264 2.81241
+2.67248 3.91661
+3.98443 4.64406
+5.50463 6.92435
+-0.257961 0.905736
+5.71363 6.67387
+4.12643 4.66467
+3.97623 4.64917
+9.71227 9.8243
+8.66674 8.97634
+7.94673 8.73904
+7.45228 8.14466
+3.78405 4.81189
+4.05505 5.00011
+2.84957 3.15451
+6.93785 7.58172
+1.85006 1.96814
+6.82256 7.00166
+2.42727 2.68161
+8.06129 8.76308
+1.53758 3.67482
+2.5057 4.18495
+7.09618 7.79664
+1.12843 1.46228
+1.61447 2.2668
+5.58639 5.70776
+8.15398 8.34959
+2.49733 2.57643
+5.18817 5.32462
+5.62963 5.86377
+1.95215 2.26641
+7.22129 7.23255
+5.99833 6.18639
+6.20875 7.13868
+6.814 7.6597
+7.41314 9.49798
+5.48819 6.31634
+4.81318 5.08156
+9.15434 9.42787
+4.83201 5.43295
+1.44477 2.6455
+8.8907 10.4727
+3.19487 3.21255
+1.47291 3.13113
+4.14796 5.10058
+5.85016 8.41212
+7.58183 8.53659
+9.5978 10.2877
+1.5954 2.58394
+2.65561 4.0975
+-0.157024 0.16627
+7.04379 7.75368
+2.39896 2.7728
+2.42376 3.58085
+0.158653 0.857045
+7.82101 9.01833
+6.80499 7.35261
+6.62833 6.66255
+4.90229 5.45681
+8.50205 8.69236
+2.01845 2.06924
+8.2503 9.04222
+4.58265 5.52758
+8.6176 9.74887
+1.28468 1.77019
+5.40424 6.20705
+0.943905 1.98023
+4.2702 4.41287
+3.89454 4.4814
+0.585132 1.56351
+9.45354 10.5374
+3.7501 5.07553
+7.53248 8.14004
+4.60026 4.78921
+1.61073 4.22368
+6.22591 7.40966
+0.57866 1.0522
+5.877 6.55882
+3.54573 3.7731
+7.64294 7.66103
+8.2399 9.14032
+0.307808 0.571367
+7.89791 9.25734
+5.2852 5.84332
+0.45713 2.42223
+7.73426 8.48158
+8.0058 9.46405
+8.03189 8.41868
+1.54624 1.98914
+7.24167 7.27699
+8.61226 8.83199
+5.38365 6.52599
+0.827018 1.51428
+7.19285 7.48372
+-0.0969552 2.16007
+4.08084 6.32563
+9.16026 10.2604
+0.206147 0.717435
+4.00643 4.8093
+2.16139 3.14759
+1.73359 3.13485
+9.1103 9.36052
+7.05621 7.43901
+4.83509 6.07581
+5.67164 7.89488
+7.93353 8.18454
+2.59566 3.1842
+3.62521 4.95121
+3.0297 3.18649
+1.08515 2.69289
+3.77063 5.7789
+0.106035 1.27409
+0.601099 2.13481
+6.98837 7.58833
+9.22955 9.79149
+1.6398 1.78726
+2.30423 3.34814
+2.3912 2.81842
+4.71724 6.16966
+5.13553 5.5016
+5.34117 5.45075
+9.32776 10.0676
+4.54244 5.29058
+4.01337 5.73188
+8.17427 8.39652
+1.96122 2.6921
+0.594267 1.00176
+-0.136973 0.977133
+6.41362 6.78056
+1.68388 2.39891
+9.50795 10.2315
+-0.262703 1.15557
+8.72229 9.683
+5.41821 5.67519
+4.93514 7.15867
+4.07046 4.26702
+-0.00866106 0.252353
+8.65877 10.1527
+2.10958 3.40353
+2.94947 3.43201
+6.32014 7.06279
+2.55034 2.89646
+3.87777 5.68044
+2.05325 3.00968
+5.11855 6.55784
+8.99618 9.22608
+3.36303 3.84902
+2.6234 3.70832
+7.35189 8.30856
+6.43777 7.28495
+5.33954 5.48055
+0.15999 0.391114
+3.4492 5.07088
+2.38503 2.42742
+3.88912 4.93246
+2.76303 4.54991
+6.56261 7.60381
+3.64198 3.72471
+1.70542 1.78806
+9.71115 9.88315
+0.471586 1.82377
+9.27611 10.5725
+0.486889 0.851587
+4.39234 5.10637
+9.54209 9.8955
+6.99602 7.42461
+2.98797 3.74623
+5.89424 6.4498
+9.63845 9.86333
+4.39828 5.18646
+2.30118 3.5758
+8.68128 9.56011
+9.00505 10.4304
+-0.22184 0.233296
+6.48492 7.60283
+1.54156 2.60693
+4.06808 6.39369
+5.52361 6.26241
+-0.698727 0.745524
+2.30742 2.41924
+0.655833 1.65752
+6.94733 7.81866
+7.83136 9.10651
+6.45284 7.1931
+6.09683 6.66159
+9.03299 9.4163
+1.86392 3.26189
+0.54863 2.07194
+0.364026 1.38376
+0.706954 1.0736
+-0.111015 0.584367
+1.54265 2.1413
+0.501172 0.57928
+2.09411 2.28902
+1.89894 4.09104
+8.72895 8.87045
+5.27709 5.72545
+0.164581 1.64188
+8.39203 8.73608
+8.21523 8.45002
+9.62006 10.1665
+4.79076 6.26442
+3.44189 3.68669
+8.93789 9.38343
+7.07036 7.64194
+8.34396 9.56445
+8.29992 8.64954
+5.82566 7.83287
+2.43008 3.4476
+1.81121 2.12203
+4.36108 4.3842
+6.28756 6.95939
+3.8698 5.79519
+0.644581 0.699162
+9.71982 10.2422
+4.86545 5.00544
+8.3808 9.29356
+1.34495 1.40972
+1.03641 2.01838
+8.55609 9.99958
+1.40813 3.46097
+3.20928 4.08838
+8.24345 9.11587
+1.27604 2.03462
+8.28298 8.46252
+2.20644 3.19585
+1.91396 2.30108
+4.2553 5.66006
+7.34925 8.38275
+6.28319 7.22199
+8.42171 9.62596
+1.12059 1.18262
+1.37555 1.84196
+4.39663 4.93639
+9.28044 9.58437
+5.47407 6.88593
+8.36529 8.49813
+9.40208 10.5922
+-0.451389 1.92404
+2.89431 3.19453
+6.51433 8.02158
+5.52163 6.06786
+7.63525 9.86457
+4.13898 5.05845
+0.136662 0.503748
+6.13492 6.74997
+8.37416 9.18971
+8.64164 8.82663
+0.941173 1.16158
+6.9073 8.26916
+8.37278 8.44326
+8.8951 9.20427
+8.40149 9.17577
+3.60361 4.57183
+8.67263 10.1127
+5.89716 6.45412
+1.97285 2.35593
+7.22973 8.13467
+9.55645 9.92529
+0.261578 0.836274
+9.04414 9.45485
+6.18043 6.54229
+8.88579 9.54087
+1.82613 2.93849
+5.7599 5.96366
+5.23105 5.5541
+0.425229 1.44436
+0.32065 2.60892
+7.83655 9.48786
+2.3168 3.45972
+2.35466 3.23342
+8.24494 8.27258
+7.32678 7.74264
+8.37275 10.0741
+4.17337 4.98348
+-0.162009 0.724431
+9.49757 9.76377
+8.69435 9.08089
+4.13841 4.7514
+7.26358 7.55514
+6.91912 6.93
+6.7883 7.18296
+-0.614315 1.1857
+6.05907 7.33557
+4.86704 4.87705
+8.50012 9.14836
+1.83683 3.09895
+6.16389 8.39248
+3.03556 4.41004
+4.72416 5.05782
+1.98183 3.19183
+2.77103 5.71501
+4.90002 4.9817
+0.269258 0.725628
+5.59551 7.05038
+2.95416 3.09633
+2.17662 3.18385
+6.67536 7.56762
+7.31678 7.39321
+3.84158 3.85359
+4.38203 5.10149
+0.816784 1.09918
+0.70131 0.739502
+0.276631 2.32633
+9.15839 9.49433
+0.721295 1.97673
+2.63875 2.75437
+5.00344 5.5645
+2.24555 2.81234
+7.74465 9.07646
+2.35244 4.90632
+0.812093 0.954419
+3.97904 5.2071
+4.19177 4.83646
+0.853012 1.331
+2.64112 3.25613
+0.0894716 1.61954
+3.39617 3.40859
+1.56906 2.28518
+2.37258 4.36515
+1.60997 1.7561
+5.15275 5.33281
+6.47824 7.47529
+2.51145 3.29949
+2.71094 2.77785
+8.84653 9.48398
+1.3246 1.66664
+7.43718 7.5546
+3.68985 4.24649
+4.50553 4.51669
+4.15617 4.54887
+8.55319 10.2136
+2.1448 3.55805
+4.64594 4.71505
+1.71763 1.99977
+4.98066 5.46709
+7.7779 8.36497
+-0.0604997 0.301294
+5.11873 7.32867
+4.94567 5.5986
+5.32645 6.26835
+2.5768 3.13511
+3.31604 3.87555
+1.60834 2.68762
+3.30552 3.85211
+4.26741 4.98636
+0.820475 1.18854
+7.91501 10.7203
+5.17391 5.30351
+4.00452 5.75141
+2.37722 3.4602
+2.2373 2.94837
+1.62462 3.48264
+7.98507 9.2566
+5.32504 5.56388
+0.760614 0.7802
+0.855659 1.01522
+3.11231 4.43223
+5.62821 6.21564
+4.96845 5.35921
+8.10559 9.11106
+1.02533 1.13103
+6.99976 7.0788
+1.87628 2.58801
+1.11023 2.24655
+5.23343 5.45086
+0.95875 2.25343
+7.45917 8.23614
+2.72245 3.04663
+8.66816 8.70698
+5.55734 7.12262
+1.01935 1.88271
+0.804417 1.76187
+7.82703 8.78426
+4.77321 6.15199
+2.91503 3.69352
+0.776735 1.08883
+5.19981 5.46442
+9.06483 10.4008
+7.72082 8.26398
+2.9854 3.26573
+0.584028 2.60443
+0.700994 1.10379
+5.47612 5.94502
+-0.318442 0.986786
+5.0704 5.08055
+3.83732 4.4826
+5.60843 6.59005
+8.81432 9.7851
+6.28792 6.65284
+1.16812 2.27701
+7.15234 9.66795
+9.02188 9.15339
+1.76112 2.04839
+7.49419 7.6204
+5.1765 5.497
+1.45855 1.94969
+1.35003 1.55822
+2.50453 2.86815
+7.10451 8.51352
+3.87727 4.1124
+1.84876 2.79351
+3.01661 4.05396
+-0.16814 0.366484
+-0.538895 0.608786
+7.59933 9.00744
+0.938648 2.38471
+5.76934 6.16572
+8.20416 8.62505
+8.64542 8.7264
+2.75784 2.7828
+0.794451 1.97817
+9.21331 10.5156
+8.46671 8.80572
+3.94814 5.16845
+6.73654 6.97397
+4.05301 4.93008
+6.37833 6.77985
+7.21161 8.15994
+3.74993 4.61029
+-0.127938 1.09853
+2.82957 4.28816
+6.50564 6.59445
+8.37926 8.48332
+0.757443 1.74585
+0.232438 0.972293
+6.99187 8.7098
+7.20368 8.44301
+4.4801 6.07501
+4.34015 6.1495
+2.19394 3.22334
+7.29817 8.41021
+1.16627 2.68901
+4.62423 5.08039
+0.955655 2.22882
+1.45862 3.07065
+1.69815 2.56291
+4.01179 4.36587
+7.135 7.75829
+6.6823 7.27765
+5.44745 5.67195
+4.94594 5.42067
+0.267772 0.301939
+0.676432 1.6296
+1.37335 1.91645
+1.89051 2.38631
+4.84386 6.30539
+8.95613 10.944
+2.18119 2.41821
+5.74901 6.16952
+7.5431 7.88071
+9.05278 9.8128
+0.201334 1.65323
+2.82787 3.82083
+3.07073 3.08475
+8.99671 10.1766
+5.43261 6.12137
+4.83693 4.86848
+6.31804 7.21544
+2.34491 3.2562
+6.05941 6.53725
+-0.483381 1.17347
+5.53777 5.72651
+3.28875 3.47472
+3.94609 4.9418
+7.45585 8.6871
+1.50066 2.57215
+8.10112 8.67954
+6.24737 6.42635
+0.64413 1.05759
+7.1741 8.21476
+0.502722 1.77462
+0.783663 1.74174
+9.52704 9.9109
+-0.473873 2.01013
+7.07946 7.11474
+0.857335 1.6501
+4.00225 4.84453
+5.40598 6.30573
+8.18802 8.30067
+9.00412 10.9588
+9.8362 10.1517
+7.62735 8.37572
+3.41477 4.63099
+2.51254 2.81559
+6.36702 6.56061
+5.11842 5.35515
+5.21873 5.73296
+5.73528 7.77276
+3.64993 4.66826
+7.12664 8.46553
+8.7257 9.16851
+1.27615 2.20376
+7.46188 8.20752
+2.64939 2.66373
+4.94147 6.0509
+6.3805 7.48841
+6.25197 7.12327
+0.0885331 1.2682
+4.97356 6.58488
+4.11917 4.27267
+9.08793 9.70385
+0.897277 1.31702
+6.87538 8.25544
+1.55565 1.59492
+2.62483 3.54274
+1.49631 2.92263
+9.45305 9.97728
+6.24087 6.4577
+3.94636 5.13669
+-0.000956745 1.08235
+1.46134 1.83767
+9.18517 10.6601
+-0.740186 1.81269
+5.81977 6.15818
+7.0529 7.99421
+6.17753 7.49749
+8.63091 9.04205
+9.65219 10.1558
+3.12839 4.99211
+2.97262 4.07384
+4.28605 4.33171
+4.15906 5.6805
+1.35165 1.50732
+0.524207 2.12307
+5.32468 7.01472
+3.16982 4.87893
+6.88786 8.34191
+3.81703 5.22335
+3.86772 4.37359
+8.19386 10.0705
+1.73155 3.16695
+4.31685 4.62261
+9.40618 9.89612
+4.41215 5.19659
+2.35595 2.63543
+7.88481 8.14203
+7.17062 10.3534
+9.41379 10.389
+7.99867 9.01239
+3.31382 4.04915
+5.39222 6.07657
+8.5187 8.65976
+9.30132 10.6131
+7.17351 7.93596
+4.80134 6.72724
+3.59756 4.65182
+1.08248 1.17479
+1.03124 1.06871
+6.43154 6.95098
+-0.102199 0.59801
+4.94795 5.18081
+6.39126 7.30258
+1.52738 2.04271
+1.80373 2.33093
+2.72251 3.01677
+0.296722 1.10844
+6.39104 6.51567
+8.70965 8.78714
+2.07858 4.41695
+1.91027 2.9718
+1.42944 2.01864
+1.96347 2.73397
+4.0701 4.22456
+4.02859 4.05107
+7.10977 7.98092
+8.21148 9.54287
+6.59231 7.65109
+0.144191 0.830665
+2.0192 2.23704
+8.03482 8.39591
+8.90473 9.98543
+2.18284 2.70166
+3.05569 3.54238
+8.35319 9.39539
+2.00803 2.42866
+2.35282 3.13763
+2.20155 2.79377
+1.76531 2.94892
+7.52749 7.72567
+3.02266 3.24778
+4.01741 4.22521
+9.75263 9.91571
+6.45502 6.67838
+2.24912 3.47262
+1.84372 2.26517
+4.09559 5.71188
+1.43811 2.33732
+3.89171 4.16905
+3.01506 3.9725
+0.0273168 1.51766
+5.04118 5.80507
+3.08517 4.17316
+8.81637 8.8332
+8.74055 9.50143
+2.36904 2.69008
+6.39733 6.44221
+8.53272 9.51114
+9.48423 9.55002
+8.65645 9.04872
+6.66352 7.48009
+5.64389 7.88656
+5.75301 6.6759
+3.28645 4.22757
+4.99482 5.82988
+3.00004 4.0273
+1.45249 1.56662
+4.96263 5.32195
+7.91351 8.1437
+1.02034 1.56249
+0.71376 1.73319
+0.709968 1.44651
+9.01414 9.54799
+4.02116 4.68005
+7.10903 7.27075
+7.21322 8.71031
+1.6644 2.27186
+3.71304 4.68764
+9.66257 10.1452
+5.34477 5.46136
+9.27722 10.583
+3.82328 4.83316
+4.77019 5.07928
+9.07112 9.23836
+6.99091 7.25634
+2.11871 2.3054
+7.88242 7.98572
+0.570809 0.714073
+8.51532 9.49151
+0.329247 2.48897
+4.78202 5.36476
+1.47969 2.78867
+6.75011 7.36769
+2.31162 2.39533
+3.50434 4.48026
+5.84603 6.28861
+7.5337 7.62538
+1.09955 2.85741
+6.09915 7.20381
+0.933825 2.37925
+0.576363 2.0182
+3.12126 3.22507
+2.85313 3.02656
+3.25724 3.92077
+5.48575 6.58011
+1.02824 1.65415
+8.68703 9.06219
+3.28389 3.86349
+5.80264 6.12775
+7.11846 7.47444
+1.29638 3.38601
+6.37908 7.05986
+-0.592438 0.854361
+0.39233 1.17768
+2.1497 3.94423
+2.42336 2.43441
+6.94806 8.30626
+0.79865 1.4173
+1.41455 1.43684
+0.240074 1.16712
+4.18593 5.9929
+6.161 6.564
+0.726091 1.90706
+0.375606 0.694866
+4.09349 4.26452
+2.01652 2.68038
+8.99301 9.90549
+8.93909 9.17673
+1.10427 2.01247
+9.12668 9.15282
+1.08098 1.55374
+0.377836 0.414809
+7.28611 8.86318
+8.3542 8.53251
+3.86353 4.12875
+6.7631 7.40068
+4.61679 4.78182
+2.12935 3.45492
+3.68233 4.0457
+6.68131 8.22111
+8.79197 8.80474
+1.8915 2.26287
+0.387586 3.073
+6.46798 7.57381
+7.79742 9.34526
+-1.21538 1.67303
+2.07845 2.66028
+3.14148 4.46647
+1.66789 2.73375
+8.49821 10.0574
+8.42537 8.89906
+0.618349 2.72887
+6.8229 7.54501
+6.99343 7.35322
+7.34223 8.68781
+3.18834 3.98274
+8.86908 10.2535
+3.39839 3.76171
+0.188168 0.392276
+1.68187 3.53401
+6.50423 6.71714
+7.61191 8.89715
+1.68463 2.09275
+5.94627 7.6003
+2.15865 3.24126
+7.93639 8.53826
+2.99626 3.43273
+7.71028 8.41172
+3.19472 4.60878
+8.36123 8.92549
+8.92975 9.02783
+2.87187 3.49672
+6.76949 7.71139
+8.09121 9.31151
+6.84199 7.44009
+0.730655 0.800873
+7.5208 7.54109
+6.75992 7.55017
+6.09818 6.17399
+0.639209 1.27283
+3.01917 3.22327
+1.69181 2.60614
+9.49245 9.5842
+-0.418034 1.08035
+5.77705 6.4705
+6.79362 8.51993
+9.73155 9.81609
+3.71503 3.92022
+6.18589 6.77634
+3.94124 4.23942
+7.59911 8.05275
+3.68865 5.10948
+7.63926 8.63019
+-0.049855 0.0844425
+-0.41188 0.807786
+1.35962 1.81039
+5.40579 6.15098
+1.38594 2.0059
+6.93444 8.71958
+7.01229 9.38008
+-0.0974976 0.962679
+4.74131 6.59152
+1.02343 1.59245
+1.55629 1.9128
+6.28353 8.38021
+5.66349 5.79644
+1.72629 2.28563
+1.64539 2.82654
+0.359466 1.05106
+4.37569 4.82703
+5.87657 6.37853
+1.46316 1.65333
+7.44494 7.5985
+1.16846 1.98579
+4.43371 4.93234
+2.31838 2.47777
+7.52687 8.44423
+6.08056 7.42253
+9.16144 9.94783
+4.74382 4.95616
+0.248344 1.05335
+6.12345 7.43941
+9.45647 9.99799
+3.77124 4.75199
+3.31315 3.44873
+-0.0909828 1.51271
+7.03234 8.02546
+8.11403 9.11461
+6.734 7.34799
+1.08903 1.18319
+2.72871 4.31607
+6.53688 7.52754
+1.07868 1.27792
+6.28409 6.56795
+4.89866 5.79458
+9.06994 9.1221
+2.54989 3.14338
+3.69971 5.71717
+3.7113 4.55076
+8.91864 9.64522
+8.75634 8.82359
+9.02242 9.03869
+3.59945 4.20169
+4.98557 5.07401
+4.81526 5.74009
+7.264 8.63749
+2.79579 4.43389
+2.87204 4.66432
+2.32487 3.72127
+3.99704 4.72567
+8.17229 9.0158
+-0.72926 0.823658
+2.52355 3.32725
+5.3446 6.63868
+4.48935 7.37833
+3.08173 3.0968
+2.41585 3.23026
+9.23187 10.5413
+5.50099 5.51888
+1.29634 1.88846
+-0.0113225 1.41526
+6.34508 7.53417
+0.383019 2.25144
+5.0649 5.40222
+3.08221 3.76296
+9.29111 10.6833
+2.19714 2.94735
+8.75711 9.48583
+8.61564 8.69349
+1.9362 3.96191
+3.7962 4.44382
+7.78501 9.03843
+5.79649 7.29675
+6.03048 7.4316
+1.31105 4.36446
+6.5882 7.03622
+4.88148 7.12474
+6.62305 6.90973
+2.27488 2.73731
+8.42703 9.28888
+7.72928 8.53989
+7.27021 8.63879
+0.992908 1.92001
+-0.282737 0.511292
+7.88963 8.03117
+6.93371 8.26148
+-0.0346633 0.403617
+8.7827 8.82558
+5.16876 5.59742
+8.61275 8.73843
+5.70578 6.02783
+9.08706 9.35903
+9.32728 9.83021
+9.20058 10.2497
+6.79824 7.3024
+7.17979 7.51783
+0.918555 2.67878
+7.9662 8.63241
+8.85903 10.3145
+9.34614 10.1964
+9.05027 9.79872
+8.28959 8.45837
+1.32518 2.04557
+8.72848 9.16742
+5.92126 6.77277
+8.31504 8.78631
+1.02487 1.70172
+4.45204 4.72842
+8.20636 10.4724
+5.86211 6.25457
+6.15754 7.71303
+8.37832 8.82577
+4.25233 4.59417
+9.41451 9.95324
+9.372 10.4461
+1.8346 2.7144
+8.00681 8.14717
+7.03997 7.06753
+7.16892 7.70102
+7.01781 7.46799
+1.78526 1.7969
+1.63304 2.2011
+8.59718 8.61083
+9.43498 10.3636
+4.98718 5.32487
+3.65451 4.89601
+8.82368 9.11333
+-0.104862 0.598773
+4.97756 5.62342
+1.99876 3.24686
+2.32242 4.01096
+4.04914 4.77892
+3.81545 4.32583
+3.30153 3.46783
+3.14287 4.04718
+8.65711 8.76768
+9.09385 10.6898
+4.82771 5.64405
+5.98783 6.36785
+7.93397 9.6543
+4.89726 5.65486
+5.08717 5.22314
+6.59377 7.23748
+3.58289 3.98597
+0.177884 0.397629
+5.30856 5.79257
+2.53943 3.98007
+6.51217 6.59644
+0.196888 1.99904
+3.8709 4.1901
+2.37646 2.50997
+7.03837 8.13287
+6.8674 6.89535
+0.576964 2.08851
+0.902928 2.86981
+8.59261 9.20279
+5.96621 7.49899
+0.617602 1.83267
+2.29189 2.6361
+4.34207 4.61026
+6.19963 6.76443
+1.15955 1.44068
+5.25852 6.33905
+6.37306 7.53103
+9.13334 10.039
+8.67743 9.93959
+5.62973 6.04375
+8.32286 8.77042
+3.28772 6.1722
+4.97902 5.47249
+3.37765 5.07238
+4.58025 4.84341
+2.76807 3.18817
+4.27581 4.43023
+6.92572 7.68461
+0.279247 1.0561
+1.10903 2.61106
+6.71708 6.73132
+2.66415 3.75702
+8.0513 9.80334
+4.82466 6.04232
+2.59971 2.85768
+9.04689 9.73945
+3.48338 5.16622
+7.90925 8.92774
+7.30264 8.06247
+7.59087 8.26476
+0.150315 0.423068
+8.62726 9.74636
+9.01983 9.71707
+6.84007 7.40541
+8.87829 9.48342
+2.69214 3.71481
+0.580036 0.77289
+9.474 9.83397
+5.80151 6.08527
+3.63837 5.27137
+8.5848 8.65779
+7.88338 8.13276
+3.27992 4.20963
+6.21244 7.28079
+-0.348924 1.38478
+5.26688 5.93787
+3.78941 5.01009
+6.41929 8.38529
+1.41724 1.67733
+0.212821 1.58246
+0.0697189 0.160497
+9.57839 10.2377
+9.03332 9.70645
+4.94572 5.15163
+3.16999 4.536
+5.77494 6.68359
+5.89258 6.11852
+7.72257 8.21668
+8.42501 8.44905
+8.7196 8.86465
+4.392 5.1076
+1.88249 2.54422
+1.38092 1.60326
+5.04142 6.37374
+4.31795 5.91152
+1.79399 2.09314
+6.65405 8.32262
+1.36356 1.58538
+5.45456 6.55824
+4.95807 6.22848
+8.72077 10.2825
+0.745968 2.01546
+6.85041 7.11076
+4.82028 5.34442
+5.77673 8.01294
+8.58582 9.33714
+8.49884 9.21533
+9.05574 9.4096
+3.19932 3.27024
+9.50227 9.96685
+0.771636 1.0617
+9.00621 9.36397
+-0.097167 1.39463
+7.79622 8.43537
+8.05228 10.1504
+2.21685 4.17072
+1.82476 2.45381
+4.34408 4.56578
+9.27538 9.54701
+6.80153 7.44115
+7.38884 7.84448
+7.17526 8.00165
+5.85812 7.67326
+5.25545 6.30791
+5.68518 5.94055
+3.77685 4.1545
+0.530928 0.737248
+3.9772 4.59563
+8.96322 9.45618
+7.98322 8.44165
+3.42929 4.22329
+3.66445 4.7583
+-0.183652 0.434842
+3.16492 3.95726
+6.87407 7.89944
+5.08921 5.7745
+2.85466 3.04505
+7.12685 7.41248
+0.715419 0.876676
+3.47441 5.21753
+9.13594 9.87799
+5.52459 6.35691
+5.12544 6.12935
+2.44296 2.91543
+2.75148 4.19886
+1.43478 4.3919
+6.6352 7.07768
+4.72283 5.11506
+6.36434 7.69268
+2.32643 2.75289
+5.46566 6.22854
+6.37995 6.76989
+1.52564 3.55871
+1.05807 2.19393
+1.95374 4.08727
+8.11273 8.12767
+2.85955 4.71355
+4.89009 6.88516
+2.06859 2.25512
+7.50556 8.77923
+4.43353 5.11915
+5.16308 5.9695
+1.12072 1.69277
+3.96494 4.38143
+7.06931 7.89524
+0.514522 1.51265
+6.56389 7.01146
+1.51362 1.8541
+4.90339 5.51209
+2.11422 3.15457
+2.50094 3.92557
+8.24319 8.62826
+-0.0843505 0.710377
+6.35956 7.89457
+-0.790954 1.2964
+4.02253 5.19193
+2.7425 3.46763
+9.41469 10.1367
+1.57636 2.25105
+3.18647 3.38738
+8.36644 9.66791
+0.180846 0.461221
+7.07675 7.71881
+0.265366 1.19275
+5.43007 6.4854
+9.13912 9.23294
+9.52905 10.4029
+1.18712 2.66227
+5.22714 5.62601
+1.87413 2.8716
+5.71882 6.16374
+5.38169 6.13948
+-0.196005 0.236738
+5.36803 6.4395
+8.27713 8.71262
+8.82031 8.8598
+-0.53845 0.564783
+1.80716 1.94173
+5.67905 7.47291
+2.37779 3.64893
+0.574727 0.766424
+4.60701 4.86591
+3.17989 4.37738
+1.36777 3.15112
+1.48092 3.06573
+3.37009 4.06028
+4.17179 6.2073
+6.47953 6.88994
+5.74431 6.5253
+4.88827 5.49049
+5.44148 5.59239
+1.66153 2.63132
+7.69387 7.82267
+5.20911 5.48488
+-0.103218 0.497402
+7.18003 7.33324
+6.54305 8.81732
+0.278108 1.27452
+2.38323 2.94772
+1.2461 2.03246
+5.47052 5.75781
+7.31505 7.35895
+2.22248 4.23589
+0.0305319 0.430773
+8.32043 10.1222
+6.11732 7.09764
+5.08797 5.74991
+6.62491 7.34164
+5.55795 5.66083
+3.27549 4.13145
+1.0113 3.24631
+0.0717186 0.519738
+7.82905 9.30839
+9.90251 9.98691
+0.841457 0.952276
+-0.133927 0.510174
+1.14614 2.82218
+2.59767 4.19742
+3.41095 3.95265
+3.38951 3.75838
+8.86766 9.19437
+9.27927 10.261
+2.33249 2.79402
+5.69681 5.93469
+4.02502 5.38732
+0.797157 1.22845
+7.23558 7.8651
+1.1253 1.99184
+8.58296 8.64267
+-0.400141 0.74698
+3.46677 3.50526
+6.03252 6.64842
+5.8493 6.68938
+3.53209 3.84014
+7.22078 8.98106
+6.21943 7.69944
+0.887198 2.07323
+3.36591 4.57442
+4.30143 6.41179
+4.07556 4.54276
+8.77552 10.0615
+6.7247 7.04044
+9.05494 10.1126
+7.46604 7.80632
+3.38601 3.8043
+5.60475 7.02788
+9.09811 9.4654
+9.33447 9.80012
+8.66499 10.1002
+3.87007 3.88281
+2.87624 3.11359
+5.92385 6.80801
+4.49711 5.01863
+8.84524 9.36225
+6.40944 6.82093
+2.90915 3.68288
+3.96801 4.82534
+5.51744 5.84233
+3.2959 3.44409
+0.18526 0.207322
+5.49717 5.72648
+6.9522 7.1952
+0.769572 1.79343
+5.95522 6.03918
+6.54327 7.7475
+2.13516 3.83957
+-0.388892 0.775076
+1.30128 2.29414
+9.76761 10.1604
+7.38731 8.66002
+7.09229 7.43495
+9.1379 9.52432
+6.75942 7.88717
+7.42824 8.82063
+6.93078 8.19884
+2.307 2.93836
+8.38254 8.84691
+3.90159 5.37938
+0.0413204 0.112203
+0.638217 1.53943
+0.88678 2.49435
+1.99104 2.60847
+6.61595 7.65064
+2.37641 4.71719
+7.94945 9.21404
+5.44594 7.13646
+5.45737 6.12335
+7.39207 8.02885
+5.51588 7.39341
+8.1581 10.0632
+0.197869 1.44516
+-0.0161139 0.73487
+4.24155 4.7304
+0.00374564 1.26481
+8.1878 8.20011
+-0.115544 1.74771
+0.912347 2.52922
+2.72234 4.83268
+6.45577 7.07776
+9.74201 10.1772
+7.11008 8.72914
+4.41921 4.8673
+7.97673 8.36658
+0.438659 0.647061
+4.35086 5.44482
+8.22919 9.34379
+3.53242 5.65576
+1.126 2.32177
+5.95118 6.51364
+3.10519 3.9447
+1.28889 2.26267
+7.04255 7.67791
+3.12614 3.17626
+8.09968 8.49162
+6.07924 7.219
+5.99554 6.52549
+9.14378 9.5773
+5.82872 6.53112
+9.3361 10.1704
+4.3751 6.51675
+3.288 3.98328
+4.56342 4.80185
+7.16574 7.43901
+7.7638 8.47758
+7.31514 7.78499
+7.98942 9.50252
+4.31211 4.70724
+2.9094 3.33304
+0.108736 0.668815
+8.08409 9.11098
+-0.0053985 0.589992
+1.31926 2.72153
+2.28664 2.38813
+7.95237 8.26388
+-0.0283047 0.452099
+7.50295 8.71708
+7.72356 8.63468
+3.48953 3.89579
+7.73814 8.73456
+4.54487 5.45817
+6.45109 7.00312
+3.99915 5.41716
+6.81436 8.5682
+6.86726 7.55999
+2.67863 3.7053
+2.6837 3.39567
+2.84347 2.91724
+5.79383 5.80493
+2.41217 3.0619
+8.78163 9.0998
+1.43456 2.50854
+6.73393 8.53005
+3.02563 3.56456
+3.34628 4.2934
+2.44985 2.92819
+1.38262 2.89341
+4.56337 5.75702
+0.275735 1.16604
+1.39763 2.8108
+9.69128 9.90361
+8.54868 9.66756
+3.01838 3.72831
+8.34017 10.5262
+1.82721 3.0476
+5.9732 6.83307
+2.77874 4.25603
+1.71987 3.1227
+6.33773 7.89103
+1.31982 2.82992
+4.21601 4.9627
+6.68166 6.72653
+0.87708 1.06828
+1.03483 1.26625
+2.996 4.03087
+1.54718 1.57452
+2.33087 2.38226
+2.29464 3.36496
+2.03064 3.41867
+5.8456 6.10406
+7.54614 8.2874
+1.42938 2.89154
+2.65935 3.53883
+3.98845 4.42049
+6.85632 7.15487
+8.12038 9.34993
+0.873558 1.32129
+6.61595 8.00766
+9.49147 9.81947
+-0.0225601 0.328769
+-0.481519 1.37204
+6.31457 7.45251
+4.59738 5.81395
+4.83304 5.63008
+1.95746 2.78657
+2.97889 3.74408
+9.08327 10.702
+3.58219 4.93634
+7.87068 9.77851
+0.330978 1.36031
+4.78145 5.36918
+4.94672 5.56644
+7.66806 8.08613
+4.78512 6.35461
+5.17367 5.74386
+8.65884 9.97088
+9.22053 9.60447
+6.15061 6.58817
+0.0875971 0.541643
+6.45597 7.92002
+0.636824 1.05267
+5.31677 6.12838
+6.51127 6.6731
+0.459551 1.69382
+5.75106 6.41377
+3.68438 4.67415
+9.36302 9.78281
+5.46195 7.99215
+2.55471 2.59231
+-0.0640245 1.33755
+9.36027 10.6198
+2.67955 2.77882
+3.51443 4.10619
+6.83904 7.23692
+2.59553 2.81418
+7.74628 8.95169
+3.86464 3.90067
+3.32377 3.992
+1.43737 2.52191
+3.83927 3.99402
+5.24426 5.35179
+0.833857 1.05277
+8.4062 8.51964
+9.62299 9.66254
+3.55427 5.19048
+1.7003 2.62107
+6.8059 7.49246
+-0.761104 0.773528
+1.37137 1.95048
+2.1222 2.59387
+0.633505 2.04796
+0.605156 1.04336
+7.22842 8.3365
+4.28716 5.28921
+8.14286 9.52015
+7.62467 9.18603
+1.11029 1.81278
+5.05654 5.13597
+0.862653 0.97827
+7.24766 7.92167
+8.80103 8.91467
+3.05841 4.82292
+1.28204 1.55969
+1.58886 2.57874
+0.0537678 1.28837
+8.09303 9.71678
+8.37599 8.85705
+3.18107 4.01971
+6.67019 7.75848
+6.29836 8.21603
+0.86271 1.30358
+3.86126 6.49694
+5.84446 6.24913
+0.475025 0.598151
+6.3477 7.08327
+3.60161 4.51824
+7.13317 8.13858
+4.89052 6.23701
+5.69441 5.99027
+7.18735 8.34853
+9.30182 9.34894
+6.06589 6.15141
+8.05917 8.89642
+5.6136 7.14058
+0.838337 0.959487
+0.56421 2.00841
+6.46876 6.63629
+2.4434 3.92184
+7.97216 9.45372
+8.17926 8.66756
+1.86522 2.01888
+0.983342 1.89079
+2.07322 2.09765
+3.52974 4.73717
+3.24973 4.88691
+5.47789 5.95384
+4.11218 4.57076
+6.61174 7.47165
+8.09302 8.36193
+1.67911 1.69022
+4.436 6.17515
+5.6544 5.74951
+1.50354 1.76043
+4.41433 4.83589
+1.82528 3.53979
+3.98749 4.65527
+6.42503 7.5787
+8.69554 10.1767
+8.39215 8.56999
+8.71646 9.66209
+1.59091 3.39622
+6.12574 6.94955
+7.92527 8.25049
+9.19858 9.49137
+2.73382 2.97747
+4.56558 5.94738
+8.33983 8.58548
+9.00798 9.01838
+4.93268 5.28383
+3.15356 3.58606
+8.28171 8.79351
+1.47358 1.9581
+0.891797 2.05345
+1.56032 2.38159
+2.5152 3.80485
+8.0963 9.88138
+1.1262 1.89279
+7.99336 8.2352
+5.25067 5.41251
+4.57532 5.20101
+1.87911 4.59415
+4.25142 4.70467
+8.18782 8.76989
+9.20478 9.3612
+7.70898 9.7752
+0.655865 0.958924
+4.8883 5.77477
+3.03279 3.47456
+1.01979 1.41661
+8.94219 10.6987
+2.49348 4.58195
+2.44003 3.29005
+3.4725 3.55572
+9.3917 9.95851
+7.08658 7.47686
+3.56413 4.44089
+-0.47868 1.11453
+6.82615 8.00596
+3.49451 3.74705
+8.13286 8.47976
+7.01732 8.82556
+1.19064 1.48887
+5.28851 6.88637
+8.83175 9.49879
+0.939903 1.17024
+7.49124 9.01906
+2.9285 4.23224
+5.68296 6.86273
+8.53897 8.77886
+2.9107 5.01232
+0.748655 1.10265
+4.77258 5.12626
+3.995 4.75289
+2.71467 4.26926
+6.21665 7.16233
+4.53883 5.75731
+4.37153 4.76125
+7.47635 8.75777
+4.82013 6.4699
+9.36015 9.58451
+4.43054 5.86752
+2.10934 2.34705
+3.00306 3.06539
+7.81957 8.44081
+1.97221 3.06916
+0.153393 0.503956
+5.05611 5.27536
+5.73277 5.89001
+3.64807 4.85582
+6.13416 6.1528
+3.85511 4.14045
+0.411725 1.36529
+2.26932 2.5447
+3.51164 4.93266
+2.50955 4.34201
+8.74663 9.39268
+6.2229 6.39303
+4.38059 4.91592
+7.29109 8.62318
+6.31801 6.99532
+9.75036 10.0514
+1.69019 2.41527
+4.20462 5.27729
+6.32944 6.94729
+3.5736 5.21496
+4.48316 4.61828
+1.76915 2.43263
+2.42026 4.09159
+2.08762 2.43074
+5.48161 6.02473
+5.51826 7.47042
+2.78026 3.1552
+7.89469 9.49867
+3.09084 4.54697
+7.20417 7.42408
+5.36528 5.74851
+1.86239 2.41988
+1.55994 2.85743
+4.40182 4.6638
+7.91619 9.01242
+3.08119 3.74714
+1.54108 2.08538
+3.61461 3.64631
+8.76851 9.66257
+-0.645571 1.3366
+-0.707083 1.21005
+7.19571 8.23405
+5.42865 5.89329
+2.12897 2.59222
+0.603102 0.930391
+3.75025 4.63181
+6.14867 6.4526
+7.30947 7.51461
+7.83183 8.79802
+6.06658 8.53246
+1.67895 2.50063
+1.14179 2.04478
+8.59583 8.90112
+-0.918885 1.30717
+0.182607 0.613593
+3.3335 3.77196
+0.783053 2.4368
+6.49331 7.60104
+2.85101 3.28637
+7.42273 7.66905
+3.96433 5.02573
+8.26262 8.40749
+9.24451 9.32783
+4.89036 7.07214
+6.45431 6.96815
+5.20701 6.58747
+7.40142 7.98615
+4.19768 4.9831
+3.32546 3.88811
+-0.471996 0.967855
+9.36172 9.63532
+1.96831 3.00632
+7.537 9.72671
+4.67746 4.81135
+3.10782 4.93642
+4.94809 6.54855
+4.16763 5.25628
+9.04992 10.316
+0.668935 0.680886
+4.02935 4.84503
+5.32499 5.76636
+5.32267 7.15457
+5.18886 5.23491
+4.37053 5.36801
+2.39955 2.74657
+8.19764 8.86645
+4.24706 5.69703
+1.87851 2.36988
+0.886553 1.05064
+7.27428 7.90224
+9.08417 9.44879
+3.11534 4.02019
+6.3284 7.39925
+4.96029 5.59076
+2.58248 3.11741
+7.76513 8.13505
+4.93613 6.51523
+0.565355 1.70512
+2.12366 3.0319
+5.32422 6.84146
+-0.135396 1.08591
+3.7901 4.86303
+4.49677 5.41847
+0.615748 0.834712
+0.64784 1.81859
+6.65505 7.13894
+-1.12744 1.61017
+0.550814 1.24316
+6.66639 6.89866
+6.19271 8.17468
+3.09382 3.78684
+4.41221 4.95889
+7.96091 8.48824
+8.32129 10.2917
+2.13168 2.19835
+1.4635 2.38989
+5.78102 6.42215
+1.70153 3.20616
+5.35068 5.71016
+4.27702 4.37203
+5.13888 6.04764
+4.79644 5.37927
+6.75314 7.66368
+6.04484 6.84064
+4.34947 4.45643
+9.08755 10.396
+0.88804 2.17441
+6.86788 7.88301
+7.94296 8.61664
+8.02387 8.79591
+1.79024 2.40559
+5.50404 6.01044
+7.76772 8.1932
+1.174 1.23693
+6.20571 6.9224
+4.20863 4.48702
+4.16743 4.39075
+-0.11965 0.120778
+7.01234 7.52619
+5.91415 6.46151
+5.28713 5.72354
+6.26981 6.31237
+0.643056 1.43864
+1.62562 1.99875
+0.544992 0.721386
+6.92522 7.09165
+-0.107048 1.12273
+0.644674 0.91244
+8.56904 9.01883
+2.23079 2.56598
+9.79034 10.1123
+8.13788 8.4131
+1.86753 1.95236
+2.97577 3.33272
+8.57454 10.0193
+1.20043 1.53408
+3.43515 3.86571
+5.79075 6.41293
+1.71558 2.52845
+2.39907 3.46652
+9.08289 9.91182
+0.859644 1.07475
+5.30144 5.42157
+-0.441497 0.890794
+3.55044 4.14918
+-0.340115 1.19239
+6.5534 6.76908
+0.836514 2.09196
+8.15747 8.96484
+4.80087 5.14227
+7.72071 8.88223
+5.11901 5.65559
+4.44996 4.63562
+-0.328404 1.3002
+0.90759 1.34556
+5.94839 6.35058
+1.76504 1.78344
+1.32585 2.08994
+7.18641 8.20945
+0.62657 1.06025
+6.28086 6.40975
+5.05525 5.16143
+5.82694 8.07685
+6.23677 7.55394
+-0.226265 0.661443
+1.42599 2.36325
+9.04445 9.92971
+-0.169286 0.185741
+8.34636 10.9042
+9.52494 10.0475
+8.39989 10.1377
+3.89956 4.70428
+3.98673 4.97185
+5.43008 5.67936
+7.76475 7.98591
+4.46895 4.73188
+0.584662 1.54474
+2.12622 2.79994
+1.40578 2.2461
+1.45171 2.02105
+2.05665 3.04611
+2.29818 2.68118
+1.77344 2.98698
+4.92092 5.55302
+7.18758 8.37525
+8.83407 10.0565
+2.91182 4.71932
+6.47293 6.74664
+2.49238 3.69749
+0.487234 0.541003
+4.703 4.92744
+9.8867 9.94918
+1.7713 1.9792
+5.68316 6.90242
+5.62485 6.70656
+7.24837 9.60197
+7.71147 7.76519
+5.22324 5.30661
+9.11258 9.28071
+8.2827 8.90115
+8.90865 9.42138
+7.47233 8.72308
+4.89712 5.65153
+4.12392 4.20239
+5.65325 6.55887
+8.65945 9.05845
+7.9165 8.36489
+1.4952 2.43991
+5.49665 5.80793
+1.67206 2.55302
+0.943544 1.58521
+0.47 0.860959
+6.47638 7.43101
+4.38434 5.97278
+8.12782 9.10574
+5.78143 6.6539
+9.23616 9.40513
+1.6845 2.00736
+6.56955 7.37847
+7.42993 9.04718
+-0.179632 0.450904
+8.65819 9.07724
+7.86567 8.80824
+1.85428 2.7755
+2.29222 2.65374
+4.03614 4.51729
+6.9326 7.07635
+5.50807 6.498
+6.17637 7.26432
+8.7688 9.16308
+7.65 8.88604
+3.74495 4.29991
+8.5671 10.5661
+7.41964 8.21083
+8.04302 9.78783
+0.269663 0.317601
+8.29804 9.40991
+3.90673 4.22298
+8.82384 10.9441
+7.27081 8.19548
+1.30184 1.98993
+8.13028 8.92385
+7.21224 7.35137
+5.02122 5.69666
+0.817219 0.974073
+-0.128067 0.589359
+2.12137 2.74019
+5.24657 5.44714
+1.55805 3.10332
+9.91031 10.0748
+7.13941 7.9143
+-0.183908 0.934079
+3.987 4.11053
+3.26678 3.67608
+9.75921 10.1121
+0.755391 1.06346
+7.28479 7.49982
+1.37522 3.80623
+0.944351 1.46531
+9.49278 10.2372
+8.28946 8.67597
+9.43537 9.58003
+7.73357 8.756
+2.64043 2.8687
+4.70448 6.99929
+3.82199 3.89343
+3.43825 4.10908
+4.42362 5.69086
+8.08536 8.60142
+8.43208 9.31272
+7.5889 8.39208
+7.90112 7.9734
+6.10381 6.80568
+8.76283 8.80151
+1.46728 2.53288
+1.68884 2.47102
+7.63343 8.29838
+9.18852 9.5558
+0.977174 1.4792
+4.7577 5.74873
+4.66433 6.37375
+-0.0952277 0.378184
+5.30929 6.07469
+4.98811 5.16146
+3.0744 5.59799
+0.944909 1.25222
+1.38561 2.51277
+3.77811 4.23459
+2.11604 3.32458
+0.920929 1.17187
+5.23496 6.34905
+6.9953 7.65745
+4.81803 4.89553
+4.69301 5.36777
+-0.208926 2.6111
+7.97334 9.83269
+-0.396673 0.779988
+5.91367 6.47682
+6.27249 6.83533
+5.58931 6.89679
+2.03394 2.67025
+-0.197752 0.383167
+4.69751 7.695
+4.5989 6.07875
+3.7285 4.27396
+7.9807 8.27693
+-0.00248985 1.30934
+2.68016 3.916
+0.881558 1.14567
+4.77066 5.05302
+0.552268 0.919467
+2.46862 2.65199
+1.4009 2.51701
+-0.171185 1.28252
+9.27842 9.90243
+3.51778 3.57728
+6.10071 6.92163
+9.05387 10.0894
+5.52995 5.89082
+8.40216 9.0272
+9.02911 10.1602
+4.85818 7.38829
+1.6762 2.32334
+6.45416 8.62337
+5.44592 6.0245
+3.45876 3.94274
+9.07144 9.16725
+6.51885 7.6363
+7.92593 9.01986
+0.270702 1.57395
+6.11245 6.70173
+1.37658 2.19068
+2.42668 3.43827
+7.98226 8.43306
+3.72269 4.74654
+8.16252 8.58873
+8.81456 9.5363
+-0.338386 0.864811
+1.90693 2.25796
+3.5305 4.17475
+6.07997 7.67393
+0.53347 1.68815
+7.31182 8.44458
+7.77462 8.33613
+3.79975 4.15552
+9.08822 9.9771
+-0.101698 1.05442
+8.44869 9.95724
+-0.0318759 0.532673
+8.09238 9.51356
+5.51514 6.60799
+8.66528 10.3297
+8.25556 9.97893
+-0.220428 0.247563
+0.00453913 0.540444
+1.53599 1.61735
+3.77213 5.06896
+2.65332 2.75864
+6.05811 6.43112
+0.302534 0.803651
+0.393766 1.11611
+9.31035 9.62387
+0.568281 1.7765
+-0.721118 1.27387
+1.83573 2.62578
+1.39953 1.91158
+6.51883 8.52813
+2.60154 2.95054
+6.58322 9.37818
+5.61178 5.67661
+9.56511 10.2767
+9.09174 10.0697
+2.55846 3.39943
+8.38146 9.06138
+7.97019 8.18074
+6.1426 6.42787
+1.15876 1.55463
+2.93483 2.96376
+7.23883 7.29158
+9.64606 10.0674
+4.89825 6.70366
+7.35635 7.96328
+2.2702 2.36797
+-0.0464389 0.395244
+1.14883 2.10411
+4.7309 5.10593
+6.07946 7.37741
+5.50202 6.28822
+3.66574 3.96271
+1.9944 2.3862
+7.58159 7.59275
+1.98712 3.30587
+2.10317 2.89161
+9.66889 9.97287
+1.57327 2.15421
+8.14125 8.30983
+3.77185 4.12658
+8.51624 9.51485
+9.25211 9.722
+2.06312 3.0453
+9.34954 9.91254
+7.31475 8.89322
+7.85044 9.20242
+0.226243 1.28465
+0.0260868 0.575177
+9.40743 10.1655
+4.04324 5.05341
+1.02626 1.48332
+3.33074 3.72025
+9.2005 9.61387
+6.68317 7.14109
+6.82083 8.6312
+4.34816 4.50329
+-0.48874 0.975608
+4.26651 5.68526
+4.89731 5.57569
+2.68984 3.5661
+0.499714 1.01055
+9.01902 9.36142
+3.22067 4.59054
+0.65132 0.860512
+1.6791 2.36642
+8.28222 8.7579
+2.84349 3.24134
+5.64949 6.09512
+3.44026 4.43245
+2.60889 2.6248
+-0.00849234 0.984046
+7.5745 8.65675
+2.07464 2.6488
+2.59747 2.65772
+6.36828 7.42208
+3.83342 4.50127
+5.41167 5.7011
+6.53606 7.53796
+8.21975 9.56176
+1.90113 3.08684
+7.74402 7.82057
+4.26515 5.11327
+5.42743 5.59215
+8.69709 10.0912
+2.87019 3.94798
+9.27013 9.54627
+9.30568 10.2136
+9.02985 9.62917
+3.7589 4.59642
+6.59359 6.86939
+3.26574 4.83488
+5.14545 7.70086
+7.43163 8.05103
+5.72972 5.74457
+0.490113 1.31151
+7.018 7.42627
+6.22976 6.27589
+9.07732 9.30419
+4.3917 4.42663
+8.50298 10.3728
+6.18671 7.53619
+3.51053 4.097
+2.17172 3.56595
+6.08046 6.23691
+9.07361 10.9129
+3.95757 4.11333
+-0.136516 0.78995
+1.34923 3.47002
+0.0562579 0.686502
+9.10943 10.2731
+5.80174 6.16971
+7.86011 7.87649
+5.34384 5.51645
+6.32167 6.76387
+7.70566 8.28038
+-0.319903 0.867682
+-0.372564 0.570014
+8.83696 10.8439
+7.78947 9.38211
+9.25815 10.1092
+5.59721 5.67148
+0.234719 2.42489
+1.06314 2.87416
+1.75391 2.69799
+5.4536 6.66068
+1.35696 1.87102
+2.17418 3.1459
+7.61817 7.98287
+2.92194 3.18393
+7.68243 7.83261
+9.33163 10.5531
+1.14227 2.50228
+5.47911 5.70857
+9.88123 10.0758
+8.81249 8.83145
+6.02747 6.43183
+4.81158 5.79178
+6.65666 7.5047
+4.89085 5.56569
+0.935564 1.71547
+-0.0452879 1.16222
+4.03524 4.6206
+5.88518 6.02658
+2.06227 2.9581
+0.207246 2.2404
+2.81757 3.70318
+0.704257 1.98403
+2.38486 3.30039
+3.57073 4.78358
+1.53721 3.00546
+8.37852 8.39527
+1.54619 1.59789
+1.00447 1.40778
+5.31977 6.43861
+3.82175 3.83209
+3.37738 4.44002
+5.46644 5.97254
+3.88191 5.00688
+4.88046 5.39031
+4.15092 4.93679
+1.75182 2.07399
+1.16434 1.76541
+3.37032 4.29676
+3.1685 3.98533
+1.28787 1.59775
+5.86338 6.17993
+3.8645 4.25757
+1.83947 2.48092
+0.184795 0.586724
+3.13752 3.76447
+2.14264 3.03248
+5.78182 5.9029
+2.47969 3.8088
+2.59206 3.08362
+-0.354871 1.03627
+7.94041 8.05947
+9.48014 9.93817
+0.992727 1.48877
+6.1525 7.51387
+5.00071 6.15665
+7.42074 8.27606
+9.6539 9.83042
+1.08984 1.46387
+5.46282 6.95907
+4.74506 5.13968
+0.357565 1.91464
+9.07652 9.65474
+0.201095 0.646211
+7.04306 7.69131
+1.17728 1.2237
+5.92183 6.29165
+-0.41356 0.491524
+8.38339 10.4509
+8.08648 8.11344
+3.32474 3.39522
+5.762 5.83732
+2.26778 2.55548
+4.86127 5.92868
+3.75949 5.16608
+4.83431 5.88632
+2.65122 3.31344
+9.30295 9.38948
+6.03391 6.32749
+5.12035 5.59414
+5.68785 5.979
+7.89553 9.15202
+2.54445 2.74715
+2.36337 2.49709
+4.71661 6.12198
+3.72447 4.68735
+1.0541 1.53187
+3.45178 4.80929
+7.90773 8.26212
+8.1816 9.18627
+0.322569 0.871041
+7.24823 7.32699
+1.7003 2.78087
+9.70927 10.2515
+3.75922 4.01081
+1.06949 1.40253
+1.21774 1.4734
+6.02123 6.32973
+2.76396 3.09484
+2.80358 3.00026
+5.25666 6.31369
+4.71714 5.30669
+4.37906 4.50557
+7.40824 7.44969
+7.89081 9.18263
+8.8136 10.3074
+9.1757 9.37261
+7.1938 8.51137
+0.580081 2.32678
+2.02497 2.95434
+6.01446 6.78851
+8.54365 9.21454
+3.03567 3.27089
+0.650657 1.5716
+5.05518 6.36521
+1.64301 2.76399
+4.15989 4.34183
+3.72791 3.98156
+3.91372 4.06182
+3.04507 3.88871
+3.82596 4.25694
+3.36492 5.00402
+6.50019 8.17974
+3.54621 3.81009
+0.546921 2.09811
+5.1789 5.9826
+4.98983 6.31221
+2.47557 2.63878
+4.64568 4.81101
+9.1462 9.21888
+7.37417 7.5276
+2.21604 2.50113
+8.29804 10.2722
+5.1282 6.06353
+8.58281 10.1589
+6.47084 7.04085
+6.27806 6.72674
+7.11554 7.85687
+6.01085 6.02773
+5.46694 7.52872
+9.51078 9.85387
+3.36627 4.06552
+2.96126 5.12635
+3.09314 3.40691
+5.05456 6.62548
+7.56469 8.97053
+1.33727 2.87482
+5.6572 6.28169
+0.120924 0.296475
+7.09139 7.41322
+2.10076 3.28507
+8.74998 10.1094
+7.45072 9.50796
+7.75294 8.59218
+0.740374 2.44897
+7.63001 8.91562
+4.30743 4.81716
+6.40813 7.29159
+6.30213 7.35987
+6.44392 7.32584
+8.41155 9.4466
+-0.377892 0.689618
+5.88857 6.70983
+6.67779 7.70668
+4.831 5.17464
+2.62342 3.82764
+8.57453 9.29283
+7.32648 7.96725
+9.32937 9.9726
+7.30774 7.65754
+3.97456 4.59876
+5.73092 7.20962
+1.958 2.10551
+3.2115 3.81482
+5.76497 7.42425
+2.77219 3.29692
+4.95297 5.14843
+5.96367 6.3619
+2.49872 4.61736
+8.21817 8.23425
+2.13615 2.61877
+7.84121 9.55011
+8.63416 10.2773
+5.61084 6.32053
+4.86002 5.79944
+9.07858 10.688
+5.95829 6.42504
+3.3289 4.17849
+3.27989 4.91625
+8.28046 9.23021
+2.18691 2.6072
+1.3962 1.75013
+2.13627 3.73117
+2.11128 2.57303
+7.22357 7.50136
+7.43862 8.03136
+2.80578 3.02886
+0.176906 0.761142
+5.99314 6.6075
+1.90398 3.3925
+5.48264 6.73579
+7.18447 7.49811
+3.24434 5.05219
+5.53263 6.04178
+1.71172 2.45682
+0.297266 0.481632
+2.62582 3.36142
+0.243865 1.49321
+8.86142 10.169
+3.93193 4.39404
+4.98182 5.15675
+7.99209 9.73159
+8.18033 9.45596
+4.25235 4.41546
+1.59603 2.15581
+6.47724 8.69649
+5.24138 7.93131
+3.4267 3.49003
+0.0439912 0.316407
+1.99983 3.87206
+-0.103124 0.568771
+4.62451 4.80117
+2.89065 4.16315
+5.82817 7.43232
+6.89255 7.82189
+5.71037 6.81241
+4.34551 5.24905
+7.33931 7.3741
+-0.855192 1.27129
+8.94842 9.10813
+9.19877 9.68412
+6.42658 7.77968
+-0.0669636 0.430107
+6.40366 7.40701
+8.91175 9.24059
+3.21388 4.21676
+3.38557 3.79509
+4.24411 4.97032
+7.259 7.34896
+2.55995 3.18361
+8.77438 10.5503
+8.18685 9.79378
+2.78397 4.4563
+8.6891 9.38337
+6.51749 7.59374
+2.52346 3.46101
+8.40526 9.35647
+5.26942 6.33572
+4.15094 5.00668
+0.471666 1.53842
+7.63441 7.96745
+2.39974 3.7814
+2.71989 3.02994
+8.12085 8.33493
+6.19474 6.84381
+6.6133 8.31417
+5.1758 6.94983
+8.66241 8.79095
+6.10878 8.22083
+8.81883 9.08031
+8.28969 8.45176
+7.19851 8.37836
+1.5722 1.6836
+4.57814 6.95063
+7.66128 8.10631
+0.742483 3.08515
+1.15026 1.98074
+3.90133 4.12003
+7.61145 7.73433
+8.32187 10.2933
+0.407205 1.08089
+1.26545 2.60796
+2.70646 3.92753
+-0.196551 1.83536
+-0.413063 1.23838
+0.264484 0.556192
+6.30158 6.96097
+-0.66246 0.809062
+9.34243 10.3521
+8.70093 8.79679
+0.745195 1.92911
+9.12892 9.68193
+7.98533 8.30538
+6.23671 7.04296
+6.5603 6.95483
+7.08133 7.10563
+2.15769 2.41541
+8.24752 8.73978
+5.27693 5.61904
+0.317419 1.48404
+3.48029 5.46979
+7.38901 8.56554
+1.06587 1.62384
+5.54926 6.04924
+4.46577 6.48749
+5.349 6.15584
+8.04249 8.17359
+3.37651 3.56179
+3.64706 5.57403
+4.49844 5.26404
+3.93361 4.92128
+5.82184 6.29881
+0.984273 1.70318
+1.12773 1.80726
+3.11675 3.17451
+5.07913 5.46291
+0.615591 1.81465
+1.08948 2.77847
+7.97412 8.07365
+5.05207 5.82497
+0.0407709 0.558817
+6.11142 6.48205
+3.4461 3.57315
+8.6547 8.80553
+8.18965 9.64194
+5.55564 7.9703
+4.01776 4.16989
+2.4668 2.82018
+0.911925 2.56662
+4.68814 5.03614
+7.4899 8.49036
+8.40912 9.14001
+2.32725 3.16377
+0.0723972 1.42049
+6.6441 6.6953
+3.65586 4.38222
+6.35844 6.57833
+4.44435 5.73077
+1.81779 2.57257
+4.17692 4.59722
+8.54682 9.38058
+1.61135 1.81629
+3.91926 5.00536
+9.78302 9.85143
+1.25632 3.10345
+5.53191 6.08174
+-0.231868 0.676811
+1.03054 2.58105
+0.0402172 0.690608
+0.974571 1.25234
+5.22227 5.92302
+8.05843 10.1439
+8.48938 8.50755
+0.0965782 1.24008
+6.53821 7.47765
+0.189991 0.475204
+8.48963 8.54995
+9.68363 10.0534
+1.49381 2.71302
+6.75552 7.41283
+7.91075 9.15302
+0.520922 1.40928
+1.17957 2.11221
+4.00122 4.40686
+7.32467 7.9273
+6.39126 7.90248
+6.50534 8.19308
+7.19888 7.22234
+-0.136797 0.731889
+0.870318 1.25614
+2.07126 2.28297
+6.10995 7.60408
+3.02174 3.90102
+-0.657541 1.57517
+0.993121 2.66255
+7.27232 7.50832
+2.16079 3.75428
+9.27397 9.75098
+8.36865 8.5545
+4.56641 4.97607
+3.60746 4.34616
+6.31304 7.70611
+2.91442 3.7602
+4.85814 6.70407
+4.45876 5.67661
+8.06749 8.82229
+2.02826 3.59873
+1.92922 2.50088
+2.63867 3.48117
+2.17665 2.54826
+8.62674 9.10675
+0.96648 1.47671
+8.86336 9.53978
+5.52747 5.80829
+0.77099 3.06106
+2.2307 2.53877
+6.29165 6.63018
+4.44717 5.04651
+3.80894 4.63054
+7.47519 7.87072
+0.933668 1.9949
+-0.712945 1.21558
+7.30206 8.38376
+5.80281 7.00022
+7.96578 8.6558
+0.24063 0.706466
+4.41893 4.58472
+4.0132 4.92768
+5.29626 6.09397
+3.43602 4.00728
+0.780945 1.66499
+8.83861 9.15168
+9.06411 9.75544
+3.45618 3.62529
+9.51413 10.0148
+0.842106 1.75695
+1.06485 1.44192
+6.89987 8.05314
+7.89154 8.73313
+8.71675 9.79526
+2.40574 2.58062
+8.55952 8.78132
+5.61716 6.06282
+3.71059 3.77929
+2.50187 2.99137
+6.92852 7.23184
+7.00442 7.93869
+8.82232 8.8756
+4.10389 4.53702
+7.6907 7.77577
+9.31554 10.2674
+8.51082 8.70339
+4.83332 6.70311
+4.6904 5.42892
+4.71407 5.67695
+4.12047 4.44089
+7.51845 8.26858
+1.31781 1.9397
+6.26854 8.02093
+6.92072 7.77774
+0.438156 2.18909
+0.898035 1.72074
+3.81121 3.8643
+1.01676 1.34308
+9.28445 9.42801
+2.43133 4.43516
+4.33664 5.9904
+2.19178 2.37244
+1.5457 1.79785
+2.23781 2.6481
+6.8365 6.87073
+0.82568 2.74775
+9.59404 9.89262
+8.48394 9.15107
+6.16085 6.42224
+3.5667 5.97689
+4.16931 7.41638
+6.95636 7.0982
+6.87987 7.09233
+3.12619 3.14821
+7.76636 7.98459
+4.60371 5.59136
+3.92189 4.88302
+6.90694 8.19858
+3.85132 5.19015
+8.05045 8.32483
+4.8338 6.05032
+1.93576 3.18873
+2.4182 3.55039
+5.56905 5.8172
+4.18436 6.01283
+3.04944 3.85936
+7.83585 8.95233
+1.76281 3.0558
+3.44143 3.6317
+8.69887 9.40371
+5.67867 5.73236
+0.859809 1.76578
+6.92284 7.13601
+8.27495 9.13414
+5.44385 6.42599
+-0.941603 1.8215
+7.88161 8.79447
+0.965018 1.17732
+5.56442 5.79546
+8.79032 10.9909
+5.28632 5.79175
+4.80998 6.07002
+8.4021 9.81107
+3.16415 5.08682
+-0.212163 1.2052
+5.683 5.83625
+0.738527 1.31842
+2.03835 2.52756
+7.4543 8.91243
+-0.568869 1.44659
+3.58855 4.42371
+6.33058 7.18779
+-0.645579 1.94313
+2.18149 2.24157
+3.80281 4.67323
+5.14628 5.97452
+2.55239 3.45685
+3.56586 6.23355
+6.74752 7.19693
+8.99006 10.5533
+0.259833 0.99882
+8.9005 9.75401
+7.28058 8.41075
+4.57803 5.70104
+9.82823 9.90251
+6.94375 7.42033
+7.8878 8.81951
+5.01137 5.52693
+2.25503 2.28817
+6.65772 7.11107
+0.647512 2.04416
+4.34796 4.5706
+4.5395 4.91529
+2.65423 3.49531
+7.97384 8.78377
+5.53873 5.76806
+9.78641 10.1351
+6.01664 6.44407
+3.47406 3.75187
+4.59421 4.81804
+1.20641 2.00488
+2.48904 2.80768
+5.77372 6.10692
+2.49363 3.24499
+1.8483 2.62965
+2.28556 3.22209
+3.17819 4.51426
+3.5548 4.23276
+3.25239 3.57895
+0.613317 2.44862
+3.82234 4.78976
+4.72809 6.46528
+9.54107 10.4426
+9.20052 10.1921
+8.24152 9.89817
+5.17594 6.19462
+7.83364 8.17082
+5.67992 6.36464
+8.9943 10.1426
+2.20598 3.0081
+3.38199 5.16464
+0.599928 1.35804
+0.841211 1.60761
+5.29338 5.89919
+1.11061 2.29219
+3.41512 3.95907
+7.9375 10.0203
+8.73852 9.66917
+9.95092 10.0162
+4.02544 4.30219
+4.1461 5.37827
+1.08089 1.59196
+7.87513 8.21121
+7.85673 8.0973
+0.96237 1.56519
+2.45532 2.61678
+6.1829 6.23637
+0.135135 0.613518
+3.18324 3.78587
+5.64796 7.20194
+0.861169 1.71661
+9.66005 10.1169
+0.880774 1.12452
+1.29389 1.57658
+5.60299 5.89759
+5.53642 7.07306
+0.540268 1.31836
+6.60244 7.98105
+4.21877 4.57159
+3.15367 4.75356
+7.81055 8.40378
+8.00942 8.10861
+5.78071 6.35646
+3.15993 4.99293
+2.36526 2.78444
+8.1361 8.76071
+1.40066 2.96474
+-0.17906 1.05877
+5.94933 6.6808
+3.43187 4.05553
+3.02912 4.68942
+2.1506 2.29413
+2.3516 2.38305
+2.87496 3.0851
+6.71294 8.99858
+3.76177 5.52545
+1.58417 2.57063
+2.74646 4.27445
+5.48407 6.60696
+-0.133321 0.716559
+3.53886 3.58196
+2.28729 2.40198
+-0.209646 1.21263
+6.62795 7.32318
+0.714781 0.880466
+2.96831 4.05932
+6.00935 6.38896
+5.39798 6.11983
+8.47679 9.70468
+1.4339 1.74845
+2.35223 4.75732
+4.31357 4.9642
+5.26493 7.70538
+7.91888 8.94851
+6.51439 7.69469
+7.69015 7.85411
+3.94274 5.15373
+6.25852 7.32402
+2.73567 3.43236
+7.09564 8.42242
+2.55932 4.29066
+1.79489 1.84559
+8.86427 9.35669
+7.23854 8.27062
+7.8488 7.98307
+0.710888 2.22424
+0.0413624 1.10578
+1.54302 1.97696
+1.64924 3.01081
+8.15535 10.2397
+0.305662 1.63835
+8.20375 9.03123
+1.66617 2.08748
+4.01691 4.88505
+3.32856 4.10709
+5.15342 5.44616
+5.80751 7.38872
+0.485341 1.07648
+3.98267 4.20211
+6.96867 9.37655
+9.48055 9.85181
+8.39277 9.50424
+2.47589 2.79873
+3.48046 5.37417
+4.98279 6.01686
+1.29845 2.31199
+-0.204348 2.50289
+0.23488 1.00378
+6.26899 7.14823
+4.62903 5.49672
+0.199052 0.822066
+6.97297 7.69083
+4.23783 4.65198
+0.530497 0.839143
+6.61355 8.22831
+-0.0103941 2.16307
+0.148601 1.20044
+0.314438 0.67632
+3.43415 4.06208
+1.95498 3.25728
+4.23094 4.84942
+9.5493 10.0057
+2.64964 3.52073
+8.21388 9.1622
+-0.112496 0.47622
+7.97551 8.19546
+2.16155 2.6289
+0.38442 1.46032
+3.85675 3.91557
+1.00605 1.42016
+2.4853 3.53086
+-0.0765625 0.504366
+8.11302 8.46334
+7.18135 7.80218
+6.46466 8.12336
+3.75968 5.33954
+9.08789 9.73677
+6.47459 7.49454
+0.90148 1.47681
+3.44733 3.54163
+7.32968 7.909
+1.30055 2.75407
+8.78735 8.92461
+8.21764 8.59414
+0.888162 1.08404
+5.65195 6.26421
+6.23881 7.33284
+8.69731 9.88088
+3.55695 5.36909
+6.49248 7.02755
+2.31407 3.01952
+5.7803 6.1286
+6.30415 8.01577
+7.73864 8.27496
+0.741078 1.69184
+4.94671 5.68254
+3.28226 5.02894
+1.97446 2.60413
+3.26555 5.54754
+2.56179 3.41897
+3.20058 3.32486
+6.96915 7.69055
+6.89302 7.39856
+1.9659 2.61404
+1.31107 1.36867
+6.23573 6.33677
+0.17616 0.517772
+8.55548 8.79155
+9.61632 10.2651
+2.20331 2.34017
+6.93195 7.42939
+1.25398 2.23119
+1.06577 1.41048
+5.99156 7.09818
+3.34821 4.1271
+4.61618 6.90956
+2.30853 3.52875
+0.0518063 0.113732
+5.38513 6.09734
+1.73468 2.64838
+7.24679 7.63999
+4.18175 5.06728
+7.09602 7.13414
+9.06191 9.11605
+6.2309 7.67675
+3.96576 4.63237
+-0.552645 1.37948
+5.76964 6.89903
+4.9272 7.5832
+4.59003 6.49719
+4.12281 6.9664
+5.12256 5.58387
+1.78859 2.76954
+4.36808 5.05712
+8.41165 9.54483
+8.11513 8.43405
+8.42016 9.52715
+8.50598 9.34564
+1.80028 1.83558
+8.08502 8.43726
+6.96667 8.12021
+5.4726 6.26772
+7.1141 9.29989
+7.83324 8.1744
+8.74368 9.16491
+2.5515 3.01706
+5.92375 6.44495
+7.45628 8.41582
+9.04829 9.71503
+4.58856 4.75356
+7.26064 7.32462
+1.81695 2.40529
+6.88067 7.95052
+1.91408 2.02663
+1.32005 1.45025
+7.47733 8.42004
+4.99403 5.85297
+0.95744 2.28875
+-0.089503 0.536888
+1.09978 2.48865
+1.9959 3.098
+0.376116 0.448329
+3.98908 6.49684
+9.10178 9.51012
+5.41394 7.31529
+6.60708 7.59071
+4.38466 5.76203
+1.84355 2.60304
+0.658705 0.933522
+6.98725 7.05509
+5.60064 6.98804
+1.0603 1.1521
+4.06192 4.46156
+0.351018 1.00807
+9.17113 10.2192
+6.71641 6.74659
+8.85392 10.5272
+4.50816 5.22908
+1.13934 2.43196
+3.3746 3.57576
+7.62137 9.3234
+6.93482 7.16058
+5.66506 6.44324
+5.13364 5.86068
+1.97257 2.03803
+2.69746 2.73067
+0.989591 1.38342
+4.18819 4.69676
+4.31608 5.12265
+2.79556 4.87763
+3.55387 5.34421
+-0.112466 0.585639
+2.43156 2.70221
+5.88314 7.08322
+-0.450332 1.29858
+1.22202 2.46588
+6.74433 7.32925
+5.14596 5.37435
+6.76754 7.41799
+1.48762 2.45958
+4.57241 5.3382
+4.17465 5.02296
+6.48856 7.5576
+0.383566 0.823394
+8.50875 9.08734
+1.79393 2.24548
+5.06812 6.49508
+3.55364 3.61502
+5.58973 6.58885
+0.631097 2.10041
+0.323995 0.941782
+8.8798 10.1036
+6.37114 6.88202
+6.9393 7.83288
+3.09503 3.41759
+3.65269 3.70305
+5.61676 5.8924
+1.90199 2.38446
+4.23683 5.35609
+9.18649 9.88878
+8.28736 8.37734
+3.04805 5.03593
+8.02926 8.38975
+3.58161 4.01331
+3.20923 3.48207
+6.85118 8.78281
+5.06518 7.49843
+1.57456 3.05552
+3.0154 4.23782
+2.83557 3.24854
+1.29358 1.89328
+1.42911 2.72661
+3.17067 3.96651
+0.353554 1.48472
+3.46227 4.25611
+6.17639 7.24657
+5.60878 7.13562
+4.11129 5.52476
+9.17596 9.4123
+3.08339 3.65766
+4.083 4.63013
+0.628465 1.92141
+7.81989 8.39386
+3.35589 3.87531
+5.35974 5.41743
+4.48321 4.64376
+0.888177 1.37343
+8.49061 8.50063
+5.09078 6.01801
+9.65314 9.99342
+1.60502 3.0115
+1.37928 2.77642
+6.60322 8.94046
+6.74573 7.45157
+-0.291156 0.325249
+6.1518 6.66827
+5.38199 6.46959
+3.50128 5.22692
+1.31774 1.70159
+0.550546 1.48845
+7.51187 7.85496
+4.2014 5.23193
+3.88255 3.97209
+2.60555 2.84958
+5.15706 6.00036
+2.99284 3.27867
+0.395077 0.768383
+3.30863 3.60594
+0.0325231 0.379208
+6.55183 7.33346
+1.44554 2.95846
+0.245421 1.29751
+3.98808 5.41226
+5.90242 6.266
+4.11097 5.02597
+0.134753 0.929866
+0.609287 1.16311
+0.231832 1.06825
+6.22093 7.05584
+9.18429 9.80637
+0.544139 1.30185
+1.69143 2.90306
+6.75109 8.67893
+5.49641 6.76104
+8.91712 10.0271
+7.09126 8.12404
+8.82958 10.2847
+0.569249 0.69421
+3.59288 5.8053
+9.25068 9.4226
+8.51607 9.26259
+5.00906 5.17068
+1.83467 2.99102
+7.32006 7.64842
+0.405532 0.603773
+6.41882 6.60495
+0.721592 1.44375
+2.78393 4.46732
+7.14806 7.16117
+5.12868 5.27918
+2.74138 3.1737
+2.95394 4.26547
+7.82827 8.21028
+9.06982 10.7279
+0.108376 0.290131
+6.34574 6.97141
+4.39022 5.50801
+7.98339 8.79674
+3.80026 4.71831
+5.43594 5.66916
+1.6743 2.61476
+4.29763 5.47402
+7.95714 8.69311
+3.4152 3.7387
+8.01715 8.8941
+6.53723 7.44437
+-0.0222108 1.04503
+4.96242 6.01648
+1.70885 1.75511
+7.62434 8.53526
+6.82863 7.39782
+8.19967 9.22283
+1.99719 2.11323
+-0.0124079 0.240201
+4.48577 4.87935
+2.586 4.41666
+6.37848 6.67092
+4.39606 5.67983
+9.39761 10.1095
+7.10866 7.15796
+3.91993 4.52129
+5.10552 5.36997
+7.08963 8.32694
+9.12669 9.58509
+9.26894 10.1974
+0.737413 1.26523
+2.77833 5.28516
+3.19039 4.36857
+4.32954 5.45614
+4.98069 5.49295
+7.54745 8.76142
+5.70425 7.05749
+-0.250513 0.36578
+4.76997 5.89607
+2.03075 2.32111
+6.54141 6.55896
+4.19799 4.45091
+8.7796 9.11915
+5.75014 6.05646
+5.36885 5.42775
+-0.00433056 0.865304
+3.65169 5.4751
+0.23625 0.872926
+0.0386337 0.792214
+4.40245 4.56789
+6.44567 7.42162
+5.51394 5.98005
+3.50146 3.83147
+8.47573 9.85647
+7.91378 8.47044
+9.44297 9.90241
+5.962 6.68782
+4.49034 4.86927
+2.17774 3.47061
+8.80614 9.26595
+7.92096 8.13838
+7.80209 7.93317
+7.78915 8.29735
+6.98111 7.162
+0.491059 1.14901
+8.97965 9.38792
+3.30207 3.53207
+3.17127 4.43581
+3.97564 4.43746
+6.79008 7.17877
+5.61669 7.51263
+4.0853 5.38748
+4.42181 6.32041
+8.08599 8.9095
+2.46938 2.55499
+1.20692 2.06351
+1.98995 2.35216
+8.17116 9.17158
+7.53414 8.37086
+3.7744 4.46197
+3.29464 4.38
+7.33246 7.81959
+4.89572 6.2831
+-0.152496 1.56427
+0.636242 0.938556
+5.62066 6.06096
+9.42994 10.473
+8.95446 9.46311
+0.277891 2.80311
+6.92968 7.29845
+2.75677 3.02975
+2.2859 2.51308
+2.96683 3.03857
+6.44584 6.49518
+8.33607 8.60407
+7.20303 7.7616
+7.07205 7.46849
+2.35677 2.7904
+5.86404 6.12906
+2.42371 4.62735
+3.27237 4.11016
+0.0668578 0.644021
+6.77371 7.45187
+3.66596 5.21874
+0.718034 0.755944
+6.06162 7.05
+6.91473 7.09753
+5.0749 6.08914
+0.759874 1.11978
+8.54591 9.64997
+3.97266 4.70679
+1.51133 3.17164
+7.21772 7.69877
+8.00719 8.37052
+0.284003 0.38001
+4.08842 4.16227
+5.04461 5.79973
+4.60604 5.31979
+2.2461 2.28157
+6.25631 7.69766
+9.12404 9.67586
+7.73134 8.98923
+1.0513 1.46408
+9.17225 9.42567
+3.66795 4.29168
+8.84403 9.28497
+9.93613 9.94729
+3.16615 5.09374
+-0.149675 1.43397
+2.30855 2.48392
+0.843172 0.951801
+8.32945 8.8506
+8.97012 9.94697
+2.8559 2.92359
+-0.321715 0.89173
+7.48565 7.71775
+1.44301 1.47795
+6.6649 6.76187
+9.10721 9.93599
+1.82207 3.03935
+3.61893 4.5306
+2.53746 3.81243
+0.424528 1.29026
+9.51874 9.68841
+7.94954 8.14396
+7.49282 7.52655
+3.04604 3.69656
+9.45461 9.47212
+7.69209 8.16412
+0.607135 1.16564
+0.150291 0.450632
+3.28914 4.01085
+5.45597 6.02921
+8.16157 8.36605
+9.76573 10.2325
+0.151994 1.07074
+1.3748 1.68548
+2.29854 2.63593
+7.92162 8.68895
+1.28795 1.61949
+7.85469 8.26683
+4.32268 6.33174
+6.13964 6.3596
+1.25714 1.88002
+2.05006 2.28294
+8.31864 8.34151
+9.0613 10.0715
+-0.041568 0.25139
+6.79984 6.81686
+5.10674 5.70583
+5.92937 7.01652
+7.57649 8.05834
+0.937157 2.25362
+7.48567 7.59746
+2.33403 2.88942
+7.3805 7.73421
+5.586 5.75327
+0.828854 2.12988
+8.22741 8.59954
+9.69214 10.1207
+6.55359 7.08114
+1.85342 2.634
+6.08756 7.28893
+6.34993 6.93474
+8.93548 10.1463
+5.49445 5.8338
+1.47951 2.14646
+2.62089 2.75888
+2.35352 3.10539
+4.98774 5.28931
+4.92239 5.40697
+7.52674 8.78948
+4.52451 4.83819
+5.45854 5.75838
+5.51553 6.3901
+4.82905 6.44407
+6.20655 6.4483
+5.68116 7.06109
+7.97301 9.15827
+8.8854 9.91623
+9.60198 10.2449
+1.93322 2.67684
+0.441852 1.87646
+5.19981 5.71385
+2.54799 2.5809
+4.34591 5.02655
+7.54678 8.75202
+6.1496 7.19033
+1.13658 1.30756
+1.38724 2.08252
+2.13624 2.30419
+8.49196 9.41369
+-0.21387 0.685093
+2.47875 4.19982
+3.69093 4.00543
+5.70643 6.50331
+7.07443 8.83588
+6.85756 7.68937
+1.69241 1.83242
+0.140565 0.502156
+2.15007 3.23784
+4.97403 5.69757
+5.08315 6.25554
+3.45026 4.01942
+3.37482 4.73009
+7.4154 8.34013
+6.95399 7.59768
+8.07995 9.86199
+8.43993 8.88645
+7.66844 8.12742
+-0.0200687 0.435846
+4.47984 5.9416
+7.66804 10.0801
+4.14578 5.98717
+0.256533 0.89254
+6.43216 7.4474
+3.60295 4.79419
+3.90129 4.29812
+5.30606 5.58674
+9.11552 9.79229
+5.60702 5.85299
+2.39514 2.64865
+4.51164 4.60227
+6.31154 6.77441
+3.12239 3.13505
+7.50962 7.89478
+3.90928 4.88831
+9.64625 10.0629
+5.9465 6.02877
+2.08554 2.10477
+0.087547 0.34748
+2.34295 2.53703
+6.846 7.3043
+1.37869 2.11446
+4.03371 4.26278
+5.38623 6.40917
+4.75848 6.25417
+6.03478 6.15991
+-0.585543 1.2091
+2.52824 3.57712
+3.95687 5.40914
+4.42955 4.71909
+2.9328 3.98848
+5.40471 6.97056
+7.64789 9.30279
+6.19595 7.07492
+8.27328 9.41596
+8.29855 9.13665
+2.54035 3.10488
+8.25038 8.87903
+5.66599 5.88701
+7.40067 8.71195
+6.63762 6.67694
+-0.0163105 1.72666
+4.77743 6.60356
+0.567991 1.14977
+5.96841 6.42987
+3.02266 4.58424
+6.72121 7.35492
+7.51477 8.65223
+8.55055 8.81014
+5.59759 5.82816
+0.218944 1.82542
+1.03197 2.36652
+7.84302 9.1594
+2.11542 4.7332
+6.37618 6.92981
+1.34963 1.59353
+0.516281 1.08859
+-0.0151152 0.0624718
+6.45603 7.23063
+4.76865 5.46588
+7.5893 8.42021
+1.04534 1.99034
+2.62638 3.04997
+5.00254 5.98512
+7.7588 9.44547
+6.82186 7.34321
+8.7629 9.82272
+-0.309554 0.54858
+4.19843 4.92981
+5.62327 6.80846
+6.40599 7.6073
+6.1547 6.53898
+3.93941 4.44985
+3.28342 3.72778
+7.17256 7.23035
+2.31269 3.05437
+7.99132 8.20926
+7.19338 8.08381
+7.29139 7.96441
+4.25818 4.4208
+0.802894 0.81938
+0.990115 1.04066
+0.443898 0.490936
+3.44459 3.95977
+9.07812 10.3145
+7.86709 8.26338
+-0.230114 0.390748
+7.50905 8.49199
+-0.715424 1.97535
+2.92248 3.12903
+5.44209 6.62431
+0.991914 1.99037
+5.92275 6.7724
+9.10818 9.2797
+4.46434 4.83462
+4.21122 5.48353
+1.8721 3.40764
+7.04713 7.60526
+3.76581 4.76317
+7.00667 7.36475
+6.87244 7.39431
+7.6349 8.46695
+-0.0728922 0.351194
+5.02925 5.6834
+1.45779 2.83702
+0.339175 1.46574
+6.40414 6.9165
+6.30401 6.91007
+5.6392 5.78172
+5.63288 6.44639
+7.45285 8.89031
+4.09741 4.57929
+8.76728 9.06448
+1.62324 1.84552
+5.72509 6.54553
+8.65273 10.3652
+7.3362 7.8953
+8.96224 10.3113
+0.217316 1.7827
+1.28523 2.90127
+8.78746 9.11602
+8.6075 9.9606
+-0.647788 0.779976
+4.9702 5.47602
+4.15553 4.57497
+1.08174 2.80993
+4.01011 4.8145
+6.79603 7.2317
+4.3711 4.43566
+9.65087 9.79922
+8.19407 9.21784
+3.04008 4.94094
+6.0883 7.23919
+6.88708 6.97172
+0.438073 2.00665
+8.53083 8.83004
+4.22258 4.65233
+6.72856 7.61085
+3.17591 3.18978
+5.07955 5.6938
+2.09043 2.55351
+3.28085 4.43556
+7.29225 8.03925
+7.78034 7.82608
+6.59677 7.67719
+5.56032 6.38139
+8.72663 8.82535
+2.96505 3.11983
+1.67192 2.11727
+7.85386 8.49025
+6.30965 6.72799
+8.53082 9.3801
+2.8976 3.39972
+8.90427 9.44661
+-0.0665785 0.410254
+4.58099 5.81135
+1.88015 2.21838
+3.38693 4.10149
+7.46378 7.68246
+8.80985 9.72212
+6.54877 7.25642
+7.18249 7.71509
+7.41978 8.64805
+1.00839 1.78626
+0.39421 0.526751
+7.13516 7.28317
+7.28011 7.80573
+1.90158 2.49032
+1.66181 4.17994
+8.81106 9.21133
+9.46151 10.5007
+0.52585 0.575082
+7.66495 8.64072
+7.72794 8.50991
+4.92409 6.23879
+2.28769 3.21774
+3.62671 4.40932
+5.77688 7.31314
+8.94253 10.0664
+0.416618 0.635111
+1.81377 2.41356
+7.91755 8.83363
+1.62715 1.82626
+8.22065 9.51656
+0.020228 0.724724
+8.81119 9.95764
+8.66509 9.61079
+5.28201 5.32152
+3.95724 4.22138
+7.09339 7.77685
+9.63428 10.1514
+3.69117 3.779
+3.82195 4.76757
+5.75824 6.62265
+3.69984 4.75163
+3.58259 4.8788
+8.32635 8.85873
+5.81959 7.32506
+8.11265 9.14304
+2.20118 3.32511
+7.79582 8.52691
+6.5891 7.13584
+0.385393 0.440656
+1.13414 1.9951
+1.76482 2.69977
+4.76194 5.82757
+6.33633 7.5348
+4.7663 5.65083
+1.98298 3.01285
+0.956973 2.38629
+5.60955 7.65827
+9.11064 9.14351
+2.99933 3.37975
+3.36304 4.57437
+3.89886 4.50733
+8.73838 9.3514
+9.11824 9.66042
+1.47961 2.93909
+0.615297 1.13217
+1.70646 2.32478
+4.35168 4.99362
+0.986601 1.18332
+4.01551 4.92342
+7.68944 9.86838
+4.47611 4.85316
+0.051839 0.86288
+3.59624 5.5628
+7.08729 8.90374
+9.53464 9.9196
+4.69871 5.74189
+8.43146 10.6889
+3.23774 3.77777
+9.35399 9.62741
+1.15259 2.69451
+6.6368 7.33773
+5.26395 6.09857
+6.87415 7.21717
+-0.925645 1.06118
+8.49641 8.67659
+2.31486 3.25354
+2.51057 2.58303
+0.921997 1.48762
+6.29777 6.74738
+4.03945 4.27305
+7.1668 7.3471
+8.44572 8.80343
+7.16937 7.84526
+8.89008 9.4332
+7.01815 7.66319
+-0.420804 0.982878
+1.59755 1.64672
+0.700814 0.72579
+6.3138 7.37379
+8.49276 9.93522
+-0.795656 0.819657
+0.772253 1.05926
+0.917593 1.3917
+3.30076 4.12274
+-0.0237176 0.260552
+6.82385 7.49119
+6.98638 7.52012
+8.24915 9.08397
+4.17486 4.25908
+3.08435 4.64404
+8.17114 9.91412
+8.95923 9.3751
+0.596707 1.89462
+0.982917 1.40236
+6.79552 7.36657
+8.2599 9.69551
+8.85126 10.4342
+7.98967 9.14514
+0.766355 1.63286
+7.76211 7.99247
+5.23163 5.89338
+4.4707 5.50457
+9.257 9.27862
+2.11049 2.59654
+1.65501 2.06238
+0.551768 2.10873
+0.0285582 0.194421
+3.66153 3.85615
+5.07097 5.55806
+5.29145 5.80735
+2.03499 3.0863
+0.73171 2.29494
+2.63023 3.6417
+6.17478 6.25997
+5.79646 6.46363
+9.10633 10.5516
+7.23415 7.84823
+6.49951 7.1506
+9.94647 10.0242
+7.91236 8.09097
+7.8127 7.97662
+3.34238 3.42907
+8.50796 9.8311
+8.75792 8.98028
+9.34125 10.4441
+2.84413 3.71602
+1.49884 2.35652
+7.52317 9.18955
+9.5587 10.3525
+4.85436 6.1181
+5.91369 6.12194
+6.88463 8.34471
+1.51952 2.99156
+4.29022 5.12674
+8.0229 8.41246
+2.44841 3.04779
+7.59975 7.91485
+2.74491 3.62575
+0.0169968 0.240919
+5.85351 6.29039
+4.99825 5.93439
+2.153 3.35304
+1.19032 1.41763
+6.13337 7.80615
+7.05013 7.89364
+8.38056 9.92
+6.35525 6.64521
+3.93342 5.15885
+2.87656 3.47116
+3.56176 4.41159
+6.72084 7.9171
+8.03801 9.12442
+1.03329 2.56255
+7.64542 8.61709
+2.85627 2.89437
+8.8303 9.79838
+1.08032 2.34573
+7.51366 8.39169
+9.09685 10.3677
+6.753 7.41904
+-0.217662 1.42059
+6.72492 7.97553
+7.99325 8.8976
+0.765372 1.10894
+4.37958 6.04671
+8.72027 9.58928
+6.00234 7.29277
+8.43912 9.25356
+2.98816 3.17389
+0.4292 0.552167
+1.69827 2.80318
+5.99904 7.09981
+4.68367 5.87791
+-0.203208 1.09587
+2.65367 3.28472
+3.87051 3.88111
+6.36178 7.18853
+-0.0815935 0.200848
+6.82255 7.18488
+4.99295 5.08405
+2.67155 3.08447
+5.82099 6.77145
+8.76434 9.01086
+5.94982 6.18665
+3.23369 3.71743
+0.934129 2.73456
+1.13233 1.24208
+8.21931 9.03906
+6.25425 6.69972
+0.971299 4.21205
+5.68426 6.45281
+2.85786 3.3955
+8.17715 8.88439
+2.72802 5.01235
+6.12811 6.53711
+5.22878 6.45864
+0.453655 0.922032
+0.466162 0.85262
+2.40916 2.64759
+5.63583 6.37476
+2.18434 3.14105
+0.912811 2.08432
+8.9464 10.1515
+6.77323 7.27133
+0.7167 1.60579
+5.89813 6.32997
+7.66593 8.4611
+6.54145 6.88337
+5.95421 6.21188
+1.10383 1.92226
+5.37168 5.65707
+1.51874 1.66339
+4.60748 5.00384
+8.97354 10.5394
+2.05022 3.20373
+8.17316 8.19283
+2.33792 2.72643
+8.81577 9.3704
+5.95738 6.59855
+5.69025 6.17335
+6.91889 7.88142
+2.17529 2.81528
+6.65046 7.19698
+7.10694 8.78046
+2.09613 2.47484
+1.92423 2.25333
+-0.0906039 0.861376
+6.61481 7.70609
+6.7448 6.84276
+3.43655 5.28405
+6.05404 6.48902
+3.24637 3.36149
+5.69528 5.77157
+5.12352 5.31024
+7.65858 8.80828
+3.69209 4.4851
+0.25765 1.29637
+3.1537 4.13191
+3.12328 3.83765
+2.99798 4.8748
+4.49566 4.67827
+3.50822 4.03987
+8.00334 8.34084
+8.61039 9.00704
+0.0332147 0.166124
+4.55193 5.36546
+4.20308 4.31589
+0.955466 1.20095
+-0.382972 1.47625
+0.803913 1.01916
+3.78333 4.0707
+6.58604 6.70173
+3.02066 3.82562
+1.16515 2.2816
+7.87242 8.24214
+4.057 4.60368
+2.84714 3.59726
+2.77804 3.69136
+-0.139996 1.36416
+4.50647 6.37579
+8.86647 10.1549
+9.24372 10.1442
+0.743107 1.84722
+6.18761 7.65841
+0.214887 0.443938
+8.8513 9.55063
+4.04856 5.79916
+6.69671 7.10025
+6.97477 7.79702
+4.82551 5.10538
+0.821772 2.85828
+9.3086 9.74805
+5.45623 6.66668
+7.64296 8.67451
+7.53052 8.31024
+7.45352 7.5063
+1.31412 1.4979
+7.81176 8.48083
+0.228964 1.73207
+5.52579 5.93103
+6.58544 8.48938
+2.75407 4.18746
+3.21396 3.96298
+1.13806 2.34106
+0.899331 2.87945
+5.69016 6.61624
+2.48172 2.58082
+0.676004 1.43405
+3.41766 3.9503
+0.104554 0.298373
+6.50673 8.21831
+6.00349 6.69385
+9.62453 10.3147
+4.09379 6.02911
+-1.12803 1.68823
+1.83324 3.43133
+8.30576 9.09288
+-0.363911 0.405218
+1.91686 3.34928
+6.98331 7.15885
+-0.31591 0.996789
+0.145813 0.35408
+5.32016 6.13679
+6.99664 7.48644
+-0.140875 0.821045
+9.0119 9.19742
+1.69616 1.72453
+4.38064 5.07542
+6.85898 7.55478
+3.9145 4.27935
+5.77592 6.16806
+1.45345 3.01301
+4.13024 5.59662
+8.14557 8.41669
+4.00075 4.829
+-0.283024 1.59436
+5.92468 7.17507
+6.84458 7.18356
+1.06987 1.42839
+8.618 8.66235
+0.432802 1.59512
+3.78058 4.36051
+1.6113 4.21135
+6.73475 7.01057
+6.74819 6.90498
+6.93146 8.54681
+9.02605 9.91613
+3.888 4.00526
+1.07958 2.27915
+4.78456 5.10764
+3.92952 4.89555
+9.09348 9.30304
+6.73107 7.21036
+7.42366 7.73225
+4.04079 4.72919
+1.21726 1.34683
+8.82903 9.73504
+0.577663 1.00786
+1.56822 2.08675
+4.84315 5.44994
+1.01008 1.16524
+5.99782 6.01535
+0.996739 1.75305
+4.76128 6.39012
+8.93563 9.51972
+-0.0698166 0.453543
+5.9084 6.95139
+0.535401 0.692258
+4.80729 5.48335
+3.42581 4.76147
+3.58715 4.43541
+7.50236 7.71227
+5.19742 5.87901
+1.79752 2.43097
+7.29762 7.57608
+5.65169 6.47762
+6.02249 7.93642
+0.840131 2.81176
+6.2646 6.96911
+7.46014 8.17136
+9.79049 9.94054
+4.61094 5.35819
+7.30902 7.41873
+1.21883 1.84621
+6.41743 6.57736
+1.53114 1.62859
+6.73237 7.47083
+6.05618 7.56831
+7.63374 8.16821
+5.20839 6.05382
+0.619043 1.44065
+2.38657 4.88786
+3.88289 5.18788
+4.42283 4.51106
+9.15575 9.22388
+3.18678 3.72243
+3.20638 3.65935
+4.2219 4.97961
+4.63725 6.90959
+2.57123 2.59101
+4.08581 4.37325
+6.53926 6.80412
+1.77475 3.89149
+9.22854 10.426
+2.67375 4.36551
+3.17194 4.0433
+1.10304 2.0348
+3.67233 4.04957
+3.23526 3.5012
+5.17684 6.47301
+4.4 4.67662
+4.15842 5.85903
+5.88496 6.61616
+7.26489 7.51279
+4.17402 6.6997
+-0.540216 0.54573
+4.36063 4.60442
+9.18146 9.96239
+0.977216 2.42032
+9.09143 9.61178
+5.06686 6.23076
+2.04772 2.92048
+1.4154 2.00707
+7.80442 9.54824
+4.55549 4.7148
+7.56964 8.80172
+1.35347 3.21648
+9.12751 10.0605
+1.81735 2.06061
+5.63798 8.0918
+6.79492 7.98002
+9.23053 10.1299
+1.74639 2.02724
+3.71825 4.09879
+2.4995 3.42493
+4.1255 5.66758
+4.75493 6.99687
+8.22481 8.72036
+6.13689 7.53026
+5.41315 5.66358
+4.21425 5.62743
+6.22936 6.44392
+2.02303 2.96414
+-0.0655462 0.130508
+6.1487 6.70994
+4.36674 6.24985
+7.51129 7.63176
+7.9729 8.98613
+3.92117 4.15596
+4.54398 5.43399
+6.34248 6.92305
+-0.550253 1.16167
+9.15142 9.53717
+8.99354 9.65952
+6.28988 7.90053
+3.36505 3.782
+8.80005 9.70553
+1.99947 2.18573
+1.15023 2.07069
+0.253723 1.32958
+2.0392 2.93977
+2.89024 3.00836
+8.16735 8.2049
+1.49508 2.95258
+6.19092 7.44552
+2.33328 3.06758
+6.44166 7.4649
+7.34749 7.79488
+7.5557 8.04141
+2.76812 5.13617
+7.97308 9.25668
+4.73539 5.22234
+7.53377 8.41651
+-0.355405 1.36499
+4.72111 4.73744
+-1.22753 1.84842
+5.5033 5.63808
+3.95421 4.19313
+6.24752 6.98229
+4.49694 5.07277
+3.70871 4.30093
+1.31984 1.50116
+7.16044 8.70868
+2.44587 3.34659
+6.08322 7.20376
+2.75012 2.82555
+0.0394442 0.863634
+3.90896 4.73696
+4.77494 5.04158
+8.41473 8.82932
+1.7049 2.71024
+9.01684 10.1044
+4.57959 5.01066
+3.2484 4.21875
+1.11596 2.88792
+3.53616 4.14001
+5.80672 5.82478
+5.85844 7.70293
+6.18239 6.30124
+2.22913 3.23412
+2.97521 3.08481
+2.2749 3.70611
+2.3457 3.86609
+2.71695 4.04473
+7.22863 7.40115
+1.80428 2.39815
+1.80781 2.33028
+2.78662 3.14936
+9.40717 9.94906
+6.54968 6.80773
+2.76862 3.24492
+1.96034 2.87404
+3.53295 3.54927
+5.36042 5.67073
+8.63339 8.93752
+0.932415 1.70402
+4.32923 4.55594
+9.3491 10.4969
+0.121416 1.15499
+-0.172998 1.36319
+2.02349 2.29887
+1.75352 2.35329
+0.502555 2.01665
+6.71754 6.80014
+3.35175 3.93337
+7.17133 7.9851
+8.51299 9.95771
+5.86103 6.36734
+1.44593 3.46008
+4.49699 4.60855
+2.29261 3.10053
+6.68713 8.19499
+5.43776 6.84387
+8.58591 9.02134
+5.24746 6.15595
+1.3847 2.5074
+6.62143 7.07775
+1.7101 2.077
+9.70898 10.2789
+6.67451 7.92058
+2.56858 3.60374
+1.61917 2.60482
+1.77902 2.16908
+4.76209 6.00461
+3.8894 3.98269
+7.0278 7.276
+5.4866 5.59417
+1.69306 2.92506
+2.45744 3.76592
+2.5689 2.80611
+5.98283 6.06154
+9.5267 9.9626
+9.55652 10.4128
+6.6111 6.64606
+3.38826 4.26111
+3.61887 3.73455
+4.14924 6.13796
+7.15863 7.28212
+5.78984 6.56662
+2.09304 2.2681
+4.39867 4.88557
+6.20907 6.81034
+4.63336 4.91476
+0.939805 2.43621
+1.56774 5.13599
+8.40908 9.82058
+2.06273 2.20306
+2.53524 5.01482
+2.9314 3.23661
+2.48535 3.47368
+0.366389 1.4699
+8.81131 9.01654
+2.05102 2.87972
+1.9699 2.22723
+6.18333 6.98224
+1.3425 2.4443
+0.767883 1.77423
+3.1538 3.43248
+0.891006 0.903458
+5.7136 5.8713
+0.437569 1.37539
+3.98533 5.01646
+8.65764 9.89518
+3.74889 3.98561
+7.74507 8.30657
+8.24671 8.43006
+6.88467 7.42036
+1.99426 2.03522
+1.90486 2.04181
+1.12911 1.71807
+9.25253 10.105
+1.92989 2.0346
+5.60044 6.25585
+9.16848 10.087
+6.67824 6.72257
+1.88522 2.80222
+0.242758 0.852689
+5.09249 7.71484
+5.54974 6.44414
+7.66767 8.72936
+3.48884 3.83156
+3.4697 5.14646
+8.48582 8.7692
+6.76259 7.06897
+7.83856 8.62005
+5.81853 6.76571
+2.04803 2.94439
+6.85396 7.22985
+6.52449 7.39764
+9.26838 9.34809
+4.64449 5.64975
+7.51845 7.80279
+-1.27268 1.65344
+0.686101 4.20373
+7.80552 8.37119
+7.20419 8.35284
+9.33962 9.87975
+4.31238 5.58683
+2.39198 3.84398
+1.29248 2.59269
+4.71612 6.195
+5.27332 6.52174
+7.71492 7.84702
+8.18064 8.72233
+1.55223 2.31294
+6.34374 7.31758
+6.48966 6.92611
+2.62268 3.09895
+4.09064 5.06197
+2.66367 4.12126
+1.53391 2.93092
+8.64516 8.70655
+9.20047 9.28957
+4.00474 4.11716
+8.5418 9.45901
+8.73386 9.73253
+9.22596 9.63179
+1.34204 2.7834
+8.4489 9.21027
+7.75158 8.51085
+5.98856 6.11212
+1.29906 2.08111
+9.24315 9.76291
+6.84345 6.91607
+5.88294 5.90545
+3.03022 3.39941
+3.22222 3.4089
+1.12791 1.65898
+6.70232 7.36336
+8.60042 8.82377
+1.26451 1.30362
+2.76682 2.92693
+1.54763 2.19582
+6.5865 7.24173
+4.15242 4.21742
+8.39615 8.78524
+1.67017 2.08717
+9.03012 9.97041
+2.31463 2.45877
+8.29872 8.51813
+1.66689 2.51919
+-0.807606 1.47794
+1.31452 1.94418
+0.0739222 0.512106
+4.23577 4.25889
+7.45273 7.97505
+3.34234 3.46608
+7.97304 9.14131
+1.9029 2.99946
+8.84087 9.79689
+4.92769 5.68685
+2.74004 3.04513
+0.889257 2.20448
+3.10574 3.9758
+3.91547 4.32303
+7.17475 8.07377
+5.92903 8.03738
+1.57974 1.65527
+3.76339 4.2285
+2.28263 2.7559
+9.53105 9.87477
+2.10154 3.2222
+4.23683 5.34347
+1.38769 2.48482
+5.39838 5.51872
+8.50975 10.1382
+8.04108 9.21474
+8.5252 9.67823
+8.893 10.7726
+7.1294 8.18211
+1.15642 1.73882
+0.436911 0.756698
+3.66142 3.71659
+6.37686 6.7
+8.88506 8.99896
+2.31891 3.79061
+2.61615 2.81909
+1.35216 1.39571
+3.04217 3.52564
+7.8409 9.34099
+0.470596 1.49157
+6.94014 7.18365
+8.05483 8.49979
+8.18511 8.25608
+7.03597 8.45251
+2.47411 2.65172
+0.112716 0.193057
+4.45039 5.10584
+4.53906 5.80013
+5.11702 5.27151
+1.24211 1.90757
+4.64114 4.72912
+1.77254 3.45037
+-0.1275 0.99675
+5.69637 7.67722
+2.21252 2.44032
+3.89623 4.40192
+2.79904 3.15569
+8.37911 9.42424
+5.27199 6.2026
+1.84791 3.75411
+0.522801 0.54806
+3.83644 4.64785
+6.65497 7.55638
+6.75104 6.98564
+2.34979 2.98049
+8.27176 8.60459
+5.07773 5.44064
+1.16934 1.98872
+4.2914 5.37557
+6.83462 7.95408
+3.91405 5.73229
+7.77473 8.53538
+9.23441 9.90185
+4.03659 5.2473
+5.99336 7.8004
+4.2432 5.89276
+6.39847 7.81276
+9.13909 10.4164
+1.12009 2.5649
+2.35157 3.18468
+4.46918 5.55572
+3.82512 5.53666
+7.18238 8.10193
+8.40911 9.23639
+8.99555 10.4192
+6.69547 8.87825
+4.79012 5.34858
+9.23615 10.0986
+-0.590587 1.14603
+2.74289 3.48244
+-0.248403 1.1591
+3.35663 3.7229
+7.37504 7.6481
+6.64796 7.64695
+0.778081 2.41212
+4.49242 4.7772
+8.01419 8.109
+6.6494 7.76619
+8.86331 10.1205
+0.817273 0.937855
+8.00019 8.21556
+6.19405 6.54794
+6.11798 7.30421
+3.40164 4.28921
+5.31927 6.21584
+2.79377 3.40938
+3.59494 3.90321
+7.79218 10.3132
+2.99546 3.86111
+1.71916 3.40283
+6.1768 6.81915
+7.59629 8.68568
+1.59724 2.348
+6.20151 6.5391
+6.30798 6.70478
+0.489786 1.51322
+1.28396 1.86775
+5.18031 5.43007
+6.61276 7.70565
+1.4909 2.11165
+4.56163 5.49277
+1.93598 4.35147
+3.65568 5.00224
+1.68028 2.00363
+7.82874 8.67399
+1.23053 2.87598
+-0.164275 0.194491
+2.58349 4.01302
+1.23279 2.02984
+0.599702 1.09257
+9.50965 9.80164
+2.33108 3.58037
+4.38659 4.62378
+2.65097 2.87349
+0.0537058 0.576502
+4.20415 5.15693
+5.41458 5.98382
+4.37747 5.10347
+2.62536 2.70073
+6.96845 8.15356
+6.91533 8.41638
+9.36431 9.58863
+6.13019 7.25915
+2.7818 3.4951
+9.44641 10.1301
+2.68817 4.19772
+5.65664 5.6814
+8.25308 10.498
+3.50374 3.64458
+1.47063 1.78567
+8.21901 8.98152
+3.99261 4.47339
+2.51395 3.38788
+4.66178 5.24959
+9.08415 10.3467
+5.92351 7.20447
+1.74145 2.35957
+7.62653 8.96797
+6.43542 7.68775
+5.49047 6.56355
+4.9225 6.22555
+0.257967 0.704837
+3.42488 3.52873
+8.67606 9.77824
+5.12981 6.37856
+5.97359 6.32151
+1.58517 2.28129
+0.530687 1.54545
+7.04056 8.15296
+1.8541 3.1902
+9.46286 10.0098
+3.17967 4.02237
+3.49966 3.80271
+6.24894 6.49618
+1.19944 1.59215
+5.30422 6.94823
+7.49137 7.78584
+7.02669 8.16282
+2.21673 3.36471
+7.66183 8.34763
+4.13876 4.87421
+3.0199 4.07124
+8.40439 8.82943
+-0.274649 0.429602
+6.11215 7.65609
+3.34781 5.03006
+1.28231 1.77258
+7.57256 8.59456
+5.36208 5.81735
+7.18511 8.96618
+8.86053 9.49567
+5.39097 5.93211
+6.59094 7.26553
+3.69159 4.01914
+8.73797 8.81611
+1.41144 1.82827
+7.83555 8.07567
+6.13821 8.44907
+5.83432 6.48744
+2.93596 4.66271
+7.03215 7.59658
+1.65252 2.45337
+2.91358 4.90129
+8.94415 9.14642
+5.21005 6.1166
+0.33225 1.17039
+7.40089 8.07586
+9.30427 9.40776
+2.34188 2.81124
+1.02811 3.3344
+6.28117 7.62089
+4.80105 7.10049
+8.90252 10.0057
+2.20932 2.33093
+8.20746 10.6268
+4.31887 5.23945
+9.258 9.8985
+3.80742 4.15057
+1.11313 1.23711
+9.53067 9.70165
+7.95467 8.67187
+9.66031 9.83223
+3.61385 4.09571
+0.623148 0.652817
+7.77809 8.62118
+0.86157 1.98606
+3.12528 3.75815
+1.9363 3.22621
+8.23521 8.99175
+8.95406 10.4487
+3.38526 3.90652
+0.34281 2.0226
+0.739384 0.793829
+3.55637 3.96384
+6.1562 7.28647
+5.30211 7.51385
+1.46275 1.78688
+-0.0144662 0.868488
+0.0740443 0.119828
+9.26206 9.83923
+0.743397 1.40754
+4.68823 6.62985
+8.8291 9.17373
+4.66711 5.09313
+4.023 4.44994
+5.68937 5.79194
+8.04835 8.06763
+6.94662 8.00075
+0.774686 1.13428
+0.381819 2.34757
+2.1235 2.63524
+5.42795 6.89998
+6.07662 6.29083
+6.47821 6.7872
+2.58305 2.6192
+-0.598336 1.23458
+4.29089 5.43332
+8.09914 8.28229
+5.05925 5.35258
+0.181705 0.444466
+3.27849 4.79932
+0.310314 1.43125
+1.13836 2.76825
+1.2529 4.09336
+0.198106 0.608625
+1.77442 2.23777
+6.29823 6.64574
+1.22125 1.37929
+1.77592 3.04011
+1.43999 2.90926
+4.20495 5.32396
+4.98874 5.33211
+8.36483 8.67875
+5.65373 7.14132
+2.8303 3.05037
+3.41509 3.54032
+7.21702 7.85857
+5.79848 5.8913
+4.52711 5.65511
+2.04663 2.66919
+5.76363 6.77903
+-0.153046 0.77878
+4.37474 4.49936
+6.86786 7.81999
+8.92084 9.16368
+7.5975 8.56954
+0.197493 1.07503
+3.99803 4.67019
+9.35123 9.60094
+1.46442 2.4256
+5.21501 5.79612
+8.80879 8.99085
+-0.109252 1.30631
+7.34965 7.87947
+7.08703 8.12723
+0.985946 2.14663
+0.48521 0.856118
+6.57719 6.70623
+8.71165 8.72286
+3.16883 4.8714
+-0.21189 0.412944
+3.6526 4.37121
+0.364649 1.3363
+9.27722 9.35135
+3.47517 3.8793
+5.67149 6.28631
+6.52789 6.61039
+9.36323 10.4189
+4.30743 6.18638
+7.93653 9.4877
+8.24024 8.41475
+2.75692 3.13935
+8.80223 9.1489
+3.42656 3.90557
+8.96598 9.3217
+1.99582 4.84803
+5.1178 5.8688
+4.47901 5.73433
+7.30397 7.85527
+0.18463 0.656832
+7.80806 8.41666
+8.50023 9.42628
+7.67563 8.64756
+9.46783 9.52169
+2.06797 3.3107
+5.08863 5.10167
+0.82146 1.39055
+7.5428 8.04736
+9.09407 10.8208
+9.15219 9.99706
+1.61637 3.46354
+5.3812 5.96247
+9.34115 9.73575
+6.49221 7.30031
+1.56337 3.39704
+8.463 8.60841
+-0.322779 0.658242
+8.50173 8.72125
+0.854851 1.83405
+7.81945 8.12841
+2.60724 3.19985
+5.03714 5.55331
+1.85041 3.36816
+7.26119 7.64364
+5.75223 5.99653
+4.00026 4.43863
+5.00939 6.03009
+6.22879 6.6638
+6.44231 7.18622
+1.66002 1.88587
+2.59781 2.84919
+4.96399 5.40545
+5.70327 6.95018
+6.97141 7.08346
+3.98535 4.6179
+5.96795 7.14997
+5.07581 5.8262
+4.65665 4.98851
+8.65646 8.70986
+3.04175 3.19155
+0.796073 1.0952
+8.24859 8.57828
+5.26952 6.34245
+7.94685 8.78542
+0.193963 0.968524
+6.61159 6.80186
+9.37533 9.79195
+8.94048 9.74959
+5.77272 6.48616
+6.0092 7.86718
+2.52621 2.58938
+8.91347 9.22421
+4.20466 5.45909
+4.82157 5.09167
+7.35464 7.36611
+5.12413 6.45063
+2.12404 2.81187
+8.88875 9.20752
+2.59731 3.20587
+1.54772 2.08968
+6.70449 7.08952
+-0.0967146 0.888521
+3.10207 4.34815
+1.20807 2.35497
+6.00753 6.08492
+3.21837 4.00446
+4.34095 6.0963
+4.24821 4.79576
+4.49523 6.6669
+1.49483 2.52552
+0.0411497 0.641526
+8.3854 9.20954
+8.12419 8.93702
+0.0201515 1.06914
+1.57617 3.44176
+1.4173 1.76847
+5.42261 6.51539
+6.6744 8.46109
+3.05234 3.59179
+6.49059 7.24618
+7.01989 7.69901
+2.34664 2.90601
+9.17324 9.86754
+5.50919 5.70258
+2.40486 4.6009
+3.74368 4.00093
+6.9211 7.33554
+7.41358 8.7413
+8.78284 9.62033
+2.96753 3.01602
+-0.200693 0.535532
+6.4383 6.45049
+8.28835 9.42148
+4.2379 5.35128
+4.68397 5.04593
+5.7185 7.03177
+5.37494 6.43977
+2.99518 4.08138
+7.28064 7.54638
+9.10622 10.4907
+1.23839 1.50915
+6.7823 9.24533
+8.45679 8.62427
+0.106718 0.69304
+2.84119 3.50375
+3.60466 4.51338
+8.04709 8.19023
+3.31632 3.48054
+5.9027 7.46331
+-0.621072 1.13003
+8.57167 8.69262
+0.301047 1.42246
+1.24229 2.44616
+0.962706 1.55754
+8.77327 9.55275
+1.77899 2.44335
+0.368575 1.84726
+9.05918 9.07832
+6.61723 7.68015
+8.59899 8.80383
+-0.133927 0.20271
+5.69266 5.74809
+0.68202 1.52342
+7.17359 7.91482
+5.74049 7.34297
+7.88371 7.9683
+1.58749 2.26543
+3.96728 4.45988
+5.4354 6.88336
+1.68706 1.6976
+6.56907 7.40696
+0.518151 0.724124
+8.99155 9.36995
+6.00506 7.91529
+5.26967 6.11536
+2.37416 2.50887
+8.47983 9.31509
+2.38155 2.54346
+8.08415 9.65214
+1.00693 3.19203
+1.6523 1.73553
+6.85283 6.9958
+4.11425 4.90193
+1.39597 1.58725
+5.05551 5.19458
+5.89969 6.11394
+5.9148 7.26824
+9.32271 9.93989
+1.62911 2.58215
+5.43399 6.14203
+3.11393 3.58792
+8.57619 9.3788
+2.23349 2.7884
+8.09022 8.54326
+9.7114 9.87076
+5.91086 6.10885
+7.35805 7.57276
+0.650002 0.879866
+3.24977 3.75531
+2.73948 3.41051
+3.08006 4.62772
+3.71868 4.31519
+4.13905 5.78577
+1.77297 3.02983
+5.85931 5.89333
+3.68972 3.93193
+1.43922 2.98425
+6.51534 8.33386
+6.6821 7.50874
+1.2541 2.11722
+5.40634 5.54411
+4.55502 4.60346
+4.32484 4.68497
+3.40711 4.31975
+9.20893 10.0853
+6.12594 6.9009
+0.12664 0.347193
+7.53378 8.82258
+7.79572 8.91645
+2.50098 3.39701
+4.17873 4.97732
+1.05822 2.47032
+3.1012 4.97736
+8.42126 8.74568
+7.83301 8.17843
+9.26618 10.584
+3.02667 3.7128
+8.30654 8.69242
+2.87173 3.43275
+6.59917 7.54843
+7.03447 8.20283
+5.75718 6.40637
+2.62899 4.1855
+-0.520148 0.902194
+5.1538 5.61763
+1.25625 2.33142
+4.16336 4.3384
+3.01296 3.41026
+3.16515 3.26305
+2.40944 3.21897
+6.80742 8.57141
+1.15125 1.54824
+8.72251 9.50878
+3.15703 4.04482
+0.470308 0.726093
+0.199979 0.878243
+7.8908 9.17915
+6.91793 7.16038
+4.64783 5.00217
+2.21237 3.03073
+1.5825 1.63362
+3.18806 5.20795
+5.92725 5.95595
+4.65027 5.09868
+6.42204 6.87201
+8.08637 9.40221
+4.95542 6.16185
+7.45987 7.57979
+8.826 9.13961
+4.42078 5.27977
+7.26216 8.97585
+2.26919 3.33512
+9.4077 9.81908
+0.722223 1.03378
+-0.0497795 1.19355
+8.22686 9.31082
+0.0733766 0.93037
+7.47883 7.9062
+5.28731 5.74181
+1.78496 3.61348
+0.690987 0.764344
+2.56442 3.54999
+4.27944 5.43124
+4.04412 5.35376
+0.663756 1.88268
+1.73567 1.78553
+8.07666 9.41842
+7.70138 8.42873
+9.27113 9.55873
+0.982413 2.5565
+0.994807 1.02007
+5.01226 5.31923
+8.87435 10.0597
+1.74836 3.22578
+0.151528 0.191719
+5.82608 6.06438
+1.17239 1.59955
+3.18515 4.11049
+1.92258 3.70604
+1.63692 1.8266
+1.83542 2.66228
+2.21954 3.11425
+3.97546 4.3928
+0.731374 2.05705
+5.44809 5.96359
+9.85934 10.0553
+8.42169 9.63654
+6.68148 8.43446
+2.00014 3.3485
+0.735924 1.73
+1.61833 3.05643
+7.87934 8.67316
+8.67441 10.0032
+0.794573 1.2493
+6.11926 6.41441
+5.2715 5.82597
+9.41854 9.46625
+3.46299 4.06742
+5.6487 5.79053
+1.46503 3.43496
+0.9957 1.53939
+2.4714 3.1301
+0.887049 1.6196
+3.04884 3.19662
+1.24337 2.05758
+7.61142 8.55766
+0.998279 1.64425
+4.74917 5.85236
+2.97632 3.94611
+4.11786 5.62709
+7.40498 7.62083
+1.47854 3.64736
+2.1176 2.64511
+4.55533 5.89436
+7.44618 9.79926
+-0.410242 0.737348
+5.719 6.30861
+8.33692 8.38222
+8.78122 9.98195
+3.75452 4.26866
+2.23771 2.44985
+6.72455 7.61362
+5.9797 6.58846
+6.72885 7.60315
+-0.710302 1.18332
+7.73287 9.383
+6.61213 7.67394
+4.12945 5.68527
+-0.300887 0.341615
+5.77978 6.41534
+8.34001 9.96874
+1.62323 1.8283
+1.71788 2.23905
+7.43484 8.0418
+3.47322 3.8047
+3.47311 3.51261
+7.82093 8.86377
+2.46973 2.99125
+7.91166 8.55065
+3.39807 3.43599
+8.94792 10.0437
+7.70859 8.32487
+5.86852 7.13103
+7.64996 9.19033
+6.66742 7.8092
+7.88241 8.58675
+9.42939 10.3479
diff --git a/wasserstein/tests/data/test_5000_B b/wasserstein/tests/data/test_5000_B
new file mode 100644
index 0000000..5f6e43c
--- /dev/null
+++ b/wasserstein/tests/data/test_5000_B
@@ -0,0 +1,5000 @@
+1.17434 1.46837
+2.58198 4.16589
+0.234041 0.968658
+1.52703 1.59579
+6.7103 7.44033
+3.19227 4.41539
+5.42556 5.57369
+3.45417 4.86089
+3.82256 4.1092
+7.82551 7.90784
+3.9384 4.71796
+5.60335 5.9054
+7.96663 9.8987
+6.30305 6.64853
+7.33246 10.5316
+0.623312 1.09008
+2.63041 2.64616
+5.36028 6.28956
+4.64202 5.91858
+7.55219 7.96304
+7.73736 9.18221
+1.67114 1.84851
+5.07514 5.12159
+7.03732 7.05228
+7.5006 7.59212
+0.244947 1.55875
+0.0170454 1.10485
+1.95394 3.53669
+5.66015 6.01949
+5.88211 7.64639
+7.46698 9.27085
+6.37429 7.10154
+4.54535 4.81932
+8.21203 9.35896
+4.89933 6.20802
+3.68683 4.17831
+0.477467 0.828394
+6.17871 6.77834
+9.77523 9.92676
+0.854808 2.38709
+7.93326 8.3553
+2.10917 2.27771
+4.07045 4.72793
+8.2016 8.8011
+2.9205 3.95746
+2.89806 4.39725
+5.5654 5.78669
+9.5219 9.98543
+7.08591 7.19588
+8.35359 9.57893
+9.81348 10.0345
+8.5994 9.71835
+5.43903 7.25234
+1.82768 2.92724
+4.44952 6.79754
+5.66747 7.34386
+5.88153 6.39253
+3.34008 4.22032
+2.46068 2.76051
+0.370778 2.61681
+6.02508 6.26809
+4.32654 4.93262
+7.41536 7.99616
+8.84229 9.87911
+3.8551 5.84353
+1.56832 2.34694
+6.96099 7.42028
+8.15753 8.72014
+9.23141 10.3815
+7.4484 7.80228
+0.473671 0.874895
+3.15689 3.50687
+3.58122 4.09945
+3.55022 3.74767
+4.42708 5.80211
+4.40956 4.68699
+3.80576 4.61856
+7.29965 8.28614
+7.40582 8.15308
+1.69789 1.77669
+1.66419 3.44308
+0.473997 0.872506
+7.83959 8.52898
+6.22416 6.36949
+-0.187159 0.871822
+0.232336 0.585965
+9.29905 9.44357
+1.4459 2.40589
+2.83008 3.19758
+1.15291 2.12112
+2.58686 3.33896
+6.79362 7.88068
+0.228178 1.48318
+5.60001 6.20258
+4.97803 7.10992
+1.70429 1.962
+2.72659 3.13886
+9.22714 9.25889
+3.84694 3.88778
+-0.282077 1.48155
+9.28756 9.58517
+4.34069 5.59751
+8.63909 8.76839
+8.86236 10.7642
+6.77597 8.41888
+7.30621 8.64164
+0.685607 1.22755
+2.91514 3.22638
+2.72098 3.66837
+8.17528 8.32638
+5.19632 5.7506
+7.34177 8.70639
+5.74082 6.35524
+5.95975 6.69284
+9.40187 10.4488
+2.92761 3.36735
+0.399531 3.13082
+4.83399 4.92635
+7.74539 8.56852
+1.76322 3.5086
+6.54479 6.72963
+7.64362 8.12404
+1.35542 1.45313
+0.214385 0.718085
+1.7006 3.21962
+5.91009 6.47862
+2.21093 2.34636
+5.96919 6.79365
+6.59951 8.22203
+1.54571 1.59397
+3.27012 3.79128
+0.32455 0.622995
+1.73926 2.78017
+9.81035 9.84077
+7.38441 7.85171
+8.90372 9.34186
+7.26323 8.41174
+5.7363 5.97348
+8.25473 10.1281
+2.3981 2.52096
+8.53783 9.63442
+8.51755 9.2735
+6.48614 6.773
+3.40182 3.65137
+2.1353 3.04852
+2.95397 3.73285
+6.98063 7.4963
+4.50189 5.26384
+0.21416 1.49363
+0.632196 1.36307
+6.57833 6.60481
+8.0634 9.33903
+2.79759 2.94462
+4.43747 4.58861
+6.48733 6.86569
+2.28008 3.47037
+6.87452 7.77431
+-0.156821 2.71557
+0.72595 1.78862
+1.97586 2.38196
+8.61839 9.1468
+4.55496 5.68986
+0.26923 1.15728
+9.63757 9.7236
+1.39497 1.96698
+4.8643 5.04172
+6.64675 7.66435
+2.56256 2.6015
+-0.381989 0.611211
+0.676336 1.26896
+8.95304 9.03243
+5.62058 6.07997
+3.36522 4.04276
+8.64868 10.5024
+4.75813 5.19834
+1.96608 2.05864
+9.01449 9.10397
+3.72786 4.51921
+5.6938 6.96584
+1.73499 2.9314
+2.73099 3.41409
+8.77171 9.07665
+4.63865 4.67649
+8.6698 9.30782
+-0.168259 2.09581
+9.29672 9.56
+0.372544 2.60567
+0.450487 1.32919
+6.95341 7.6399
+3.4403 5.24993
+5.53469 6.97831
+-0.79664 1.21306
+5.68831 6.14413
+8.85601 8.95444
+3.83309 5.211
+5.51573 6.5114
+3.64009 3.99648
+4.40759 4.99283
+1.85198 2.6457
+2.72645 3.74803
+2.04751 3.00998
+3.19365 3.9383
+8.09529 9.45596
+8.88173 9.5618
+0.609816 2.67806
+1.57288 2.60884
+1.68354 1.80124
+4.92058 5.9959
+1.48728 1.84885
+0.299669 0.413905
+9.02156 9.56731
+7.50854 8.49023
+0.667131 1.89987
+2.22472 2.58793
+5.84395 8.79426
+2.35839 2.66935
+3.43111 3.69982
+6.71023 7.36801
+6.75697 9.0991
+2.35352 2.85316
+6.73054 7.39006
+9.48673 10.1493
+6.71226 6.72805
+9.22083 9.71889
+8.36513 9.33921
+0.0652672 0.319993
+3.26467 4.60881
+7.62269 7.79878
+6.48608 6.69515
+6.21737 6.88645
+6.56094 6.9699
+1.61317 2.7167
+5.08621 6.29754
+2.24676 2.8076
+3.09943 3.93921
+9.74093 10.0968
+0.417699 1.6381
+9.2958 10.2973
+3.6663 4.1369
+0.0229943 0.448065
+9.2928 10.1833
+3.66334 4.22032
+0.812172 2.19952
+7.88025 8.71192
+8.69379 9.34922
+1.70691 2.95352
+8.28737 8.29985
+5.22491 5.354
+4.03526 4.14084
+6.49359 7.05924
+0.24853 1.44718
+7.86936 8.75135
+5.76 6.68919
+5.85437 6.14314
+5.86292 6.0516
+2.35692 2.91295
+0.0990674 1.29386
+2.9911 3.56188
+0.552671 0.638929
+5.80756 6.22761
+1.21067 1.77175
+4.51882 4.72936
+1.99969 2.89732
+3.65968 6.61987
+0.478582 1.33355
+0.259061 0.289813
+3.89264 5.02474
+0.349236 0.438003
+7.70442 8.1729
+7.90389 10.1876
+3.06898 3.15219
+4.77811 5.29095
+9.76561 9.89451
+4.14295 4.2489
+0.540224 2.28623
+9.60749 10.2284
+8.49555 9.00307
+7.89668 9.76886
+4.12631 4.70897
+7.87898 7.91814
+9.29858 9.52908
+9.24009 9.91544
+3.73498 4.70275
+5.44467 5.9274
+2.13453 4.85697
+2.29607 2.88771
+0.807842 1.82319
+0.319005 2.08473
+1.62 1.63649
+2.20431 3.23869
+2.00132 2.77136
+6.64752 6.71706
+8.12249 8.28379
+7.55541 7.7813
+3.51763 3.64484
+9.21075 10.2811
+2.24501 2.54426
+5.64566 6.46452
+6.72307 8.56698
+3.91728 4.60262
+4.02535 4.29548
+3.0499 3.53135
+1.30677 2.32194
+9.36908 9.90669
+3.92387 4.33848
+2.87312 3.08243
+4.49167 5.2749
+5.43143 6.74905
+6.94595 9.16539
+1.9784 2.00429
+9.42478 10.2226
+3.7185 3.96576
+9.37729 9.50574
+5.34283 6.89736
+4.95341 5.84626
+2.91654 4.28413
+8.26544 9.3076
+6.23114 7.20273
+1.02585 2.21446
+1.6718 2.29591
+2.28926 2.73452
+-0.648145 1.105
+1.44194 2.18562
+6.78584 8.37985
+2.00402 2.08248
+1.64076 2.04067
+0.0419044 0.455962
+5.51723 5.72098
+5.42117 6.81165
+5.70331 5.81707
+4.97889 5.60741
+3.38797 4.46846
+7.20995 7.66784
+3.45388 4.23386
+3.11057 4.35995
+3.29476 4.04676
+2.0519 2.94719
+5.37101 5.38271
+5.99383 6.64188
+7.48444 7.6377
+2.15043 3.05399
+1.54093 1.83799
+5.59223 5.87222
+5.8005 6.08042
+6.1208 7.22563
+1.2938 2.17454
+4.92405 5.0402
+6.91336 7.79688
+1.47978 1.99762
+9.00494 10.8315
+5.84805 6.15303
+4.95368 5.49096
+8.21704 8.31192
+0.715222 2.33517
+0.904183 2.54741
+3.42349 3.74906
+0.627978 2.37092
+8.41477 8.72651
+3.55373 5.58652
+4.12685 4.61533
+0.775274 1.41263
+4.78915 5.08639
+6.35791 8.15015
+2.88242 3.63509
+2.78526 3.07834
+0.39129 1.15933
+3.26615 4.74531
+8.78873 9.8888
+7.25612 7.45972
+4.97452 5.30012
+0.757255 1.35518
+1.29516 2.52446
+4.66838 4.96648
+-0.0720209 0.832726
+2.68276 3.21123
+8.44253 10.0311
+3.40809 4.70506
+1.09617 2.35452
+5.19302 6.73599
+1.25316 1.58101
+6.2056 7.10099
+7.7666 8.52777
+0.301239 1.37275
+0.522829 0.731575
+6.73869 6.96826
+2.41703 3.20567
+4.94617 6.22052
+5.41524 7.68272
+6.0408 6.29938
+0.0642067 0.600878
+6.32122 6.63505
+3.25427 4.70611
+5.88704 6.1678
+8.71533 9.08476
+6.25575 6.88392
+1.54462 1.56366
+3.95938 4.03326
+2.54671 3.66798
+8.48603 9.10156
+3.37369 4.65454
+5.25469 5.64636
+7.02624 7.36449
+8.17061 8.44321
+9.23147 10.1149
+1.45589 2.25886
+6.47702 8.25307
+7.69088 7.91753
+0.442832 0.616926
+8.35355 8.83222
+7.65142 9.58906
+4.04877 5.17345
+0.76012 1.8686
+6.54877 7.40058
+7.41774 7.65429
+8.69655 9.3325
+4.8302 6.25306
+1.77203 1.90284
+3.67485 4.94569
+6.60162 6.72031
+3.05924 3.35235
+0.0823162 1.3486
+8.42991 8.86331
+6.81596 6.83527
+-0.0174808 1.6745
+-0.758131 1.08928
+4.14423 5.46342
+9.26253 9.85714
+7.42749 8.58214
+4.88849 5.86936
+8.99339 9.38141
+8.85301 9.18285
+2.64303 3.45658
+7.1133 8.66473
+3.50745 3.8629
+7.81615 7.83244
+2.94991 3.8741
+7.91822 8.8362
+-0.0553088 1.19059
+7.35558 7.77948
+2.11257 2.20563
+8.57533 9.16338
+2.3515 3.13009
+4.13239 5.38696
+2.20763 2.93941
+7.2451 7.3211
+0.834388 1.57413
+4.47024 6.17855
+4.75947 6.80913
+2.99607 3.54732
+8.15998 8.80718
+8.94688 9.27971
+4.46335 4.9522
+5.30725 5.69786
+7.63989 7.86974
+6.69589 7.69565
+5.34018 6.08115
+8.59515 9.62264
+1.80557 3.22507
+8.62429 8.94242
+1.34532 1.95042
+8.60707 8.80741
+8.03275 9.40327
+4.30357 4.39095
+8.97954 10.7076
+2.18143 3.51825
+3.98695 5.62062
+2.48813 2.60622
+5.56957 6.43776
+5.18249 5.55459
+3.45373 3.64101
+-0.00345662 0.570597
+3.61127 4.69761
+9.37858 10.6205
+7.24635 8.19639
+4.70142 4.80735
+3.30055 5.14257
+0.860415 1.31635
+4.72924 5.46893
+7.47391 7.72644
+6.22287 6.57754
+0.181652 1.01366
+2.14494 2.80736
+2.16406 3.19383
+8.52991 9.22722
+8.74411 9.06935
+0.575831 1.02699
+2.47315 3.0331
+4.2872 4.59813
+5.82293 7.03604
+2.08982 2.25319
+7.3626 8.41994
+1.23867 3.10885
+7.397 7.78026
+6.78837 7.32977
+0.829368 1.56617
+9.23075 9.35172
+6.76562 7.23578
+0.42851 0.839401
+4.83626 5.5852
+0.150032 2.45322
+2.16811 2.47439
+5.60245 5.81188
+7.43707 7.46519
+0.167317 1.44642
+4.9732 7.58343
+8.67391 10.2957
+0.318592 0.639284
+3.365 4.25929
+7.83683 8.88895
+5.20557 5.30114
+0.940347 1.74022
+5.39149 7.13464
+1.10826 1.27913
+1.9147 2.31276
+0.935283 2.49181
+3.67898 4.33336
+5.10125 6.07734
+0.348807 0.839242
+0.310986 0.58381
+2.03594 2.43119
+5.49755 5.94215
+1.94885 3.34409
+9.66806 9.97883
+4.79099 5.45155
+4.81158 5.30001
+5.17667 5.90019
+9.64168 9.99177
+1.14899 1.22792
+0.466236 0.952985
+6.93679 7.72282
+2.97285 3.23931
+9.22517 9.24315
+7.25783 7.46414
+4.37304 4.51815
+4.01069 4.02979
+0.843132 1.80443
+4.78572 6.04237
+6.02471 6.38074
+4.99536 7.76852
+4.97442 5.17384
+0.731231 1.49497
+2.2797 2.90845
+9.13211 10.341
+4.19545 5.08597
+6.13127 7.09817
+2.65124 5.02208
+5.40235 7.12912
+6.86258 6.91991
+8.24317 8.55273
+7.6877 7.69875
+3.33922 3.53776
+0.089484 0.40755
+1.34909 1.68726
+8.43113 8.72899
+4.90038 5.55994
+0.308089 0.490555
+5.42628 7.1433
+2.11647 2.56987
+3.56934 4.1619
+8.35794 9.24416
+8.8645 9.69151
+5.10701 6.0036
+7.66385 7.8412
+2.89952 4.55221
+6.01533 6.38269
+-0.945182 1.07304
+1.79537 1.85576
+-0.0313338 0.501067
+8.85689 8.87522
+1.61143 1.7773
+9.53229 9.84943
+3.51669 3.81091
+-0.448016 1.10903
+3.16889 3.439
+4.30534 4.36372
+6.20158 8.09618
+2.20949 5.23616
+3.29459 4.17079
+3.90101 4.05611
+5.89688 6.85702
+0.734474 1.04471
+7.84341 8.02702
+8.69431 10.1086
+9.73194 9.92195
+7.63516 7.70631
+8.51416 9.33072
+-0.0712911 0.361001
+2.76979 3.22708
+5.34404 7.5165
+5.64429 5.79865
+0.0755012 0.363483
+5.05631 7.27153
+-0.60164 1.09659
+0.457228 0.876186
+4.27092 5.38033
+8.63891 9.04134
+6.29608 7.04242
+8.97795 9.93013
+5.00385 5.57737
+8.48068 9.44885
+7.35543 7.78492
+3.55698 4.01035
+-0.268117 0.649128
+0.633184 0.66254
+4.54216 4.81132
+6.15574 6.35276
+4.3663 6.36286
+1.45231 2.07039
+7.37031 7.9157
+5.30961 6.3506
+5.80757 5.81762
+4.91767 4.97519
+3.45667 3.60965
+1.7934 2.3807
+4.33289 5.41047
+1.16021 1.29979
+3.75172 4.53521
+3.10835 3.1275
+2.68167 3.00314
+4.10639 4.24094
+4.90776 5.74069
+7.30861 7.86666
+3.52822 3.70998
+5.22222 5.28033
+0.00866476 0.326377
+7.73247 8.61481
+4.25231 4.77499
+8.41148 8.54604
+2.95389 3.63497
+7.76126 9.69124
+6.41218 6.69682
+4.86285 6.44503
+1.84783 1.9065
+4.08788 4.11706
+9.17473 9.50133
+5.15091 5.78649
+1.27694 3.33579
+2.92648 3.37855
+9.37392 10.5123
+4.81878 6.34991
+8.38702 8.83716
+5.07771 6.33618
+1.47438 1.75588
+6.20935 7.11166
+1.08286 1.38
+1.40048 2.0157
+6.60355 7.26234
+5.28396 5.90003
+8.9525 9.59216
+-0.0305792 0.544664
+-0.571491 0.735471
+6.287 7.03679
+5.35225 5.4104
+0.095812 0.605976
+4.33523 4.4048
+6.13288 6.80949
+4.14654 5.5505
+-0.213214 0.260592
+7.56188 7.83088
+7.8132 8.65963
+8.02469 9.3254
+0.00641711 0.420562
+7.49269 8.15849
+9.26359 9.4366
+5.74008 7.86317
+8.62729 9.78825
+4.28946 6.20553
+3.19174 4.54991
+4.16992 4.25203
+2.46138 4.11583
+1.92971 2.16701
+3.43028 3.80842
+6.98297 7.28388
+7.51884 7.55947
+7.79102 9.44326
+0.416342 1.32311
+9.35398 9.85201
+8.72997 9.10384
+6.23398 6.88888
+7.46984 7.4875
+5.92603 6.66938
+1.77761 2.58697
+0.835966 2.06139
+9.63284 10.3565
+6.13677 6.42768
+0.151375 0.382404
+8.10315 8.13441
+5.52283 6.28113
+1.00873 2.44226
+2.5239 3.89871
+5.40599 6.72653
+3.43407 4.0068
+1.22444 1.26601
+7.04395 7.80599
+3.75987 3.77123
+6.43597 7.06249
+8.34435 8.87418
+8.25853 9.04009
+0.415321 2.32725
+0.639046 1.75525
+7.83226 8.12538
+9.55429 10.2734
+3.658 4.35867
+1.8588 3.93292
+7.38922 8.16823
+8.53626 9.23024
+0.848152 1.13412
+6.31667 7.2348
+3.81584 4.62621
+9.24748 10.7408
+2.75953 2.95288
+5.70188 6.62278
+4.22202 4.45368
+3.24616 3.88779
+1.05053 2.09846
+8.67718 9.52693
+2.14107 2.71959
+1.10518 2.69689
+5.01476 5.54139
+4.69244 5.20358
+8.88285 9.93012
+2.55228 2.77382
+6.72118 7.50057
+7.58999 8.71573
+1.83763 2.13481
+4.86135 5.27995
+4.39794 5.42117
+1.42512 2.98262
+4.80489 5.34701
+2.7993 5.13702
+7.52122 8.41729
+9.08613 9.37543
+1.1555 1.3935
+7.34071 8.0428
+8.33361 8.40349
+2.514 2.54741
+8.25732 8.41758
+1.65337 2.57964
+4.20527 5.06565
+0.723443 1.06987
+5.85836 6.64701
+7.908 8.07591
+5.01839 7.0105
+3.15908 5.10364
+4.3574 6.67192
+2.06662 2.46437
+7.5595 8.9108
+7.94919 9.20231
+4.11889 5.49714
+7.28151 7.51881
+1.30685 2.09479
+3.08479 4.47364
+4.50916 5.91511
+7.31605 7.63868
+3.14469 4.07035
+8.38431 8.87993
+7.42277 7.64967
+4.22472 4.26323
+8.49871 8.90746
+7.44431 8.09014
+8.35213 8.7504
+3.85634 4.37584
+9.12975 9.77042
+-0.326056 1.17374
+3.53802 4.06211
+6.81775 6.8467
+8.19106 8.64489
+4.20526 5.37727
+2.74081 3.72143
+0.49642 1.10775
+7.76606 8.00524
+4.79825 6.38926
+1.99478 3.20484
+4.69853 6.29508
+5.73058 7.18643
+8.11708 8.64257
+9.62375 9.84838
+5.95271 6.38989
+9.0193 9.93848
+3.91188 4.10834
+6.065 6.60546
+2.62354 3.60072
+8.53665 9.06824
+6.40691 7.44693
+1.62959 2.5825
+9.4128 9.87031
+6.24697 6.62684
+3.31136 3.45626
+4.80347 4.9935
+9.21711 9.53416
+-0.491547 1.72886
+4.75174 4.87217
+0.86329 1.53331
+2.4586 4.2578
+5.10301 6.2815
+5.08302 5.86788
+6.12434 6.78948
+9.68323 10.0973
+3.52576 4.40424
+4.9925 6.89084
+0.846638 1.80782
+1.09709 1.7685
+8.38592 9.03312
+9.56243 10.2682
+5.03592 6.6429
+7.8609 8.04599
+1.21404 1.31975
+7.47824 9.2063
+1.47849 2.68795
+1.2909 2.06381
+5.21288 5.54616
+6.27218 6.99345
+4.77622 5.08494
+3.30665 4.14735
+3.38947 3.55545
+7.71197 8.53162
+1.10565 1.50806
+0.7889 0.984689
+2.88598 3.33244
+5.70958 5.81232
+5.16567 6.24511
+6.91255 7.25784
+-0.401084 0.753156
+4.81138 6.20671
+1.67301 3.58501
+7.19478 8.25624
+1.24428 2.2523
+4.31631 5.33357
+0.589196 1.02017
+5.69207 6.97803
+2.3854 3.25501
+4.1362 4.91135
+8.9932 10.3184
+7.95871 8.45158
+4.03213 5.26347
+3.09506 4.06425
+-0.0310321 0.738171
+7.35733 7.61512
+2.48488 2.96253
+4.72098 5.69867
+5.5395 5.96914
+3.17854 4.283
+6.50012 7.33744
+1.93266 3.00941
+1.49319 2.71826
+9.0187 9.13099
+7.15259 7.40691
+8.71939 8.93257
+1.57203 3.11249
+0.933429 2.16903
+2.99663 3.71667
+2.06144 2.81311
+7.9072 8.2103
+0.490069 0.614737
+7.84111 9.70812
+1.15363 1.6421
+1.15475 1.43307
+8.2228 9.92116
+7.76825 8.40724
+6.15122 7.31322
+7.1427 7.49294
+2.30516 2.7019
+2.03336 4.03387
+8.3918 9.85707
+8.57214 9.59345
+3.8057 4.1119
+8.9223 9.38556
+9.32051 9.60504
+7.13349 7.69154
+1.71855 2.00425
+5.10333 6.0605
+-0.149137 0.80973
+0.466224 3.1698
+4.19165 4.29604
+1.64018 2.3161
+9.40397 9.89211
+5.21738 7.06323
+0.525526 1.0331
+8.06992 8.08704
+9.81539 10.0915
+9.33514 9.50521
+5.95494 6.54519
+9.21466 9.35909
+4.96603 5.18164
+3.89238 5.53056
+5.04546 6.32916
+8.63758 8.65805
+7.03226 7.57074
+0.32029 1.10893
+0.194176 0.992252
+8.79061 9.50848
+0.239137 0.300717
+7.7234 8.43747
+3.43679 4.28954
+8.31382 9.18928
+1.39612 1.67253
+6.95733 7.39846
+1.29129 2.12185
+7.93611 10.2305
+3.67764 4.17562
+1.38149 2.42407
+2.2847 2.48412
+9.28655 10.0661
+2.94115 3.21326
+7.04238 7.91536
+5.06012 5.61526
+8.95611 9.91736
+2.18524 3.44007
+1.0692 1.10987
+4.37019 5.18443
+5.82014 6.441
+1.68642 1.70458
+4.93783 4.9535
+9.42003 10.1196
+-0.356795 1.30987
+1.37778 2.80527
+9.54126 10.1758
+8.67413 10.5984
+0.914291 2.0697
+6.08696 7.09832
+2.82202 3.31103
+4.07818 5.50195
+2.85223 3.67449
+6.03006 7.10863
+8.84655 10.528
+5.08031 6.2001
+1.00272 2.74191
+0.169102 0.223253
+0.025089 1.26534
+-0.203339 0.64667
+0.899666 1.48885
+0.74235 1.49976
+6.28212 6.80412
+5.65159 5.93106
+2.1686 2.7445
+5.02936 5.43091
+8.07124 8.80499
+8.65696 8.95802
+7.68394 8.365
+8.65062 8.69146
+0.058248 1.19535
+5.74545 5.84057
+6.05244 6.52152
+9.3878 10.3328
+7.71379 8.88044
+3.32961 4.54105
+8.51987 8.62854
+4.10821 4.16902
+9.47639 9.78723
+4.72417 4.84793
+2.32867 2.94068
+9.52275 9.57815
+5.32867 6.96127
+4.32462 5.1508
+4.46919 6.45961
+8.62661 10.9533
+0.0244049 0.56156
+1.49207 1.73164
+7.03156 7.81168
+5.88587 5.89732
+8.43632 9.65085
+7.52612 8.06726
+4.82464 5.6193
+3.8062 3.90356
+2.42708 2.51646
+2.06458 2.45877
+0.427218 2.24283
+7.42616 8.11513
+0.617708 1.01833
+8.74218 9.03592
+-0.213346 0.599112
+9.05291 9.59124
+5.20365 5.54277
+2.85289 3.99509
+3.08468 4.58456
+0.136826 0.685254
+3.87191 3.99021
+0.970836 1.49673
+2.44355 2.53584
+8.88615 9.94545
+3.90591 4.52798
+1.52518 2.50658
+7.21268 9.07745
+0.767314 1.23833
+8.62975 9.42367
+6.71524 7.67686
+7.61205 8.48292
+5.312 5.65087
+4.75627 5.96261
+7.90674 8.0753
+7.37887 7.71478
+3.74483 5.52984
+2.7187 2.85544
+4.7902 5.62159
+2.89671 5.19815
+7.37268 8.72506
+7.11916 8.28301
+9.19814 9.75279
+1.2085 2.60113
+-0.632009 0.889734
+7.99858 8.39743
+6.48346 7.10822
+6.30616 7.06648
+5.56514 6.51183
+2.41505 3.56224
+6.83749 8.84447
+9.05111 9.46906
+7.77476 8.4091
+6.11378 6.31232
+4.42882 5.69917
+5.88107 8.052
+3.75437 4.08893
+2.70487 2.77664
+7.26028 9.77257
+1.44621 2.73267
+2.0384 2.60397
+2.95402 3.68949
+6.04766 6.4054
+0.716046 1.77698
+1.5084 1.72988
+2.58426 2.80376
+8.05255 8.59793
+6.06336 6.20709
+3.29813 4.31473
+2.53477 4.92554
+8.78711 9.88634
+9.26627 9.82082
+6.70683 6.81257
+8.25978 8.99788
+7.28054 7.64237
+5.14556 5.20711
+4.20431 5.87866
+8.96592 9.97597
+4.06216 4.41519
+8.49174 11.0491
+5.24547 6.03094
+4.65885 5.95835
+5.09606 6.34846
+6.30463 6.65933
+6.48022 9.56168
+1.38088 2.98143
+0.486911 1.16767
+8.16327 9.34821
+0.768885 0.782616
+4.51699 6.08086
+9.55086 9.70242
+2.86802 3.72489
+1.88496 2.18749
+4.31876 4.33726
+8.38871 9.45631
+8.80634 9.36198
+5.232 6.42399
+9.86919 10.0492
+3.61902 4.53086
+3.13118 4.42364
+2.69395 3.1816
+-0.303144 1.32309
+4.28871 4.36739
+3.8631 4.08745
+4.9291 4.98968
+7.14273 7.25505
+2.56623 2.59122
+6.01753 7.72265
+6.76051 7.53954
+6.76933 8.14741
+0.933137 1.83537
+7.9357 8.57904
+5.55847 5.59984
+4.25563 4.3345
+4.28087 5.21348
+8.88534 9.06554
+1.88575 2.94002
+5.26613 6.04562
+0.514249 1.45538
+0.130644 0.501645
+4.30564 4.86337
+1.57246 2.38451
+0.303814 1.77474
+4.22675 5.02783
+6.75381 6.78634
+5.64096 5.9725
+6.76159 6.98142
+2.35569 2.39119
+3.29794 4.95962
+6.55055 7.03366
+5.31474 5.69404
+9.01335 9.16988
+8.58306 9.37831
+7.06522 7.07778
+1.14695 1.74744
+3.15507 3.22865
+5.5925 7.14168
+2.14679 3.68767
+7.54789 9.71878
+1.5667 2.08742
+-0.604726 1.66718
+0.306012 0.54799
+2.61731 5.08257
+0.80957 1.74655
+8.22035 8.81637
+4.401 5.449
+8.89389 9.01988
+4.80574 4.9322
+2.19895 2.88565
+9.06688 10.8095
+1.23727 1.58699
+7.14836 7.92057
+4.65155 6.15149
+0.563061 2.16535
+7.66764 8.0341
+8.32324 8.42774
+4.54541 5.11069
+8.0237 8.09992
+7.26113 8.09404
+2.55196 3.20317
+8.1236 8.60951
+1.90437 3.23006
+0.888133 2.50365
+1.13618 1.69444
+2.60463 3.01696
+7.2311 7.73229
+5.06501 6.01487
+3.9893 4.10116
+1.45278 1.56937
+2.74601 3.80778
+9.40705 10.3843
+3.02533 3.52213
+8.7097 9.2268
+8.73145 10.5552
+2.56059 3.5742
+6.27328 7.57089
+3.23291 3.30811
+6.33804 7.20304
+7.63648 8.34564
+9.82053 9.93597
+3.14924 4.58629
+5.28253 6.33733
+1.99411 2.04104
+0.305593 0.420302
+5.39668 6.64188
+7.99992 9.37823
+5.25169 5.65987
+0.109291 0.875734
+3.08589 5.50296
+6.51358 6.62588
+5.34687 5.58204
+0.043587 0.932787
+-0.0264143 0.28677
+8.09722 8.37087
+5.46612 6.30285
+2.89146 3.49892
+6.73278 7.11762
+5.03068 5.90176
+1.7459 2.87727
+0.207707 0.448933
+7.00453 7.63105
+6.02789 7.87991
+8.1917 8.95854
+7.49014 8.73215
+8.48402 9.22063
+1.0467 2.4687
+0.241901 1.38802
+2.65867 2.81258
+5.46725 6.59448
+3.40578 3.75607
+4.2495 4.26392
+5.6608 6.213
+2.99705 3.88852
+6.17231 6.72018
+-0.17415 0.492739
+4.89596 6.49895
+4.68876 6.60218
+-0.0510568 1.46013
+8.87099 9.28179
+3.98894 4.5838
+-0.20015 1.59214
+8.80756 9.51828
+7.74921 8.53538
+-0.380041 0.440574
+2.69409 3.91466
+2.42747 4.56745
+6.25881 7.75647
+7.2941 7.77193
+2.60806 2.90251
+0.325028 1.22219
+8.29921 9.01416
+3.85524 5.45451
+5.2612 5.71877
+2.92849 3.73937
+8.6242 8.70808
+7.28153 7.35797
+1.65378 2.87917
+3.46034 4.24143
+3.99989 4.3199
+1.15266 3.60328
+4.8464 6.4887
+4.67021 4.68421
+6.96861 7.31554
+0.00723008 0.817047
+7.59589 8.88352
+5.56725 6.08465
+9.02409 9.19527
+5.81681 6.74193
+1.98221 2.98678
+8.76392 10.7646
+4.3903 4.50531
+1.0186 2.01838
+2.66674 2.74505
+2.41105 3.44579
+8.98295 9.18995
+8.14385 8.98779
+2.69613 3.60144
+0.445704 1.51319
+-0.634889 0.860409
+6.32737 7.10112
+7.88824 8.06838
+3.76271 4.43529
+7.66487 9.30221
+8.73974 9.59191
+3.08965 3.43006
+8.9518 9.96154
+0.727194 1.55228
+6.35214 7.12234
+2.71987 3.22996
+7.12786 7.4379
+-0.346107 0.837469
+8.47103 9.05987
+9.15744 10.628
+8.3237 10.093
+1.15052 1.16223
+6.95959 7.35423
+7.69488 8.44145
+4.21694 5.65913
+3.10562 3.37534
+9.73437 9.78252
+5.0458 5.53479
+7.80485 8.5163
+2.0442 3.75748
+-0.459177 0.498702
+7.38032 8.32195
+0.909659 2.11175
+7.08657 7.56877
+1.84997 3.10206
+4.2517 4.53819
+6.71655 7.04117
+1.06604 1.29153
+2.69273 3.31633
+2.19732 2.84826
+-0.723032 0.774865
+-0.289734 1.44645
+5.87194 7.71917
+1.01576 2.83685
+0.981927 0.998558
+3.07172 3.73201
+-0.112577 1.12642
+3.54063 3.67007
+7.21571 8.53815
+0.109957 0.839052
+6.86046 7.17211
+9.40878 9.69478
+0.989391 1.69046
+8.22287 8.8147
+1.48203 2.83308
+5.86418 8.0993
+0.749797 1.09852
+1.82996 2.50847
+0.28178 0.496017
+2.60694 3.00872
+8.6254 10.1698
+6.11641 6.41537
+7.19529 7.21342
+1.8214 2.17517
+0.991201 1.3788
+2.84924 3.12362
+5.75821 7.13843
+6.7106 7.35932
+6.6055 6.6829
+7.97105 8.58613
+1.56087 1.95845
+6.36782 7.10926
+2.43382 2.74699
+7.40509 8.8029
+8.42459 8.63142
+6.26128 7.55043
+4.6465 5.4431
+2.93214 3.29517
+0.157602 0.545214
+6.05931 6.72188
+1.7908 3.11731
+2.39217 3.58736
+7.07421 7.43852
+8.13419 9.74991
+9.53094 9.65319
+2.35726 3.68679
+-0.108561 0.874853
+6.87136 8.84157
+3.40803 4.58835
+7.50448 7.89932
+4.29762 5.53867
+0.863755 2.30032
+7.24847 7.95342
+2.89618 2.98849
+-0.928261 1.61922
+0.974105 2.91262
+6.99271 7.25856
+3.60995 5.01832
+1.26865 1.79704
+9.62217 9.80719
+1.02656 1.35514
+7.16502 7.32934
+3.12092 3.28857
+2.81374 3.84317
+8.73626 10.7585
+3.36982 3.61446
+5.08437 5.78949
+2.90218 3.0862
+9.2309 10.2523
+5.0967 5.48926
+9.73088 9.92708
+1.54013 2.78301
+6.73707 10.0789
+6.41735 6.838
+2.57935 3.04287
+5.719 6.70352
+5.42474 5.62732
+4.23904 4.69787
+4.16528 4.28736
+7.73477 8.84143
+4.90346 5.87324
+5.1969 6.14087
+3.48793 4.14182
+0.648493 1.07987
+6.88101 6.97932
+7.67342 8.74418
+5.16759 6.3871
+9.16292 9.49569
+8.77422 10.4817
+-0.358149 1.04178
+9.54616 10.3424
+3.12027 4.26504
+3.81223 4.73004
+1.2386 3.32247
+8.21963 8.42629
+9.10312 9.51016
+6.96107 7.43045
+2.98587 3.12365
+0.198165 0.211424
+5.19716 6.10856
+6.10553 6.3327
+3.98176 5.11099
+1.02512 1.04242
+4.27949 5.71947
+-0.457956 0.538807
+7.99877 9.48581
+5.88782 7.73303
+1.21496 2.85825
+8.46962 8.7862
+9.50182 10.1527
+5.85223 7.76234
+2.48368 2.52439
+2.35426 2.77405
+0.397056 0.482679
+0.160423 1.15786
+4.47109 4.8633
+4.74523 5.84196
+5.39177 5.75218
+9.00754 10.3249
+3.74813 4.03273
+3.08633 4.08426
+4.62672 5.29012
+1.92055 3.01442
+3.79279 4.5603
+9.52431 9.68334
+2.8126 3.32592
+-0.313688 0.490785
+9.06695 9.36835
+2.60321 4.14185
+4.40231 4.99535
+9.32205 10.1041
+5.3879 5.44349
+0.308728 1.0956
+9.05758 9.08283
+1.90313 2.50914
+7.1391 7.59459
+7.47357 7.95993
+1.25267 2.34827
+3.33222 4.36522
+8.78126 9.38611
+0.635979 1.62283
+8.3492 8.57545
+-0.572557 1.60517
+8.28855 9.03937
+3.47934 3.90271
+4.64498 5.43501
+0.872177 2.62011
+7.3893 7.58876
+2.14063 2.88063
+1.69361 1.75261
+4.19727 4.86483
+0.814676 1.27639
+8.19899 8.58203
+8.3394 8.99896
+9.31768 10.1694
+4.99218 5.19949
+4.2459 4.75266
+9.6314 9.64249
+4.038 4.75708
+7.92398 8.8579
+4.30747 4.54161
+7.51776 7.78258
+3.77611 5.1385
+3.53275 3.90278
+1.78619 2.12474
+3.18736 3.55159
+8.36759 8.52587
+5.52526 5.7843
+7.64174 8.09773
+4.37925 5.85699
+3.94295 5.31298
+-0.464623 0.795523
+7.02408 7.7048
+0.0690458 1.0008
+1.05445 1.32797
+0.126093 0.712612
+-0.809973 1.33869
+3.45568 3.96532
+0.433875 1.78679
+8.94667 9.65034
+1.98575 2.76936
+6.47974 7.67912
+2.74186 3.34153
+7.82655 9.32112
+4.71441 6.14932
+0.741177 1.76987
+8.05021 8.23239
+0.818503 0.882959
+7.13341 7.43399
+8.45939 8.93395
+4.44558 5.70161
+3.05657 3.86962
+8.75469 8.85537
+1.0922 2.23475
+6.00278 7.51598
+0.0530968 0.582206
+4.01788 5.48223
+1.30808 2.81869
+8.18848 8.59771
+2.43691 2.80685
+8.54045 10.6178
+7.58523 7.91634
+6.70183 7.49962
+5.81501 7.29783
+0.661853 1.58021
+6.50997 7.20411
+0.334292 1.40252
+-0.329585 0.742961
+2.38756 2.48935
+2.78114 3.58788
+7.97227 8.55379
+3.36753 4.57472
+5.14486 5.31457
+3.99691 5.47708
+6.36404 6.8741
+3.22519 4.63321
+1.80583 2.21824
+8.20747 9.42947
+5.90819 6.94368
+6.58559 6.85933
+2.99108 4.03832
+7.20963 9.6252
+3.10244 3.87265
+7.23018 7.91389
+7.18084 9.61063
+6.74145 6.86507
+8.40721 9.5751
+7.12352 9.45614
+2.06653 2.51786
+4.9155 5.04183
+1.34304 2.92777
+0.571315 1.17285
+8.05396 8.28214
+5.29142 6.24974
+8.93797 9.23051
+4.6108 5.45568
+6.46124 7.53124
+3.16695 4.37505
+2.76803 2.82764
+4.1531 4.84927
+8.19433 9.00383
+5.12114 6.22952
+2.2542 4.74849
+0.621192 0.871537
+1.37403 2.28895
+0.305704 1.3287
+8.70471 9.53085
+2.29164 3.56607
+2.42106 3.37382
+1.14309 2.03085
+9.17624 10.3281
+1.88864 2.70161
+0.932647 1.2473
+5.72385 6.55694
+5.25496 5.38675
+5.85771 6.69626
+7.37247 7.93094
+7.73499 7.98782
+4.91417 5.27506
+3.51127 3.84403
+6.96198 7.27686
+6.51176 7.74735
+4.19954 5.08222
+1.58115 1.83842
+2.11889 2.3408
+1.94427 2.00422
+5.59977 6.86555
+9.46942 10.3491
+9.18904 10.1988
+1.71938 3.01547
+4.3515 5.4951
+2.53792 5.85188
+0.3884 1.36228
+5.02469 5.62368
+6.82402 7.72203
+-0.320478 0.821539
+0.0885656 0.248783
+3.01725 3.44385
+6.63776 7.74386
+6.57899 7.9332
+4.82656 5.18327
+3.91909 4.43955
+0.0708319 0.101395
+2.59796 4.22775
+-0.433109 1.26978
+-0.434274 0.624336
+3.22018 4.25282
+4.63351 4.776
+8.889 9.56332
+5.35952 5.46531
+8.73832 9.22756
+2.03432 2.34194
+0.477994 1.43353
+1.2029 2.86844
+5.09945 5.76855
+8.89076 9.01771
+5.30284 6.31732
+1.56375 3.17543
+5.4773 6.36897
+5.30934 5.35073
+7.20096 7.7075
+6.51046 7.12888
+9.37127 10.0531
+-0.0484323 0.348687
+1.83241 2.2143
+8.28633 8.60462
+2.51014 3.65817
+3.27798 3.58685
+1.41567 2.23302
+7.50794 8.10378
+-0.0579575 2.10373
+-0.856005 0.96621
+2.96238 3.48434
+1.36304 1.90594
+2.9997 3.41214
+7.2763 8.087
+1.69207 2.74419
+5.41625 5.83917
+9.22139 9.53794
+1.17477 1.51576
+6.74597 7.90871
+0.678913 1.73759
+5.70863 5.7214
+8.88411 8.93377
+3.44409 4.54586
+0.958963 1.53878
+8.29904 9.3867
+2.52433 3.60238
+8.16257 8.21986
+2.11395 4.23455
+6.85451 7.40364
+0.20286 0.639736
+2.05848 2.49034
+0.547013 0.77336
+7.83609 8.11903
+2.16539 2.29286
+3.94232 4.31368
+8.53475 8.54519
+4.77462 6.4158
+4.08395 4.68214
+1.56902 2.23811
+1.61337 3.11768
+1.51181 1.65521
+0.0821202 2.09269
+4.77622 5.16243
+4.62148 5.75837
+0.613158 0.952696
+1.89128 3.04792
+7.57509 8.92834
+2.70465 4.2941
+4.95906 5.12442
+8.0927 8.17277
+0.796512 1.3215
+5.74134 6.45291
+9.68479 9.78978
+5.89261 6.2292
+6.11377 7.9339
+2.20571 2.67129
+3.46228 4.27058
+5.26723 6.2653
+4.04391 4.26562
+0.380382 0.818995
+7.58108 7.7618
+5.02375 6.13042
+4.20178 4.66297
+2.83039 3.0221
+2.36072 2.45545
+6.68854 9.20726
+2.91388 3.42464
+9.33373 9.73449
+7.75844 7.94625
+2.72414 2.89669
+6.65438 7.96623
+1.00647 1.05385
+2.63018 4.9432
+0.152187 1.60259
+8.86332 10.3631
+2.31523 2.6815
+8.00509 8.61794
+1.69711 1.75938
+8.65442 8.73697
+4.23917 4.32001
+9.66851 10.1925
+6.93943 7.49814
+8.51986 9.03561
+2.10317 2.5175
+0.539549 1.75683
+6.29423 7.93236
+8.64345 9.54556
+1.44069 1.6814
+9.10017 9.77088
+6.16731 7.40496
+0.570043 1.93192
+2.65761 3.88544
+1.46895 1.52688
+-0.369067 0.540647
+2.04868 2.72065
+2.1286 2.27858
+5.90157 6.16431
+1.55581 2.51851
+3.29705 3.81635
+3.4137 4.10991
+8.48699 10.1364
+8.43437 9.4642
+-0.037842 1.47589
+0.541735 1.7805
+0.499576 2.36065
+4.1415 4.72435
+4.77598 6.16872
+3.30388 3.61854
+6.43796 7.85966
+5.27157 5.70871
+0.919258 2.18653
+4.00961 4.07902
+3.78201 4.23596
+4.50464 4.791
+3.70253 5.30916
+8.59228 8.70036
+4.31103 5.69049
+5.31775 5.34378
+2.24198 2.64194
+6.66937 7.41675
+7.21753 8.42057
+4.35399 4.52398
+6.90698 7.30084
+3.44296 5.44378
+3.36719 4.89951
+3.38624 5.33856
+3.44877 3.53693
+5.81398 6.3016
+7.24655 7.33127
+3.86142 4.53134
+3.85894 6.88112
+6.45704 6.95699
+6.90997 8.24088
+5.68813 5.7611
+0.699911 0.824323
+6.73758 8.42517
+9.34644 10.07
+0.289929 1.30554
+8.30644 8.49113
+6.47667 7.16073
+4.28093 4.90236
+8.32678 8.57064
+7.09205 7.92316
+5.55599 5.63919
+1.0104 2.22875
+1.72237 3.53668
+2.54699 3.14823
+-0.668582 1.25485
+1.25582 1.37003
+1.35044 1.57807
+6.17083 6.30811
+0.618816 1.20065
+-0.540992 1.21634
+2.06673 4.28857
+9.03398 10.8112
+8.73735 9.22814
+1.30178 2.7599
+6.0221 7.34889
+8.30124 8.52159
+1.92023 3.34545
+2.99331 4.93358
+3.8412 3.93379
+1.455 2.77005
+0.538664 2.1118
+4.16926 4.26053
+0.699746 0.937609
+6.36024 6.6511
+2.34698 4.84463
+8.11109 8.76496
+4.05425 4.67773
+8.2284 9.78568
+1.64423 1.80353
+5.70109 6.93764
+7.2091 9.67224
+4.47015 5.23311
+4.29326 5.36144
+7.93151 8.96494
+4.61889 4.96487
+5.38473 5.43594
+9.35456 9.66489
+1.23737 3.04121
+1.16077 1.19519
+5.91037 7.55679
+6.88344 7.60181
+6.39705 8.65039
+1.61791 2.93041
+9.68285 10.1396
+9.03129 9.05839
+7.0683 8.29875
+7.19624 7.41696
+7.5266 8.38738
+-0.254571 1.01098
+1.30218 2.03222
+7.6432 7.73031
+4.99495 6.04757
+2.79394 3.29394
+0.31505 3.55963
+7.55382 8.18787
+6.00032 6.27664
+1.49355 1.79767
+5.21191 7.19537
+3.47816 3.75801
+2.10272 2.39494
+1.31887 1.93829
+7.14313 7.63055
+7.3141 7.77239
+6.03409 6.17265
+4.24946 4.53165
+0.0569272 2.56109
+8.44766 11.4872
+4.22879 4.28007
+6.92817 6.98775
+8.08859 9.0206
+-0.0748418 1.48605
+6.56698 7.0488
+4.46624 5.4952
+3.66085 4.05778
+6.44711 8.93943
+2.45735 2.49339
+0.0606673 0.416191
+-0.183838 0.750464
+7.08561 7.67275
+6.65423 6.90808
+0.0598735 0.364072
+5.2228 5.41543
+3.14042 3.19043
+2.40069 3.02829
+1.80441 2.1849
+3.47491 3.95775
+5.49162 6.63934
+2.03332 2.32288
+3.17234 5.25109
+2.58274 2.59951
+9.37994 9.97097
+4.71509 6.77966
+5.18915 6.84982
+6.12508 7.04354
+0.811202 1.98808
+1.46825 3.66984
+2.44386 4.15623
+7.60169 7.68242
+-0.43208 1.22222
+5.40569 5.66153
+0.391742 1.79408
+6.77742 8.43115
+9.12828 9.3851
+6.39541 6.80626
+5.17919 6.29326
+6.57263 8.12999
+3.439 4.62236
+8.40525 9.80086
+7.60986 7.70099
+1.32123 1.44213
+0.526574 1.92338
+9.57195 9.79591
+9.52103 9.63159
+3.79775 4.20608
+4.74446 4.89606
+9.00085 9.60025
+1.26279 2.08363
+4.13639 4.49232
+6.59409 7.18315
+1.0637 1.78425
+5.4213 6.87661
+4.24407 4.30987
+9.79732 10.1204
+4.24597 4.83541
+8.47705 8.5145
+4.34095 4.93842
+5.68168 6.96086
+7.48654 7.91072
+8.32005 8.45111
+5.24065 5.3032
+3.25982 3.94442
+5.58106 6.18764
+4.4243 5.58619
+6.36467 7.07082
+2.70051 3.56014
+5.94534 6.87688
+7.33638 7.7645
+4.57067 5.86652
+7.83993 8.36854
+9.03617 9.11629
+7.44672 7.95614
+6.05876 6.3594
+4.02496 4.97119
+3.01438 4.36109
+7.4932 7.92357
+7.51661 7.53354
+7.60692 8.49678
+1.76088 2.59103
+7.08578 7.39566
+4.83605 5.42933
+-0.186592 0.847663
+1.15879 2.33996
+8.11815 9.35472
+6.02584 7.62549
+0.881084 1.00015
+5.39067 6.27026
+0.910755 0.97444
+5.32174 5.65652
+7.69388 8.24928
+3.40521 3.7615
+5.60321 6.92388
+8.25096 8.34324
+0.00108913 2.16897
+0.508035 0.66573
+-0.0517816 0.0876197
+3.26472 4.30955
+1.99494 2.14903
+2.089 4.32368
+5.17378 5.75964
+2.8779 3.54361
+6.56459 6.90645
+1.43196 2.88337
+1.48917 1.94009
+3.40807 4.25784
+8.0334 8.13458
+8.22254 9.6175
+2.96308 3.14349
+5.04768 5.71252
+3.9977 4.72614
+1.44384 1.60782
+7.78147 8.19817
+7.03854 7.50085
+5.90747 7.06091
+2.89169 4.31831
+2.46167 3.16529
+9.13228 9.1504
+2.57975 3.05313
+5.75976 6.52958
+8.10499 8.98982
+8.43162 8.76377
+0.422917 0.668254
+1.69046 2.09962
+5.50386 6.66954
+0.0897183 0.564514
+3.50103 4.1041
+3.91918 4.52559
+4.39297 6.18876
+3.90396 4.90868
+9.69362 9.85528
+6.27994 6.95062
+8.01563 9.09433
+8.25641 9.72944
+8.22072 8.35423
+1.27059 1.61352
+8.53312 8.96235
+3.49185 3.9042
+5.79579 6.046
+0.489013 1.2147
+4.00074 4.177
+2.66625 2.93036
+7.20267 9.34958
+7.44659 8.54707
+8.99915 10.1143
+7.59922 7.82031
+8.38502 9.03222
+0.160075 0.294398
+4.14549 4.3927
+9.35554 10.248
+-0.159435 0.467922
+2.17272 3.72336
+8.63811 8.79976
+4.23215 4.66461
+6.99516 8.2035
+6.45212 7.88791
+6.20141 6.28633
+7.69396 8.82204
+4.50807 5.96315
+8.51725 8.89286
+0.939492 2.12064
+7.4615 7.62666
+8.46681 9.11769
+3.92828 5.40884
+9.05622 9.40015
+0.229625 0.860838
+2.05694 2.52113
+-0.217927 0.574255
+9.55146 10.3256
+8.31497 8.3417
+3.52833 4.47013
+7.7131 8.52058
+2.15462 2.66777
+5.7674 6.17553
+3.3358 4.10589
+2.06642 3.00412
+2.43387 2.85242
+5.09473 5.84276
+7.3287 7.54846
+4.64254 5.11465
+4.05785 4.93614
+4.25413 5.43513
+2.96476 3.15378
+3.53732 4.48239
+2.34137 4.01272
+2.24879 3.40626
+3.43323 4.49055
+0.871415 1.33068
+0.508929 1.65611
+4.92057 4.94743
+7.03376 7.35193
+5.73043 6.47264
+7.82417 9.93642
+5.24102 5.9178
+2.38528 4.1676
+6.27437 7.19631
+9.29267 9.53262
+4.10098 5.24964
+0.383714 0.833317
+5.97628 7.92987
+8.15799 8.96819
+8.1687 8.29862
+8.16289 10.5149
+7.38205 7.89765
+3.81883 4.15607
+9.46915 9.61755
+1.50756 1.51863
+2.34236 2.84689
+0.398473 1.15027
+1.05302 1.49155
+8.71687 9.35232
+1.0502 1.40395
+7.83685 8.76302
+7.7731 8.46899
+5.56618 5.97458
+2.90035 4.12043
+6.40644 6.68706
+3.95201 4.37075
+7.1831 7.67748
+9.42789 10.0914
+5.45198 7.01256
+8.64609 9.45756
+6.01864 6.31515
+7.64621 8.65533
+5.45654 5.76553
+2.04332 2.75476
+5.49454 5.85693
+6.13688 6.21927
+2.66255 2.7385
+4.8326 6.43772
+9.12704 9.45287
+-0.294488 0.318697
+2.26979 2.35516
+4.12949 5.58506
+3.01416 3.62246
+6.64697 7.10221
+6.44307 6.82985
+4.10484 4.73148
+7.42589 7.6029
+5.33055 5.50395
+2.46474 3.05847
+5.43677 5.59206
+2.13807 2.3988
+-0.38424 1.8121
+0.00916704 0.219304
+8.62621 10.2262
+3.33927 4.51169
+5.45656 7.13165
+5.29253 6.57917
+3.51704 3.9421
+8.63729 9.13361
+3.92626 4.3469
+6.83104 7.52695
+1.22258 2.28191
+0.447646 0.789809
+7.96543 8.54328
+2.24269 2.42571
+4.4161 5.40481
+0.813992 2.21792
+0.694664 0.974182
+6.50017 6.88902
+4.00723 4.65882
+9.05784 9.85062
+6.80276 6.98196
+0.105446 0.379881
+0.416982 0.53336
+9.01269 9.55204
+3.27197 4.23315
+6.7017 6.89704
+4.21512 4.42378
+4.86735 6.90949
+4.52235 5.36878
+2.62205 3.55746
+-0.551048 0.555476
+1.63274 2.71251
+4.26739 4.88085
+8.23129 9.77405
+2.49409 3.96851
+6.66387 6.88886
+7.72383 8.90611
+3.18511 3.27281
+0.73722 1.64435
+7.90329 9.02868
+6.94845 7.06773
+0.509461 1.54928
+4.63885 5.51652
+9.24395 9.5121
+1.00007 1.57161
+5.31349 5.45437
+0.929284 1.71034
+7.05985 7.63288
+7.38418 7.45373
+4.14937 6.5167
+7.49989 8.6081
+9.28313 9.57721
+4.41285 5.1497
+2.96148 3.09221
+1.58256 1.66419
+4.45116 5.43488
+5.70927 7.11699
+3.61105 3.93153
+5.92285 6.63773
+3.50065 4.48453
+7.97338 8.96464
+0.541394 0.965435
+4.46469 5.03925
+7.33695 7.6484
+9.64234 9.6938
+4.16378 4.17886
+7.10741 7.31549
+1.51829 2.62477
+2.1892 2.9684
+9.23767 10.0462
+7.87649 7.97087
+7.05385 7.85952
+6.91232 7.50277
+6.60185 7.81572
+2.27112 3.90211
+5.74452 8.2018
+6.25117 6.26911
+0.525893 1.53447
+0.392956 0.959233
+3.51591 4.71055
+3.10449 5.41156
+7.35964 7.65642
+2.89831 3.54334
+3.42338 3.68259
+4.75496 5.51419
+3.8792 4.48395
+2.18007 4.13236
+3.15798 3.16864
+8.91248 9.21598
+8.54636 9.34037
+7.93697 9.79709
+6.40205 8.9653
+9.67332 10.2252
+4.31771 5.25423
+7.27485 7.3725
+6.22971 7.11411
+1.16538 2.16762
+1.40443 1.6876
+3.14915 4.58847
+7.13761 8.72165
+4.38448 5.88699
+7.98309 9.19449
+8.491 9.05597
+5.55043 6.19359
+2.44006 3.36071
+9.56522 9.79903
+1.86129 2.00225
+1.65239 2.11478
+7.59392 8.4655
+2.44709 2.68538
+6.80932 7.04694
+8.8212 9.4182
+0.276845 0.956468
+8.17008 8.5538
+0.77864 2.06897
+6.78458 7.68692
+0.504907 2.67518
+5.56963 6.9058
+3.42691 3.5414
+2.52065 2.71583
+5.09924 6.26696
+0.223724 0.610039
+3.61258 5.29324
+0.388393 3.11131
+2.87763 4.45415
+8.26438 10.1169
+5.89742 8.17506
+1.89686 2.66651
+5.33662 5.68228
+3.37496 5.67291
+2.25713 2.36127
+0.402185 0.716342
+6.4231 6.79227
+3.22707 4.69314
+7.85092 8.77413
+3.31322 3.72455
+5.43021 7.7167
+8.5883 9.00864
+1.21371 1.71836
+6.35584 7.9706
+5.44438 5.50414
+5.31325 6.11217
+6.08888 6.78794
+7.70604 8.13257
+1.29858 2.48753
+5.54083 6.38817
+8.23948 9.82646
+7.5575 9.0224
+8.00415 9.39763
+0.488455 1.55358
+4.48727 5.20741
+6.46648 7.02349
+0.355939 0.611119
+9.4892 10.2189
+2.61893 2.82832
+0.268193 1.24687
+3.01964 5.19554
+6.29954 7.42795
+8.70796 9.48366
+5.39307 6.64597
+2.47001 2.60746
+5.30949 7.46529
+6.07973 6.16835
+0.764507 1.6144
+7.94123 8.52143
+1.88244 1.96592
+6.42103 7.02205
+7.673 7.73208
+6.66891 7.80675
+6.9305 7.5431
+6.62335 6.93873
+4.34846 5.77621
+0.49878 2.82928
+2.65221 2.80109
+7.45348 7.74372
+4.10129 5.26894
+3.87782 4.19855
+4.62113 5.22658
+2.84558 2.88185
+2.53209 2.86065
+8.94932 9.21967
+6.48046 6.89614
+5.81885 6.66829
+6.49129 6.62015
+8.5663 9.58685
+2.43346 3.89849
+9.36561 9.45886
+1.40232 2.65
+6.66 6.74041
+2.87007 3.49668
+4.71138 6.0184
+5.03638 6.08494
+7.77735 8.14253
+1.0301 1.27179
+2.58337 4.04699
+6.95419 7.89775
+7.81164 8.62551
+3.37669 3.96217
+4.68541 5.58692
+4.79697 6.34841
+3.95334 4.81962
+9.44006 10.0941
+4.91098 5.12386
+8.44273 10.1565
+3.6685 3.73156
+5.07599 5.33357
+-0.138235 0.260923
+2.71154 3.45603
+5.75096 6.16127
+4.4775 4.64308
+6.80557 8.97442
+5.49408 5.76652
+8.31937 9.12886
+3.26479 5.51673
+2.57425 3.03145
+2.42465 3.92714
+7.86505 8.50835
+3.29229 3.43549
+4.08537 4.69709
+7.83885 8.60616
+1.61622 2.72716
+9.10228 9.41907
+8.49325 9.46612
+-0.174644 0.351716
+1.95648 2.14825
+8.28844 8.4428
+4.35888 5.59521
+5.1396 5.22537
+0.330835 0.879566
+6.14972 6.82967
+3.14811 4.89049
+-0.231668 1.08277
+3.13526 4.94545
+8.32674 8.91046
+5.22364 5.48006
+9.84318 9.88416
+-1.07813 1.6965
+1.5095 2.0328
+8.03716 8.2792
+-1.01307 1.46703
+8.22096 9.0055
+8.9917 9.0415
+5.60623 6.74537
+3.15991 3.19314
+3.13863 3.26451
+0.739618 0.896958
+0.67599 1.18486
+3.37355 4.06303
+0.38605 0.410067
+3.03297 3.46387
+3.45867 3.79806
+8.67249 9.53278
+-0.213855 0.787363
+1.52316 2.61117
+8.31846 8.59736
+4.84685 4.94042
+7.41901 7.82623
+4.99029 5.09747
+5.3637 5.37612
+3.22123 4.77749
+3.21668 5.74743
+3.48748 4.59962
+8.00016 8.56269
+1.63631 2.42239
+1.05159 3.72319
+7.22643 7.95706
+5.65694 5.99195
+9.4469 9.66915
+0.857984 1.59867
+4.05869 5.69955
+2.65788 3.07259
+1.8038 3.38748
+3.91934 4.89922
+6.18534 6.70342
+2.85076 3.20176
+8.1897 9.9614
+0.685531 2.05322
+3.31097 4.00809
+8.26537 8.63475
+2.90508 4.07797
+1.25213 2.31285
+3.05752 4.03741
+-0.481913 0.605629
+1.87958 2.19386
+7.28689 7.76316
+4.82075 5.20688
+-0.08115 0.31839
+3.50085 5.89363
+1.31184 3.30269
+4.03137 4.81493
+6.11688 6.13923
+7.93584 8.43321
+4.9838 5.3733
+3.8174 4.11979
+8.56196 9.02824
+2.87809 3.89589
+7.95309 8.05432
+3.47469 3.63716
+6.61009 7.12576
+8.87374 9.79588
+7.31513 7.99089
+5.78084 6.68535
+4.96985 5.59877
+2.20236 2.52473
+0.661014 1.11035
+6.36183 6.58403
+6.67947 6.85093
+-0.242005 0.513902
+0.442966 1.72024
+6.4587 6.74016
+6.67958 8.0837
+8.98524 9.56405
+6.91409 7.59877
+3.73596 3.97705
+5.51193 5.96437
+3.72029 4.50126
+3.09896 3.23616
+8.83312 8.91774
+0.32173 0.486199
+4.21092 4.59955
+2.61616 4.07081
+1.89049 2.65559
+4.96401 5.00629
+9.33156 9.70914
+3.72455 4.61054
+8.91265 9.6563
+7.12401 8.04324
+6.65393 7.25572
+1.04032 1.24927
+3.0174 5.56006
+1.47645 2.26867
+3.49833 4.37416
+6.16877 6.34452
+6.47417 6.90595
+4.27056 4.92535
+7.60439 9.35352
+0.426219 0.754405
+8.5291 8.68579
+5.84717 6.64632
+1.99513 2.5284
+5.10669 7.83064
+6.99006 7.37272
+0.871836 1.5934
+3.6572 4.38875
+0.154617 0.290737
+5.91634 6.50415
+5.33982 5.45293
+6.92602 6.94691
+0.349512 1.61427
+8.02048 8.99943
+5.75598 7.34946
+5.86948 6.51327
+5.11707 5.6181
+6.27656 7.10043
+8.48922 9.73833
+8.35863 8.69746
+6.67829 7.07852
+8.51257 9.50383
+3.76636 4.33757
+4.82804 5.57166
+5.17892 5.61254
+1.35188 1.94069
+6.04969 6.06833
+5.34181 5.82455
+5.71714 6.71234
+0.966462 2.56278
+7.95169 8.15951
+6.53583 6.89673
+6.73246 8.34493
+8.71111 9.76467
+7.53215 9.56537
+0.619041 0.736713
+9.24399 9.50151
+8.57184 9.88538
+2.82682 3.77294
+4.2649 4.84602
+8.6621 8.96426
+8.04469 8.3189
+7.81877 8.42944
+2.78031 5.16589
+1.23076 1.43577
+8.35385 8.49632
+3.27901 3.66774
+0.595941 1.41354
+3.37123 5.16685
+9.11003 9.95515
+-0.25959 0.32069
+1.44153 1.70148
+1.61595 1.70799
+7.8201 8.53423
+8.5402 9.36947
+8.39125 9.8221
+6.2909 6.35773
+0.000933745 0.920054
+-0.21358 0.491025
+4.00874 4.03866
+3.43552 3.55874
+7.85942 7.98987
+7.6681 8.06748
+6.19541 7.14765
+8.53891 8.96393
+2.38789 3.26866
+-0.0162847 1.18379
+1.04764 1.52755
+0.400798 0.55475
+6.32001 6.94897
+5.9692 6.2012
+1.20784 2.67873
+3.58247 4.46372
+-0.229647 0.559407
+5.65979 5.73489
+2.32795 2.78462
+0.706144 1.55147
+4.56527 4.6636
+5.98901 7.20908
+9.27329 9.95152
+1.31296 1.70529
+5.82933 6.41329
+4.17452 5.29881
+4.15885 5.25117
+0.35549 1.3511
+1.0591 2.4463
+8.87597 9.55625
+6.66826 8.57255
+0.355945 1.40613
+5.39729 6.10218
+3.78791 4.37501
+9.53885 9.87184
+2.67568 2.82552
+4.44836 4.52939
+5.96764 7.40168
+6.35578 6.98546
+0.636857 1.19517
+3.3986 5.55448
+1.46493 2.66884
+-0.0676901 1.80921
+7.83396 8.53452
+8.3508 9.04561
+4.03407 6.0066
+0.997538 3.30635
+7.83064 8.03466
+4.57652 4.97461
+3.85952 4.15471
+0.960261 2.1069
+0.522458 1.52989
+8.81627 9.00768
+0.172256 1.29455
+5.69294 6.15752
+6.86391 7.75307
+2.32429 2.95415
+1.83191 1.90364
+0.400855 0.705649
+5.23264 5.39972
+5.19047 5.79842
+2.40804 2.89401
+0.462887 1.43874
+6.70213 7.90229
+4.37985 4.95797
+3.73768 4.30645
+0.756797 2.11146
+0.458724 0.472099
+3.93098 6.47147
+5.5294 6.00365
+2.97106 3.42174
+5.75875 5.80235
+7.96799 9.02105
+5.36254 7.22823
+6.56124 7.39973
+9.49234 9.57879
+2.87576 3.59509
+3.49182 4.28124
+8.68021 9.94486
+9.60199 10.1276
+9.70115 9.81776
+3.09609 3.98732
+5.00113 8.15031
+5.21248 5.74835
+9.23337 9.5696
+2.92777 3.56297
+2.52044 3.04905
+4.79908 5.05762
+1.98626 3.69659
+4.78726 6.20637
+7.39711 7.42831
+4.44319 4.78716
+9.28452 10.0832
+8.00774 8.85707
+9.22947 10.0523
+4.38653 4.86012
+5.15285 5.23106
+8.95413 9.75947
+2.90286 3.32407
+0.348694 1.39738
+-0.0660432 0.293424
+4.09079 4.2922
+6.0407 7.23031
+2.83771 3.72237
+8.54697 9.38898
+2.16742 3.45018
+8.83255 9.30343
+3.59112 3.6531
+7.53452 7.81898
+7.11781 7.19773
+8.2892 10.0259
+4.91072 5.06031
+5.8232 7.25924
+7.0641 8.31604
+9.477 9.63892
+5.8003 6.58306
+9.63988 10.2754
+0.654364 1.02398
+5.9488 6.85043
+7.86867 8.99891
+9.202 9.46902
+4.17932 4.20271
+6.50328 6.71085
+7.19848 8.15579
+5.62459 5.75449
+-0.159668 0.791409
+7.55683 8.7315
+1.03278 1.423
+0.751457 0.808785
+6.2203 6.50634
+1.64418 2.98238
+6.87468 7.00652
+6.36966 6.7117
+7.69893 8.89535
+0.419794 1.05032
+2.73928 4.31548
+0.409245 1.55228
+6.03905 6.39323
+0.409695 0.789834
+4.39148 4.40935
+1.14673 3.23607
+5.85562 6.44503
+6.87394 6.88742
+3.761 4.35136
+7.2208 8.01436
+6.49839 6.54002
+4.70791 5.91886
+4.24906 5.96619
+2.53482 3.91496
+-0.369254 0.69193
+4.81351 6.31088
+9.76066 10.0736
+1.4413 1.55942
+7.21917 8.88908
+6.03521 7.56826
+1.25568 1.42024
+5.47575 6.04431
+1.43099 1.99979
+5.1004 6.04088
+6.54798 6.56118
+1.0142 3.1564
+1.75267 2.1453
+1.28133 1.36044
+9.60996 10.0563
+1.14397 1.50247
+6.86688 7.08724
+8.38287 9.18041
+0.132076 1.27657
+6.52553 6.9301
+0.223917 1.41325
+1.18902 1.79753
+1.40084 1.75678
+1.94524 2.51929
+1.98276 2.62875
+0.763281 1.05483
+7.97952 8.51249
+1.059 3.05463
+5.33401 5.85094
+8.37442 8.64374
+6.62865 6.67315
+1.01707 1.64386
+0.113335 2.23523
+6.71906 8.00216
+-0.886574 1.29366
+4.20078 4.85294
+8.43336 9.06988
+3.55413 4.40768
+6.69076 9.01132
+6.18982 7.14109
+7.14381 7.7046
+8.63195 9.47031
+8.88052 9.84886
+3.34443 3.62637
+4.5862 4.72832
+4.95757 5.23571
+2.85993 4.04966
+1.43846 2.27425
+5.43112 6.30496
+-0.452609 1.55525
+7.17706 7.71287
+5.78537 5.79579
+8.51102 8.9466
+-0.472904 0.810489
+3.83688 4.24045
+8.04432 9.04582
+1.57259 3.37136
+1.22231 1.33582
+5.73006 6.26477
+2.90855 4.22125
+9.39717 9.4287
+3.63873 4.16094
+0.442035 2.08889
+0.294491 1.31124
+3.14755 3.86305
+6.57634 9.44898
+2.19051 2.41878
+4.99277 5.12569
+4.10425 4.9423
+4.83547 5.62769
+5.73879 5.78179
+8.90329 9.81905
+5.60168 6.17538
+5.83843 6.66128
+1.84271 2.57406
+3.01047 3.33662
+2.85037 3.79158
+3.49007 4.46877
+8.58942 9.51529
+0.613753 1.12824
+8.23757 9.54707
+9.27134 9.4196
+6.27126 6.56417
+2.17206 2.33018
+3.53588 5.17162
+8.6312 10.0868
+5.76342 6.66164
+9.01501 9.90984
+3.22004 4.18954
+4.37918 4.68595
+2.00928 3.49815
+6.64229 7.06693
+2.85962 4.58794
+8.45587 9.8897
+2.8481 3.65956
+8.65849 8.67336
+6.48486 6.58637
+5.82336 7.45254
+4.02267 4.59696
+2.24997 2.83815
+8.16201 8.55518
+7.40645 9.07085
+1.43137 1.50333
+8.7212 10.9419
+1.50523 2.44124
+1.92455 2.85819
+4.50866 4.53052
+5.75781 5.81275
+1.71013 2.0282
+9.31592 9.9015
+6.14972 8.18798
+1.85705 2.20068
+4.80971 5.10509
+3.31201 3.58168
+8.61824 9.31861
+7.19497 7.86933
+3.25381 4.53472
+5.62799 6.29537
+9.00659 10.021
+9.15156 9.74827
+2.0324 2.80741
+0.714403 1.00476
+1.26522 1.80417
+-0.362995 0.41758
+7.08785 7.71544
+5.55685 5.74045
+0.428866 3.03773
+7.61574 8.94894
+9.07256 9.69772
+4.49537 5.06822
+5.66388 6.48899
+1.69126 2.69607
+9.90539 10.0783
+6.56455 8.27128
+6.61988 7.86616
+7.42012 7.64493
+2.99922 3.35282
+4.69379 5.18947
+0.87894 1.30518
+9.47632 9.61234
+0.665754 0.855958
+-0.422778 2.11197
+3.38786 4.15441
+7.57236 8.75855
+1.89832 3.50224
+-0.185929 1.0777
+3.32911 5.53465
+6.91111 8.69247
+6.97456 7.86905
+4.75518 5.0948
+4.23733 5.83368
+8.52456 8.56086
+0.0978267 0.136564
+7.4668 7.99757
+5.52851 5.80858
+8.5833 8.88589
+5.10603 6.41348
+4.70682 6.59981
+8.60265 9.19477
+5.04514 6.24014
+4.49041 4.88669
+7.40925 9.15624
+0.80364 1.35315
+7.11604 8.01153
+0.267749 0.714089
+0.121521 0.822226
+9.30556 9.81307
+2.11398 2.92567
+5.97722 6.08022
+7.13483 7.22211
+8.00161 9.27274
+4.87681 5.51654
+3.11843 3.84311
+5.17747 5.98482
+3.6077 4.46306
+1.37454 2.2443
+4.93385 5.96357
+2.92184 4.0964
+4.88767 5.56353
+2.87394 3.76336
+0.326521 0.622872
+2.42056 2.45007
+-0.527891 0.827211
+6.73151 7.20155
+1.82048 2.54905
+1.35563 1.88701
+3.64202 4.10669
+5.22846 5.23953
+6.06271 6.46993
+2.71418 3.2081
+6.41179 7.57176
+7.45823 7.79609
+1.01227 1.39137
+9.0872 9.20132
+5.083 5.64038
+5.63236 5.97945
+-0.317645 0.822313
+0.865396 2.65587
+5.71839 5.98983
+1.50978 2.08611
+2.95824 3.70996
+0.264301 1.02233
+8.22351 8.98589
+4.87805 5.24127
+2.31329 3.46752
+6.19539 6.69676
+5.18643 5.40947
+7.15453 7.66643
+1.20694 2.25111
+7.87378 7.89093
+5.16514 5.604
+8.68354 9.01395
+7.33753 9.37499
+2.94627 4.06036
+8.64337 8.85727
+0.0353092 1.0128
+6.98437 7.35718
+6.77073 6.79959
+3.13559 3.70735
+7.40139 8.27017
+4.01174 4.39788
+3.22281 5.11647
+7.79256 8.58737
+0.642233 1.39694
+7.18603 8.69453
+3.37803 3.59355
+0.762287 0.84262
+4.21823 4.52565
+0.894924 1.35434
+0.844327 1.19938
+5.57958 7.05431
+-0.631066 1.55134
+3.78962 4.17935
+9.15329 10.4824
+5.47536 5.52975
+8.81243 9.16088
+4.45989 4.94123
+8.68235 9.45112
+8.04719 10.3938
+8.87349 9.40483
+0.502543 0.570283
+2.08512 2.47652
+-0.654512 0.804355
+3.68569 5.21711
+5.33017 5.80226
+3.44991 5.31415
+-0.00417763 2.95077
+7.17784 7.9318
+1.2721 1.31642
+5.24415 5.64173
+2.79434 3.28746
+4.54991 6.49276
+4.74707 5.12555
+7.36365 8.15777
+0.913049 1.79828
+1.47498 1.83425
+2.64271 3.38567
+4.78159 5.44718
+7.6087 7.66442
+-0.484393 0.909893
+3.16824 3.23757
+4.43021 5.90284
+4.25954 4.74995
+6.58742 7.24125
+1.86151 2.27069
+3.16459 4.5945
+1.06471 2.08965
+3.31028 3.83029
+1.52593 2.47521
+0.703789 1.42451
+1.47969 1.68923
+2.92352 4.24089
+9.84088 9.93485
+3.18205 4.27817
+7.39345 7.78945
+3.78808 5.41572
+4.38624 6.75693
+6.93065 7.16977
+1.01289 2.19807
+3.37006 3.54196
+5.50238 5.58285
+-0.225113 1.99347
+1.67796 1.86943
+6.1999 6.35102
+3.80494 4.74814
+1.13294 2.02639
+1.1965 2.6548
+-0.284453 0.856092
+4.26565 5.02196
+9.66948 9.88874
+6.20287 6.25528
+4.38154 6.65806
+3.77411 4.3075
+5.77177 6.78486
+9.16311 9.816
+3.22861 3.42009
+3.36573 4.34724
+6.76951 7.58025
+4.83813 5.23042
+3.87192 4.37372
+5.56859 5.90066
+-0.368163 1.4593
+5.44031 7.81671
+2.66342 2.99253
+6.11846 7.69499
+4.98811 5.17531
+4.45078 4.67513
+4.88206 4.94128
+2.51813 3.0268
+0.461292 1.15264
+2.34766 4.48652
+0.198819 2.23425
+6.85634 6.98248
+0.912438 1.81872
+4.84933 6.34912
+5.15613 5.82891
+0.172772 0.994083
+3.37381 3.64549
+1.98836 3.2697
+1.64344 2.06049
+0.766585 3.09305
+7.8979 8.28046
+4.34856 5.01341
+6.69809 7.24239
+5.19034 7.04959
+5.3747 6.92123
+7.8893 10.1251
+6.11207 6.99125
+5.37115 6.84111
+9.04786 9.11002
+6.45326 6.64415
+-0.76294 0.92832
+0.980411 1.8166
+3.05536 3.50031
+6.10827 7.55786
+6.57848 9.06264
+7.66855 8.861
+4.80276 4.82283
+1.99932 3.2877
+9.45229 9.80653
+0.457474 0.778684
+5.44444 5.95239
+5.60974 8.05169
+7.64656 7.79632
+6.78372 7.65134
+6.93878 7.82023
+9.08292 9.55308
+9.16329 9.25802
+1.4909 2.38688
+4.31881 5.3564
+5.12535 5.60119
+2.44591 2.54637
+7.36929 7.80452
+2.13707 2.97655
+9.73557 9.94588
+1.96637 3.36097
+0.857068 2.29643
+5.58224 5.91142
+8.90714 9.0255
+9.77988 10.0711
+0.41121 0.970955
+-0.518356 0.91447
+7.58725 7.71255
+8.1435 8.78712
+6.5487 7.17991
+4.94961 5.50283
+8.14086 9.03281
+3.51281 5.24806
+3.5786 3.84066
+6.27435 8.37735
+8.65263 9.5555
+2.87484 3.56117
+5.57707 6.55879
+-0.111276 0.264178
+3.60894 4.15477
+2.82322 3.64397
+8.40669 9.1127
+8.43089 10.5298
+1.38472 2.2453
+1.74464 2.00472
+4.01588 4.67572
+0.408869 0.938602
+2.06155 3.46067
+4.4871 5.08963
+2.4435 3.87355
+1.32864 2.55801
+4.78579 5.26122
+7.43027 7.57749
+6.90971 7.32716
+8.01095 9.46872
+9.41627 10.524
+8.83143 10.4474
+0.631816 1.75513
+1.72965 2.17123
+-0.513239 1.1886
+6.75616 6.7984
+2.49278 4.26493
+0.230011 0.966298
+3.78506 4.95013
+2.03886 3.14808
+7.87309 10.5637
+3.54564 3.58055
+1.91974 2.9194
+4.8503 4.98668
+4.66494 4.83558
+7.57916 8.24358
+4.78743 5.38547
+2.81034 3.34534
+1.00297 2.0138
+6.87593 7.17736
+3.93157 5.0655
+3.10361 4.05519
+8.22876 8.38326
+7.48377 8.31026
+2.23106 3.4905
+0.130934 0.606709
+1.22344 2.55898
+7.55829 7.92597
+4.10977 4.86263
+0.122756 0.264176
+3.8357 4.15854
+1.28414 2.13031
+0.280029 0.805504
+2.88245 4.1704
+5.57936 6.94781
+6.22719 6.33201
+-0.761013 1.16475
+6.16636 7.12566
+2.98935 3.192
+2.23263 2.34362
+3.9082 4.11692
+2.66865 3.5275
+1.87676 2.43966
+4.60035 5.39332
+2.74287 3.73097
+2.81953 3.96666
+5.73644 6.04042
+4.02179 4.52419
+3.26438 4.07346
+1.22509 2.13719
+7.91885 9.71846
+1.28152 1.48079
+7.97918 9.26344
+8.75682 9.8677
+7.25678 7.45362
+8.16161 8.87066
+1.21873 2.37224
+7.76739 9.06346
+3.89932 5.03406
+3.53901 4.37006
+2.93795 4.04333
+6.36543 6.72985
+4.72622 4.98804
+1.86205 1.99008
+0.784581 2.05264
+0.978519 2.91723
+3.9067 6.47195
+0.735425 2.38151
+8.37394 8.41609
+6.91804 7.23374
+9.39259 10.1026
+7.28732 7.43466
+4.75982 5.44264
+6.71504 7.53933
+2.17125 2.54358
+0.703562 1.39087
+-0.221711 0.541965
+9.22839 9.39159
+9.53465 9.97585
+1.44304 2.53666
+7.886 8.85051
+9.33174 10.1632
+2.60898 3.42889
+1.73658 2.02589
+6.31651 6.77762
+7.26755 8.34499
+9.01312 10.9837
+7.47361 8.96251
+7.98365 8.02586
+1.40065 3.44891
+9.44617 9.55391
+8.24265 9.34849
+9.366 10.4216
+0.375354 1.17522
+3.37114 3.38278
+-0.742469 1.07634
+4.29988 4.81879
+4.18605 7.21928
+7.41047 8.29198
+6.68173 7.60225
+3.24292 3.30695
+1.8951 3.42167
+3.97359 4.2857
+4.72621 5.80575
+4.75014 5.02239
+6.43454 6.94568
+7.16601 8.10355
+2.16685 2.23666
+6.70852 8.63284
+8.16988 8.95848
+0.277002 1.30648
+1.5803 2.28632
+2.22634 2.34679
+0.200623 0.814959
+5.27457 6.51651
+2.49533 2.90705
+6.48922 6.69528
+8.18879 8.63551
+2.75159 3.633
+0.884853 1.56434
+1.87488 3.98951
+4.24783 5.17713
+6.22499 6.56095
+5.68238 5.99272
+3.75553 3.85012
+4.87543 5.39966
+6.62671 8.72493
+3.50262 4.05131
+5.38952 5.4974
+7.84971 7.94051
+5.39123 6.66564
+5.43986 6.17256
+7.48968 7.7677
+4.2685 4.57296
+1.75169 4.11058
+5.03634 5.16102
+4.68003 4.84715
+8.36249 9.98761
+8.94297 10.6969
+6.21572 6.24305
+7.90303 8.0672
+7.90426 8.41244
+5.98512 7.93187
+5.13297 5.27136
+6.58367 7.4971
+4.72663 5.22956
+7.99667 8.59246
+4.3303 5.92188
+1.3132 1.80875
+7.70104 9.20947
+1.78862 2.00473
+9.63678 9.65571
+-0.264416 0.318054
+2.70004 3.40777
+2.74642 3.73608
+3.6494 3.6743
+8.03113 9.22851
+1.07526 1.3116
+4.05436 5.33291
+4.60907 6.03605
+7.83426 9.10358
+2.27997 2.77309
+5.63139 6.92616
+4.40717 5.25214
+1.98986 3.5062
+2.42393 2.9584
+1.94336 3.08456
+1.20185 3.01827
+0.641733 2.10095
+7.25046 8.29391
+0.640392 1.26451
+3.9588 4.85492
+6.83036 7.41101
+6.48581 7.08757
+6.48734 8.47856
+9.55084 10.3774
+-0.173137 1.26574
+2.32702 2.58775
+2.7463 3.13914
+7.86951 8.62807
+5.96916 7.92759
+0.217046 1.70373
+1.04207 1.05755
+4.79058 5.07902
+4.19024 5.35395
+9.00175 9.83715
+8.37554 9.275
+4.5204 4.82999
+3.49936 4.75519
+7.07916 7.74619
+6.66726 7.35282
+7.39513 8.55523
+7.50381 9.60708
+1.39304 2.26927
+2.84101 4.76376
+1.21779 1.59353
+4.7893 5.70143
+9.12195 9.57131
+5.40461 6.15443
+2.86445 4.26837
+8.01324 10.9082
+2.96659 3.8042
+2.4897 4.59323
+6.37887 7.15878
+7.00143 7.6419
+3.22491 3.41843
+1.22852 3.31783
+2.09881 2.56121
+4.43205 4.67051
+4.39328 4.66715
+2.38355 3.39058
+0.638802 1.59399
+5.32717 5.81376
+8.00353 9.72007
+8.77281 9.81649
+8.95552 9.86609
+2.90915 3.96556
+3.88176 4.93124
+6.45945 7.69942
+-0.108577 1.57424
+0.304992 0.320561
+6.47789 6.5515
+1.98211 2.05312
+6.2741 7.35626
+9.45057 9.67918
+5.2916 5.48037
+0.158802 0.712187
+6.42002 6.84323
+9.11085 9.13063
+9.42446 9.95882
+6.03624 6.96469
+9.2473 9.6286
+7.10342 8.71163
+3.34072 3.35187
+7.4602 8.58506
+8.7963 8.81873
+0.323615 2.22687
+0.326746 1.76681
+2.20062 2.76862
+7.55181 7.85006
+0.941035 1.28117
+8.76643 9.60019
+9.19731 9.33092
+6.0479 6.57293
+6.12725 6.24356
+7.53078 8.92488
+3.1841 3.48283
+1.85544 2.01888
+7.3849 9.29183
+5.03915 5.27721
+4.77142 5.46282
+-0.291696 1.14641
+1.61367 2.20867
+5.31853 6.69431
+2.52731 3.13139
+4.86677 5.18106
+4.50183 4.60969
+5.95881 6.09964
+2.41939 4.42026
+6.92003 7.17891
+4.29584 5.48557
+8.02803 9.06315
+2.82326 3.49599
+5.8647 5.87561
+2.38814 3.62688
+6.32418 7.17662
+5.99907 6.5059
+3.84698 4.14446
+9.80728 9.82132
+5.2366 6.30871
+9.81878 9.91004
+1.53024 1.83525
+2.98035 3.68531
+4.5418 6.98786
+5.19561 5.9846
+0.946068 1.46672
+3.26948 4.71928
+6.13476 7.68682
+8.36934 9.65072
+6.40074 7.14762
+1.01349 1.80493
+8.4514 10.25
+-0.180382 0.682704
+1.03041 1.63565
+5.64642 6.96069
+2.73598 3.67485
+5.8705 6.66157
+4.68343 4.7176
+5.83787 7.6818
+1.42529 2.234
+3.73726 4.19241
+5.38341 5.81884
+1.13088 1.69073
+0.968034 1.98828
+1.06007 1.11039
+3.50129 4.51807
+5.83133 6.77904
+-0.334945 1.29129
+0.326706 1.16015
+9.15028 10.4391
+5.13047 6.79712
+1.06952 1.38997
+5.79345 6.49898
+7.88149 8.5143
+8.00404 8.09794
+8.22725 8.28904
+6.38406 6.61356
+6.32166 6.73458
+7.17066 7.32049
+1.64338 3.79327
+7.92135 8.55568
+7.15578 7.42231
+6.70701 7.65427
+5.76608 7.63064
+3.54163 4.08662
+3.81402 6.76906
+4.5998 4.61865
+9.01471 9.18718
+5.21234 5.73335
+0.946018 1.39917
+6.99714 8.29739
+5.64458 6.93965
+3.39809 5.70907
+6.32284 6.83604
+8.50347 8.53097
+3.90118 4.85721
+9.41198 9.62076
+4.41514 5.55152
+7.69979 7.81249
+5.34434 5.37105
+7.25274 7.76114
+7.67383 7.92718
+5.82851 6.29417
+0.935651 1.2842
+0.639586 0.786771
+6.39823 8.31226
+3.67546 4.89035
+9.20323 9.57287
+2.33896 2.99576
+8.51933 8.80243
+0.983098 1.11084
+8.48215 9.42998
+7.29586 7.3914
+2.00695 2.89046
+2.60909 2.62433
+2.04118 2.92033
+7.60386 9.01419
+7.32896 7.73342
+9.51693 9.54891
+5.1323 5.24962
+6.35326 7.18302
+2.50952 3.51872
+3.4149 3.57431
+9.18412 10.4976
+5.68123 6.42697
+5.87758 6.0124
+6.3202 6.64588
+8.2547 9.98176
+5.50949 5.7854
+0.0824268 0.128178
+2.17292 3.76233
+7.22786 7.68214
+5.09326 6.4151
+4.30171 4.86688
+2.39206 3.47399
+7.95152 8.35556
+2.40133 2.936
+2.77819 3.87516
+3.252 4.33376
+9.54269 9.7513
+6.6747 6.73043
+0.611474 1.97158
+7.65864 8.53689
+1.58345 1.8017
+2.56917 2.8152
+8.5424 8.8301
+4.98159 5.44499
+5.82482 6.03578
+3.55509 4.90785
+5.77028 5.94747
+0.163965 1.1379
+2.85039 2.94261
+4.24343 4.67273
+3.22636 4.06084
+6.03662 6.21018
+4.55495 5.07697
+1.91173 2.51739
+6.54894 7.24036
+5.55502 6.92676
+0.245707 0.586188
+2.28044 3.29563
+4.71378 5.25198
+8.28953 8.44891
+9.42282 10.179
+5.0548 5.73614
+6.3203 6.43659
+6.54178 8.82077
+3.67181 4.17365
+8.51445 8.96445
+1.69648 2.84524
+0.194222 0.920147
+2.48533 2.59803
+1.66002 1.6739
+4.79833 4.95404
+1.09801 1.11009
+6.62529 7.4066
+8.0099 8.37262
+3.55429 4.11824
+6.2666 7.12137
+7.83222 8.01342
+9.37156 9.72961
+1.1647 4.04434
+4.50719 5.09068
+3.25175 3.75482
+8.28659 9.30848
+7.30009 8.60755
+-1.12073 1.21016
+0.310087 0.725712
+8.3746 9.13511
+9.11925 10.2234
+9.68703 9.7137
+0.603098 0.844291
+5.88373 6.99327
+0.852802 1.43297
+3.7463 5.82283
+7.69639 8.25446
+-0.337322 0.977113
+8.76606 9.16618
+3.43527 3.6616
+3.93587 5.39471
+5.66569 7.20462
+5.34999 5.7193
+3.25589 3.706
+1.52012 2.55985
+4.74228 5.43725
+5.15323 5.51652
+7.77237 8.33717
+-0.0514419 0.914127
+9.27182 9.59476
+8.14192 9.74859
+6.42702 7.20331
+7.51351 7.68358
+7.0947 7.46059
+7.97635 8.59449
+2.39931 2.66008
+5.79481 5.94673
+4.41054 4.81613
+2.72202 3.61239
+2.86039 3.44719
+1.81115 3.28151
+-0.566995 0.734214
+9.61998 9.72024
+7.4163 7.61821
+0.42522 0.552659
+3.17617 4.36942
+0.740294 1.36953
+7.13755 8.39966
+0.219186 0.892588
+3.78307 5.2905
+0.783026 1.76155
+3.01893 3.33055
+3.12143 3.5713
+-0.792679 0.92539
+0.668572 1.12961
+3.88619 4.30545
+7.59276 8.1776
+4.71509 5.05622
+6.53406 7.04242
+1.581 2.21984
+4.7144 5.51372
+2.76338 3.50211
+0.16364 0.293599
+5.92365 6.10636
+3.11174 4.29165
+5.49295 6.48717
+-0.503239 0.795707
+7.30558 8.12408
+2.10674 4.13456
+7.11985 8.01932
+1.34672 1.48739
+4.05778 5.69084
+2.83686 2.9115
+6.4471 6.53909
+0.467374 1.84371
+2.76467 2.94177
+4.87867 5.33932
+0.892878 1.96273
+1.13934 2.27205
+7.76918 8.39409
+6.72181 7.43901
+7.0836 8.68472
+7.12924 7.56332
+0.689172 1.62922
+9.41146 9.91043
+0.398265 1.27579
+6.29966 7.4874
+5.09438 5.65334
+6.04623 6.4687
+5.75305 6.89731
+0.308118 0.459501
+3.63692 4.30501
+3.1755 3.71009
+7.32787 7.52785
+2.23235 4.09978
+2.71191 2.91513
+0.209457 0.840713
+7.31489 7.38296
+6.21245 6.91111
+5.75983 5.96049
+5.92056 8.24518
+-0.354452 0.489638
+4.05894 5.34828
+1.56299 1.57414
+2.85083 3.27455
+8.78323 10.0012
+0.208502 1.26471
+6.10824 6.79285
+5.55114 8.03968
+6.13077 6.32342
+7.34865 7.82592
+3.94835 4.75016
+7.8268 8.72249
+4.85131 5.07903
+5.40398 6.0134
+2.85971 3.85293
+0.126379 1.45545
+3.15768 4.28388
+9.64566 9.70016
+4.47514 6.31064
+6.44995 7.2894
+4.70992 6.13777
+3.91128 4.22263
+7.35627 8.07739
+2.49215 2.68749
+8.09946 9.16929
+0.925679 1.92784
+8.48437 8.63892
+7.2255 9.18109
+-0.00840282 0.0168954
+5.91933 6.6274
+4.16086 4.64302
+8.27009 8.47868
+1.73372 2.93094
+8.17421 9.17705
+9.19136 9.43222
+0.0653594 0.648416
+8.69 8.96184
+8.99355 9.40832
+6.25088 6.26945
+6.72391 7.38424
+9.59708 10.3496
+6.00971 6.18818
+4.64468 5.75797
+3.64832 5.30079
+5.99378 7.8792
+6.5388 6.99379
+7.31694 8.43802
+3.66227 4.92638
+9.55964 10.3796
+-0.14433 0.29095
+3.56716 3.71252
+3.82062 4.27788
+8.10405 9.35275
+7.17891 7.46539
+1.17698 1.29602
+4.48829 5.03134
+7.18025 8.13852
+9.42388 10.3634
+5.2158 6.17469
+5.22926 6.52397
+5.16731 6.40625
+6.53348 7.269
+2.07834 2.39172
+9.65044 10.1519
+8.64551 10.1294
+9.29006 10.5993
+1.50639 2.83173
+5.71675 5.99216
+3.0783 3.35571
+0.115401 1.31431
+8.03988 8.11942
+3.11917 4.53956
+1.14552 1.1646
+5.34782 6.43017
+0.0701702 1.0368
+0.183335 0.440704
+6.33438 7.71607
+2.11533 2.64323
+7.12104 7.13366
+7.21548 8.26968
+3.13445 4.13568
+4.57452 4.74602
+2.60889 3.69846
+7.21184 7.47573
+6.87651 7.03405
+2.65431 3.94352
+1.50006 1.70087
+6.16344 7.54429
+7.02057 7.73067
+8.27833 9.01489
+0.500833 0.597845
+8.34751 9.88925
+2.80242 2.91837
+5.29424 6.079
+8.36276 9.10074
+0.216887 0.268335
+1.30798 3.16393
+3.93851 4.22658
+2.58028 3.14744
+9.31131 10.3451
+7.37262 8.84852
+4.45306 5.6723
+3.74535 4.0721
+4.90174 5.63875
+3.41847 4.65199
+3.10265 3.82548
+6.56126 6.97557
+2.57449 2.95098
+7.97418 9.06301
+9.2203 9.66829
+4.64922 4.96305
+8.83034 10.115
+6.6685 6.89847
+7.36585 7.48669
+8.66761 9.39287
+0.562216 0.961875
+7.56292 7.81006
+8.50715 8.95572
+0.572825 2.24755
+5.9367 6.06766
+-0.769578 0.776163
+4.48224 4.9553
+8.21069 9.29643
+8.57206 9.47175
+1.10032 1.21371
+3.76306 3.87152
+6.46197 8.18457
+6.96501 9.70727
+3.42357 3.93484
+0.818601 2.42743
+-0.119739 0.397938
+-0.378761 0.523892
+8.03394 9.35409
+3.60283 3.98864
+2.21789 2.70607
+-0.255329 0.319063
+6.20806 6.22609
+7.1283 8.04391
+3.73565 4.03638
+8.5374 9.10987
+5.22675 5.35072
+7.51777 7.58439
+9.12636 10.4159
+9.15003 9.40672
+0.217863 1.19883
+9.42416 9.9178
+2.55337 3.8088
+7.03655 7.98242
+9.17171 9.8047
+0.110162 0.722738
+3.16467 3.58897
+6.47244 7.12961
+1.0456 1.65614
+1.58456 1.62844
+1.79039 1.84035
+6.24286 7.07838
+9.08631 9.11684
+3.05068 3.40838
+2.81212 4.03665
+2.52011 3.09841
+8.06001 8.16356
+7.07649 7.52685
+2.47666 2.86548
+8.66241 8.95103
+-0.298116 0.662697
+0.822443 2.46125
+2.07619 2.33674
+4.84135 6.21034
+7.49625 8.13026
+7.85854 8.29618
+3.01722 3.37062
+6.54393 7.30306
+2.21113 2.30166
+8.32138 8.57349
+6.2995 6.33514
+3.0018 3.56886
+4.63378 5.52214
+6.71908 8.96715
+2.29809 2.95581
+8.34947 8.71096
+4.96902 5.32075
+9.51051 9.72733
+3.311 4.77789
+3.50233 3.66309
+4.95177 5.76002
+6.12876 7.22391
+6.27743 6.79393
+3.60638 3.6833
+5.20305 5.50848
+7.16065 8.88358
+9.45049 10.2539
+6.16892 7.0314
+8.08479 9.74516
+0.0717867 0.669987
+2.17569 3.34098
+4.81716 5.7509
+7.63999 8.01157
+5.87228 6.60363
+3.39621 4.35575
+4.96079 5.07901
+7.57639 8.82003
+8.27285 8.52609
+0.665858 1.64782
+1.74256 2.07126
+6.19512 6.4258
+0.664592 1.30896
+0.180682 1.43746
+6.46752 6.81303
+2.55562 3.08708
+9.33695 9.63312
+6.33821 6.77092
+7.88252 8.55026
+8.17937 8.45385
+-0.415294 0.793096
+5.22077 5.54553
+8.67808 9.10041
+1.72096 1.92024
+0.492778 1.48076
+2.29514 2.88531
+0.0934389 1.37614
+8.40297 9.11121
+3.66605 3.91717
+-0.274468 0.867811
+9.41428 9.56659
+1.22657 2.12792
+8.71336 9.85384
+5.09347 5.42905
+2.02877 2.36652
+5.99112 7.40703
+0.911618 3.48138
+4.84352 5.11131
+1.16309 2.08613
+5.58561 5.84805
+0.663543 1.08921
+1.83189 3.93269
+4.07731 4.38879
+4.04789 4.9989
+2.09457 3.61279
+2.00982 2.94396
+7.37537 7.66574
+5.08648 5.80122
+9.19959 10.2263
+4.26136 4.86194
+6.67875 7.61134
+1.27462 2.48399
+7.2237 7.82324
+-0.0141009 0.0441377
+8.32069 8.36192
+2.82562 3.0717
+-0.528918 1.25301
+1.90486 3.04714
+1.34489 1.75301
+3.14332 4.03322
+8.55351 10.8681
+9.09824 10.3828
+0.496868 0.622499
+7.11112 7.62765
+0.335233 0.528962
+6.71335 7.13937
+6.78574 7.71172
+9.13568 9.22251
+7.10299 7.64765
+3.64747 4.06685
+8.64041 9.40111
+2.43515 2.93081
+2.95476 3.68588
+0.0863751 0.777976
+6.5891 8.18165
+8.80986 10.0735
+0.568868 1.63785
+4.41677 5.42049
+8.72857 9.88426
+3.67467 4.25442
+8.98168 10.1087
+5.08611 5.50098
+1.28982 2.34422
+-0.914176 0.969847
+4.35042 4.42735
+4.02282 5.08164
+9.00566 9.4791
+2.71821 3.24065
+3.20252 3.24988
+8.61559 9.6733
+3.15157 4.7685
+3.59348 4.67872
+0.286864 0.36279
+8.40374 10.528
+7.53647 8.13523
+6.81591 6.90226
+7.68111 9.10704
+8.37958 8.73818
+3.25808 4.40893
+1.50348 3.00641
+0.20803 1.40949
+3.93771 4.84177
+2.79232 3.35329
+4.2666 4.63588
+0.341784 1.46241
+1.53063 2.06724
+8.58212 8.86194
+8.95411 9.70651
+8.71591 9.26292
+6.66088 6.7009
+3.95881 5.93917
+8.5823 8.76007
+-0.308958 0.34174
+1.03188 1.37677
+7.52675 9.84031
+4.27952 4.32984
+1.83465 2.27607
+8.12096 8.64922
+2.22605 4.40067
+0.00929139 0.871342
+0.376531 1.29354
+3.5257 4.30165
+1.95846 4.09589
+-0.200922 0.799272
+0.24432 1.76673
+4.73477 5.06514
+8.97059 9.2276
+2.89618 2.93969
+0.168256 1.03325
+3.44522 3.83622
+2.74889 2.76042
+6.07155 6.7979
+9.06484 9.09804
+7.56658 9.29215
+4.3084 5.45621
+-0.0786996 1.12809
+8.48249 9.74107
+6.4196 6.61469
+1.57119 1.87612
+3.15463 3.86251
+2.0089 2.57741
+6.53618 7.12035
+7.07901 7.29396
+0.114756 0.887413
+8.90806 9.65731
+4.0921 5.23407
+2.63441 2.92344
+4.31769 4.98832
+8.90336 9.26837
+8.25313 8.91204
+2.87758 4.00212
+-0.708243 0.789072
+3.28656 4.55872
+5.73177 5.80293
+5.40596 5.5844
+4.09318 4.57774
+6.16178 7.00613
+8.5514 10.5495
+6.83987 7.3056
+1.06341 1.97923
+7.82153 9.00722
+0.923069 1.42337
+1.83408 2.82331
+5.75305 7.23576
+0.241909 0.96721
+1.16645 2.10491
+5.41819 6.09839
+7.49242 7.69495
+0.347233 0.383681
+2.33245 2.53467
+4.91249 5.27759
+8.11182 9.2758
+0.0955456 0.548659
+-0.359909 0.48055
+1.64759 3.47097
+6.37855 7.40015
+0.423283 2.08857
+4.10068 4.46856
+2.58389 2.69626
+0.848483 2.72258
+8.67321 8.88903
+2.07607 3.42398
+3.11033 3.80741
+2.24735 3.48626
+8.11883 8.7687
+0.29959 1.41603
+4.84924 5.13641
+1.44102 1.74592
+1.13437 2.50296
+1.75876 3.09859
+4.75363 5.90838
+7.36423 8.20074
+5.51578 6.42652
+0.915633 1.86015
+9.44679 10.3479
+2.61691 3.60215
+6.26524 7.2538
+2.74326 3.12649
+5.83934 6.98592
+9.1111 10.4891
+2.27066 2.82709
+8.19359 8.67233
+0.834236 1.7066
+6.19288 7.21392
+-0.249843 0.891821
+2.5652 3.25132
+5.25356 5.88905
+3.99545 4.18918
+1.93186 2.51527
+4.44621 4.82421
+5.89181 7.36963
+2.77321 3.60627
+2.76444 3.88016
+2.50062 2.66105
+1.14846 1.66146
+2.951 4.81656
+3.81976 4.01061
+4.75674 5.59916
+6.74092 7.08289
+2.09989 2.32514
+0.220723 0.865303
+5.48107 5.71875
+1.48372 2.88941
+0.484577 1.12051
+8.93618 9.7185
+1.89769 3.65655
+2.0129 3.55214
+9.23173 10.3694
+0.286189 1.22753
+0.453785 1.55541
+2.24068 2.6541
+8.80917 10.4969
+7.12801 7.15222
+9.25745 9.9103
+5.73429 6.76901
+7.54454 8.47157
+1.96008 3.74997
+8.00837 9.25665
+1.66384 2.07613
+5.53014 5.97461
+-1.32495 1.33319
+4.58479 5.2263
+7.92048 8.75668
+6.87595 7.02522
+0.157713 0.389585
+7.48277 7.51261
+8.10714 8.38399
+0.0802723 0.587088
+1.13024 1.71135
+5.71769 6.84757
+3.08261 4.31054
+2.95952 5.09762
+6.62815 7.44256
+5.0805 5.8499
+3.38489 3.73265
+1.10644 2.18331
+4.70493 7.31686
+2.2253 2.6338
+0.778359 1.6265
+6.94211 7.2149
+4.20976 4.99342
+7.47792 7.67881
+7.06219 8.76137
+4.97677 6.12206
+6.30829 6.69361
+6.19977 6.76781
+9.67636 10.2172
+3.41958 3.69137
+0.374486 0.943711
+4.00837 4.80107
+8.85401 10.1325
+6.0938 7.8919
+1.51055 3.08998
+8.94594 10.3139
+1.06714 2.65511
+0.703202 0.850595
+4.87735 6.00659
+8.3067 8.39924
+7.78071 8.3155
+1.98737 2.81116
+6.86323 8.07974
+1.03479 1.34584
+0.490512 0.670211
+5.82122 6.1901
+5.50836 6.63385
+7.9192 8.9606
+0.913719 2.18983
+4.97151 5.70909
+4.19907 4.37712
+2.01188 2.63318
+7.84813 9.3771
+5.32667 7.48502
+8.50951 10.1006
+-0.551637 0.930509
+1.06511 2.23353
+1.91111 3.42663
+9.37528 9.55327
+7.27975 7.38741
+3.46676 4.83165
+7.36137 8.70333
+-0.295762 0.623228
+8.48558 8.81076
+2.71689 3.41873
+6.49265 8.11042
+5.25516 5.57336
+6.10462 7.05991
+8.76997 9.15164
+7.86196 8.30651
+7.82765 9.24604
+5.98573 6.34182
+6.45367 7.47857
+3.27018 5.10835
+1.3079 2.37423
+-0.261387 0.338113
+7.60683 8.81791
+4.7346 7.41988
+5.25597 5.28517
+3.76704 4.52226
+3.91774 6.66976
+5.69618 8.92667
+1.86148 3.07531
+5.57404 6.51438
+9.39049 9.77921
+2.38692 4.21416
+6.84909 7.23633
+7.2379 7.58761
+4.73485 6.11606
+7.80013 8.08105
+1.72701 3.40244
+2.44475 4.4072
+9.72565 9.77726
+3.35288 4.06493
+8.91215 9.92325
+8.67991 9.65865
+0.253195 0.764339
+4.23564 5.59497
+1.84752 2.14986
+-0.502957 0.528737
+1.32656 2.11347
+9.81563 10.0213
+7.60114 8.05035
+8.51797 8.83342
+-0.394604 1.41267
+7.71614 8.63514
+0.530249 0.968898
+2.90463 3.01675
+7.58098 8.71658
+-0.253747 1.28827
+1.832 2.39006
+7.2268 7.27225
+3.84076 4.66703
+2.2564 2.73185
+7.31508 8.46008
+4.99387 5.64948
+7.21239 7.79983
+7.60231 7.8473
+0.555482 1.41892
+1.25539 1.73665
+8.41561 8.96404
+5.06771 5.17664
+0.0655744 2.10718
+8.00222 8.65909
+7.48841 7.83609
+6.30909 6.89448
+9.1697 9.55942
+1.36259 2.22582
+-0.923854 0.994771
+3.43724 4.64053
+8.09411 8.19574
+4.84869 5.52805
+2.69802 3.4119
+9.0613 9.29405
+0.565216 0.687165
+5.93495 6.57426
+1.86925 2.75493
+1.41068 2.00824
+1.60612 1.62471
+3.11499 5.89909
+2.69806 3.90538
+3.76301 4.22135
+3.30065 4.70725
+5.56461 7.02137
+8.35335 8.99287
+4.79259 4.88508
+6.7911 7.52912
+8.14843 8.28583
+3.67629 5.06406
+5.71462 7.04747
+9.06721 9.99733
+4.87932 6.8586
+8.00814 9.57664
+7.03069 7.51623
+9.0989 9.57644
+2.70873 3.91296
+1.64425 1.7007
+6.53716 6.99033
+8.29874 8.74509
+1.88941 2.57626
+4.65337 5.23247
+9.04723 9.06665
+3.52258 3.61496
+1.1207 1.80143
+0.680601 1.98384
+2.94593 5.38692
+2.65685 2.67932
+9.00469 10.2054
+6.44318 7.2657
+4.66656 5.33893
+3.41719 4.72453
+3.12403 4.21748
+6.67973 6.81775
+3.54347 4.14978
+3.02554 3.50812
+3.91883 3.93657
+7.31721 7.89895
+1.86275 2.85473
+6.23266 6.4449
+7.59855 9.38013
+9.07084 9.49309
+0.557656 2.6851
+6.899 7.37693
+4.23162 5.84314
+8.54108 9.37672
+3.9513 4.79746
+7.299 8.29678
+5.58879 5.88551
+9.14992 9.22385
+9.1914 9.31788
+4.95663 5.56316
+2.16516 2.39538
+0.722262 1.89664
+7.76447 7.80026
+2.77772 3.39136
+9.59513 9.78635
+1.02728 1.2181
+7.32631 7.56611
+7.37389 7.46163
+6.87949 8.18689
+8.95602 9.81169
+5.85364 6.63434
+0.129136 2.13484
+7.09608 7.71167
+7.1487 8.34258
+7.48738 8.3172
+8.77247 9.95985
+7.6706 9.56828
+8.14268 8.61726
+6.5455 7.90871
+4.57866 4.78453
+3.63937 4.42349
+5.18905 5.36516
+4.68884 5.62995
+5.88338 7.83824
+-0.002979 0.145818
+4.42981 4.77141
+0.558593 1.07999
+6.91713 7.36159
+5.13948 6.20805
+3.34368 4.07112
+7.27365 7.8383
+9.6898 9.9514
+6.14332 6.75102
+2.16534 2.78843
+2.8007 4.37952
+7.67047 7.72955
+8.77377 9.85092
+1.26087 1.55193
+6.29788 6.58511
+7.68178 9.05777
+0.383336 1.21247
+2.55185 4.30874
+8.91971 9.21836
+3.67638 4.68596
+8.13843 9.13684
+-0.424353 1.97502
+2.71499 2.93977
+0.104447 0.387901
+4.09592 4.67009
+0.808593 0.920798
+5.01258 6.30662
+4.97668 6.57412
+8.44135 9.03816
+2.78932 3.72809
+6.71337 7.15128
+4.27234 4.50127
+6.78266 9.70351
+6.48026 7.51491
+7.36296 8.42283
+4.80339 7.3704
+6.24735 7.3132
+0.134626 0.364187
+2.73854 4.09422
+0.809997 1.19657
+6.41154 6.50244
+7.16847 8.56485
+1.53582 3.33985
+1.92874 2.86427
+6.95941 7.01378
+5.8592 6.54917
+2.51802 2.75622
+3.3894 3.6957
+2.2547 2.64693
+8.62054 9.1951
+8.86378 10.0003
+1.87892 2.28732
+3.83146 4.21484
+1.53262 1.99692
+7.86048 7.93125
+1.79437 2.68269
+3.92781 4.24119
+5.43044 5.47935
+0.322904 0.618854
+3.42383 5.18531
+4.00989 5.83612
+7.06304 8.76582
+5.88039 6.77654
+8.638 8.9479
+1.73391 2.09002
+1.04861 2.84779
+-0.313019 0.557659
+3.35245 4.1308
+9.05373 9.57205
+5.85684 6.49193
+6.00719 6.86421
+4.25244 4.65772
+5.15865 5.61529
+8.78498 9.77544
+8.33803 9.26452
+3.42915 4.92279
+8.29884 8.94035
+5.10232 5.35924
+4.33571 4.86695
+7.86184 7.90029
+7.34345 7.36214
+0.201624 0.800371
+9.05882 10.5503
+4.32188 5.03154
+-0.0456982 1.22298
+2.90921 3.60013
+1.69306 2.36564
+7.79029 9.15059
+4.65205 5.06538
+6.34552 8.32176
+7.92695 9.32585
+7.17903 8.09903
+9.53561 9.60287
+0.365723 1.23929
+0.542889 0.849053
+8.15061 8.93512
+6.40042 6.41053
+5.82666 6.5488
+1.00893 1.83717
+1.76021 2.11893
+7.61076 8.6242
+2.32513 3.4856
+4.39023 6.01094
+-0.11754 0.421848
+6.76371 6.94513
+4.67607 5.58732
+-0.201992 0.765553
+7.42926 7.44429
+2.57485 2.85339
+2.74138 4.13421
+8.21645 9.18107
+6.28184 6.4996
+7.129 7.74678
+7.76842 8.74924
+3.5359 4.35892
+3.04103 3.24376
+2.29389 2.92164
+6.96306 7.64415
+8.82053 9.04584
+1.19911 2.06167
+5.91357 7.6773
+0.150241 1.23291
+4.48681 5.41762
+6.89156 8.13443
+5.37828 5.79944
+2.13694 2.91102
+1.35932 2.08272
+6.14309 6.23278
+4.03202 5.88521
+7.23417 7.43704
+1.2501 2.60793
+2.12334 3.65727
+7.05722 8.77078
+0.437873 0.585933
+6.33338 9.16643
+2.44724 4.40234
+2.92012 3.64047
+1.2039 3.25195
+8.6611 10.0398
+8.0088 9.13622
+5.96562 7.08515
+5.45181 6.65246
+0.742546 2.38958
+4.12919 4.93571
+0.428823 0.84483
+1.45226 2.5869
+9.50727 10.0211
+7.69194 8.66273
+1.25706 2.44554
+5.23247 5.47762
+0.499178 1.70722
+7.26569 8.72467
+3.59815 5.50022
+1.03601 2.43445
+0.092414 0.927635
+3.7917 3.995
+6.21977 8.40398
+3.1513 3.81188
+9.80482 10.0951
+8.65564 9.33687
+2.06164 3.49152
+2.09754 2.34929
+0.66126 2.31888
+5.34832 6.82603
+7.91038 8.59105
+0.695523 0.800961
+2.33406 2.71629
+8.37774 10.9253
+9.7682 10.106
+9.44382 9.5743
+8.78009 9.47645
+1.87309 3.04127
+1.86724 2.13913
+3.30049 3.52416
+7.18508 7.6648
+1.3736 2.12153
+2.41879 5.06716
+1.87815 2.29743
+1.76646 2.06335
+9.73034 9.95475
+0.497489 0.686102
+6.96908 7.17338
+9.23111 10.0148
+3.30981 4.21787
+9.53311 10.3734
+-0.067709 0.147251
+8.44557 8.82047
+7.10407 7.47639
+0.834352 1.36908
+9.1598 10.6508
+4.22018 4.38279
+3.8295 3.95462
+3.97302 4.97247
+1.55856 2.31013
+0.0217962 0.486978
+1.69845 2.65786
+-0.489562 0.582187
+5.10621 5.6055
+9.8478 9.85919
+6.15389 6.92324
+7.11469 8.0418
+3.20625 3.78209
+5.93389 7.66892
+1.15134 1.18023
+6.84797 7.4239
+2.9483 3.22279
+-0.43205 0.764755
+7.17846 7.33313
+5.4729 8.26894
+6.19512 7.32132
+0.591934 0.767568
+0.49266 1.80691
+9.08272 9.72242
+5.85683 6.36905
+5.27625 7.13913
+3.60853 3.98155
+0.642811 1.10253
+1.27117 1.5329
+8.76096 9.61776
+4.9498 5.12847
+7.53282 7.80438
+1.40487 1.65657
+3.45329 3.84307
+3.25698 3.49614
+2.38651 2.89802
+8.23114 8.99016
+9.58516 10.4145
+5.5185 6.27733
+0.583068 0.892249
+1.93142 2.35084
+7.94845 9.22667
+2.47963 3.9005
+3.46106 3.86301
+7.77744 8.43735
+1.41072 1.73969
+9.12904 10.4307
+3.52227 3.66861
+5.4743 5.86487
+-0.51727 1.63657
+5.09861 7.03162
+5.14763 5.93411
+3.23526 3.47376
+0.9702 1.74063
+9.28366 10.3322
+1.80257 1.92265
+8.63597 9.08467
+4.16006 4.97753
+6.37418 6.39374
+5.82376 6.62429
+7.74751 8.68962
+1.63821 2.53399
+4.9864 6.40969
+0.680772 0.995608
+3.74344 3.83319
+0.898055 1.8593
+2.36839 2.39307
+7.21046 7.51006
+0.60893 2.91523
+3.15017 4.30412
+5.02219 6.28886
+4.60541 4.73379
+8.41196 8.58978
+8.84706 10.8198
+6.95807 7.54952
+5.54729 6.9315
+4.62574 4.73423
+3.35252 3.59865
+1.02207 1.71791
+3.16408 3.73993
+0.639222 1.69519
+7.57978 8.05813
+2.41371 2.77174
+8.65544 10.093
+6.31988 6.70758
+6.5301 8.39328
+0.578825 1.20331
+1.1243 2.07824
+5.86555 6.72397
+6.37103 6.81736
+1.12086 3.46541
+2.59503 3.44073
+5.27128 5.3616
+2.87331 3.4352
+5.48408 6.67916
+3.36016 4.09125
+0.813671 0.9811
+0.812162 3.22209
+6.85104 6.86306
+0.671311 0.979685
+2.75962 2.82659
+2.42186 2.49827
+7.82974 9.59669
+3.48851 3.60085
+8.47775 10.9574
+8.6863 10.6155
+0.196484 1.07469
+1.19293 1.45012
+5.79166 6.18466
+6.51597 6.6793
+9.78341 10.1992
+8.17879 9.59257
+6.96178 8.73165
+4.09161 4.31908
+3.19514 3.4072
+5.5101 6.32978
+0.188435 1.84481
+9.41738 10.0379
+1.46994 1.6294
+4.21915 5.39529
+5.46567 5.86638
+8.19414 9.201
+4.38616 4.55193
+2.31105 2.73345
+6.05897 6.12297
+8.84135 9.74232
+9.44943 10.2225
+3.27501 3.66059
+0.524904 1.74374
+7.7228 8.43799
+5.13274 5.82863
+8.2787 8.94491
+1.61463 2.03499
+7.04346 8.69977
+0.938308 2.38676
+0.00208037 0.0186158
+1.98744 2.05864
+7.05787 8.16211
+1.68383 2.04684
+2.24812 2.28257
+0.685061 1.2947
+2.25379 2.92827
+6.0052 6.24797
+7.06213 7.86344
+0.751849 2.96376
+0.0977921 0.513746
+8.43792 9.10545
+2.80769 3.09276
+9.19308 9.59741
+4.74365 4.99708
+8.41385 8.58422
+4.28093 5.9281
+4.26205 4.75417
+1.48035 1.61363
+1.4264 1.80922
+3.48365 4.52935
+1.78396 2.96351
+8.4134 8.96536
+8.65646 9.34781
+1.88027 2.97804
+8.92531 9.02743
+6.91815 7.88895
+5.68023 7.37521
+3.93105 4.6123
+0.385874 1.30785
+1.80151 2.24385
+8.43781 9.33927
+6.69643 8.001
+6.12062 6.673
+4.8316 6.63067
+9.00443 9.08204
+1.5651 2.65023
+3.57517 4.40231
+5.85127 8.02219
+8.02586 10.018
+2.00514 2.75138
+6.32104 7.84285
+8.90914 9.78319
+4.91325 6.27817
+3.87406 4.80327
+8.57887 9.30685
+1.40351 1.71079
+-0.217977 0.224497
+8.37711 9.56393
+5.54644 5.77714
+8.18206 8.36015
+0.774967 1.97899
+9.10434 10.1721
+9.39621 10.1135
+4.80108 4.90605
+9.45978 9.96227
+2.85412 4.05215
+5.71985 7.16735
+2.35081 2.82214
+9.34881 10.5899
+7.13014 7.82872
+4.54931 4.89725
+9.41397 9.9131
+8.90226 9.55276
+8.27995 9.83651
+9.2767 9.6053
+0.388751 1.40317
+5.01478 5.88869
+6.41521 7.21754
+1.22552 1.39067
+3.75771 3.81571
+4.39362 6.04592
+8.82639 8.84544
+4.59289 4.89208
+1.52235 1.64285
+1.85893 4.52056
+1.91781 2.78253
+3.34677 4.54987
+9.26905 10.6019
+7.10958 8.02083
+0.765257 1.66957
+2.17169 2.70214
+4.2293 6.38089
+1.41111 2.45992
+5.76864 6.85715
+2.19944 2.93182
+9.03727 9.6454
+3.82652 4.35225
+2.52642 3.09725
+7.77868 9.35844
+0.337665 1.00787
+1.92021 2.04418
+4.41862 5.95486
+9.47606 9.62386
+1.12113 1.55658
+5.26701 7.09712
+8.81478 9.34863
+6.29447 7.43847
+2.82379 3.57268
+7.9735 8.79936
+3.30176 5.50666
+6.36009 6.8864
+4.13583 5.00627
+0.510514 0.882245
+6.93864 7.78543
+2.04039 2.4298
+3.18337 3.19424
+4.20059 4.67088
+0.316687 0.707377
+0.169106 1.68194
+8.26665 10.2362
+1.1124 1.78306
+2.84603 3.33142
+9.48756 9.96651
+9.4301 9.7316
+0.234674 1.23981
+0.493232 0.522565
+1.342 1.41739
+2.57196 4.08221
+1.54201 2.52284
+5.32049 6.00052
+8.54218 8.59452
+-0.030524 1.64476
+2.31645 2.72528
+4.71898 4.92827
+0.0872997 1.74969
+0.994278 1.76964
+1.34411 2.77952
+0.156817 2.10245
+5.78094 6.34389
+3.09336 3.10563
+8.14245 9.0928
+9.34202 9.75484
+9.78415 10.0211
+4.68383 5.19384
+6.09441 7.90512
+6.74941 6.76118
+1.78693 1.91697
+2.34369 2.62141
+-0.20756 0.829082
+3.57681 5.11448
+2.44234 4.45153
+4.84521 5.31902
+1.80487 3.64498
+2.46125 3.02549
+-0.334514 0.64288
+8.06406 8.49886
+1.74559 2.54474
+6.05883 6.46529
+9.00014 10.2271
+8.00064 8.5061
+0.909467 0.980765
+8.65862 8.69736
+8.11457 8.77049
+3.93237 5.02485
+4.64507 5.34852
+3.92405 4.19449
+5.02381 5.21722
+3.76203 3.78396
+6.74925 7.34781
+8.2556 8.63585
+3.92521 3.99739
+1.44641 2.31509
+0.23516 0.917239
+4.4614 6.35489
+3.33221 3.95247
+1.73289 2.07919
+6.92385 7.55052
+8.74351 9.41125
+9.41451 10.1785
+7.4001 8.81081
+2.97038 3.12524
+7.26043 7.77569
+5.56625 5.59344
+5.70977 6.33362
+7.61443 8.43218
+1.05308 1.82947
+0.377602 1.57633
+6.42483 7.51505
+4.73011 5.43693
+7.72 8.09098
+9.20063 9.82287
+6.88273 7.35327
+6.88423 7.68356
+3.55293 3.6227
+0.947096 1.76021
+3.66411 5.67117
+9.31422 10.1035
+6.84847 6.98956
+2.16221 4.45806
+0.853284 3.15932
+2.48673 2.89793
+3.37633 3.90938
+1.6141 1.66363
+1.6658 3.01723
+0.419408 1.01736
+0.712239 0.791538
+2.25249 3.62425
+8.09772 10.2367
+1.46651 1.48148
+1.73233 2.0489
+7.42679 9.23232
+7.97446 9.53281
+2.74677 4.03955
+-0.169412 0.872795
+4.90663 5.40277
+7.62122 9.49334
+6.55971 7.34259
+3.71957 5.03775
+3.33226 4.06459
+0.634912 1.52603
+3.65506 4.09318
+4.31463 4.60534
+8.58287 9.85385
+0.334759 0.7232
+2.14027 2.866
+6.06611 6.3625
+2.53013 3.18764
+4.30913 4.89247
+6.53234 6.92328
+7.66419 8.61762
+1.37598 2.26754
+8.06279 8.80692
+5.28688 5.70608
+0.509396 1.34606
+8.80589 9.29765
+9.3801 10.3988
+0.402662 0.597735
+5.87213 6.63371
+2.79136 3.763
+6.20615 7.25189
+7.54065 9.62156
+4.12107 5.04454
+5.60294 6.69246
+1.20845 1.49272
+1.75679 2.56397
+2.83939 3.85147
+6.21362 6.71341
+9.01824 9.2388
+4.66617 5.04944
+1.48766 2.55674
+8.89442 9.42175
+5.29411 5.39531
+6.66271 8.68733
+0.730461 1.42466
+6.22927 6.55086
+0.566776 1.17299
+3.06104 4.17775
+5.28026 5.73966
+5.76071 7.61585
+7.83786 9.58106
+6.32199 6.46961
+8.89555 9.17429
+3.85772 4.97805
+6.63352 8.79211
+7.87234 7.94131
+6.53479 7.87979
+3.90293 4.50376
+6.21371 7.31788
+1.00497 1.75003
+6.90351 8.02435
+2.29142 3.9809
+6.26632 6.45283
+-0.0354471 1.31727
+8.80046 9.20169
+7.86905 8.36819
+0.848737 1.82393
+7.98136 9.40712
+3.97765 4.95399
+8.70252 9.26275
+3.13412 4.29389
+2.06446 3.55839
+7.67918 8.44509
+5.96082 6.40336
+1.20461 2.36924
+4.76741 5.74978
+9.41217 9.94305
+7.36736 8.07119
+3.44102 3.56957
+3.59893 4.52751
+4.2613 6.41628
+1.65321 3.02235
+3.70067 3.86657
+0.0176327 1.1215
+4.13592 4.88595
+8.73668 9.0834
+1.80944 2.95584
+6.05721 6.93009
+5.08206 5.38626
+1.86749 1.89392
+3.58284 4.10506
+0.0885586 1.47709
+5.46502 5.93066
+8.45338 8.47878
+3.46789 4.02317
+0.975506 1.15814
+7.12758 7.60073
+7.99582 8.56746
+3.11435 3.83805
+4.51166 4.52472
+8.39096 8.75934
+8.42208 9.66019
+2.48498 4.73703
+3.50301 4.81264
+6.40196 7.0733
+8.52138 8.82265
+1.49822 1.74634
+7.08547 7.93508
+3.47832 4.42948
+6.08646 6.20865
+4.46334 4.65278
+3.80008 4.08214
+3.4853 5.44308
+5.48109 6.18681
+6.59161 8.04307
+7.36554 7.38201
+5.2144 5.31725
+4.62607 7.25804
+1.24345 1.81263
+5.49248 8.16867
+6.4056 8.26316
+7.67828 8.56923
+2.46187 2.56974
+2.22942 3.27248
+7.14933 8.06682
+2.3236 2.95462
+4.18028 4.80535
+4.981 5.54215
+7.23261 7.34863
+4.96309 6.06396
+4.24402 4.44364
+0.917707 1.32687
+1.19806 1.65106
+3.7725 5.31412
+9.70021 9.84203
+5.99824 7.77474
+3.32636 3.84266
+8.59841 9.07653
+7.9916 9.14415
+0.786519 1.84655
+0.166394 1.47834
+2.87633 3.52808
+7.53804 9.56807
+6.14406 6.16189
+1.63428 3.96845
+1.10307 1.58897
+1.30032 2.85313
+7.89803 8.32723
+8.77593 8.90136
+1.68804 2.69447
+4.5956 4.6743
+7.39643 8.29839
+6.93629 7.82243
+6.10289 7.677
+1.83835 2.34295
+1.04506 1.91684
+8.95277 9.43817
+0.36153 0.643665
+1.02408 3.18963
+4.02972 4.40301
+2.80428 2.82552
+6.51718 6.64956
+0.185341 1.56607
+6.1658 7.59364
+4.09288 4.11687
+6.90205 7.16338
+5.0755 5.39478
+4.5614 4.83286
+5.8489 8.76295
+9.70079 10.0431
+8.44334 8.54714
+3.00139 3.66327
+5.34458 6.38895
+7.11481 7.96865
+4.66776 5.15678
+0.390138 0.53352
+2.01116 3.32839
+6.78761 6.97068
+4.57477 5.0724
+1.14098 1.36134
+7.4559 8.30327
+0.700932 2.40437
+1.90469 1.99046
+4.30064 5.11485
+7.84433 8.48543
+5.96212 7.49882
+3.93055 3.96317
+0.546327 1.04814
+8.96011 9.0404
+7.89255 8.06149
+0.669924 2.6944
+-0.00972314 0.837474
+6.07199 6.37467
+2.73659 3.19833
+5.9576 7.10966
+9.1316 9.14737
+5.26101 6.59184
+5.77697 8.08876
+0.68623 0.782805
+0.842619 1.39893
+5.82075 6.15957
+4.36394 4.88479
+7.1828 7.90107
+3.3331 4.39923
+6.54243 7.24966
+2.809 2.96491
+4.18514 4.61948
+4.95453 5.33929
+8.33288 9.52867
+9.05785 10.4276
+2.58917 4.74403
+1.34279 1.89014
+4.93626 5.75424
+7.75031 7.92788
+9.00904 9.02402
+3.91286 5.15124
+6.98486 7.34688
+-0.173169 0.415019
+0.652242 1.51556
+3.50184 5.30486
+3.72563 4.09022
+4.60463 6.58985
+3.34219 4.31833
+2.55445 2.58651
+6.14573 6.3669
+4.52336 6.37342
+9.37606 9.76836
+2.4198 3.36929
+2.89109 3.66974
+5.62463 6.05989
+0.674219 1.84165
+0.590017 1.71153
+1.54622 2.10277
+6.48003 6.55663
+3.56355 3.98573
+0.743671 1.87049
+3.27833 6.0722
+4.76267 6.9967
+2.80188 4.03037
+0.372694 0.482111
+5.73987 5.9529
+8.84732 9.49033
+0.833944 1.8157
+4.06126 4.36615
+0.884619 2.34622
+6.86723 6.99141
+8.07737 9.05193
+8.35903 9.00761
+8.84777 9.74001
+8.58058 9.05479
+8.28076 8.44566
+4.55155 5.65475
+2.44314 3.38966
+3.22172 4.50395
+7.1808 7.90376
+0.639636 1.72606
+5.46807 5.94322
+9.02146 9.87864
+-0.628472 0.655557
+4.29775 5.9553
+6.77525 7.38152
+6.51827 6.93542
+8.95252 9.52939
+0.755406 1.19973
+7.69455 7.86912
+0.170143 1.12949
+7.69254 8.08221
+2.08238 3.27051
+1.28662 1.78628
+1.21208 2.79391
+-0.155739 1.7071
+8.28833 9.10011
+5.77789 6.6954
+1.98395 2.35216
+5.77469 6.05177
+2.77565 5.81092
+-1.53416 2.30576
+6.93529 8.04506
+3.91553 4.55593
+5.57201 6.29071
+1.54149 1.86613
+4.09163 4.31234
+8.47834 11.1229
+5.70376 7.02981
+2.24683 3.79925
+5.4793 6.41036
+5.27644 6.81729
+0.13273 0.371437
+1.22959 1.41618
+0.551957 1.03276
+2.01269 2.4018
+8.77113 9.09395
+8.11753 8.46262
+0.39406 0.783705
+5.35964 5.48227
+7.24727 8.23233
+7.74525 8.85748
+0.0115736 0.882607
+1.78575 2.19684
+8.32514 9.0503
+3.11074 3.34975
+0.847464 2.13237
+0.310898 0.393528
+8.68841 10.518
+1.10032 1.83755
+2.42286 3.02554
+1.16364 2.80986
+1.46419 2.11421
+7.46021 7.90273
+6.86556 7.62542
+1.91466 3.79843
+3.1056 3.83969
+3.41591 4.26565
+0.285122 1.21372
+3.75441 5.52385
+1.07643 2.63403
+6.17341 7.67244
+9.13122 9.5132
+4.39696 6.15885
+3.7207 4.07729
+6.80782 7.1958
+6.65933 6.67105
+8.51535 8.7263
+5.98305 7.17759
+2.19609 2.46108
+8.21186 8.96908
+2.94729 3.60562
+3.31907 3.9297
+0.463492 0.626603
+2.62143 3.55089
+5.76898 6.79002
+1.45502 1.56525
+4.80797 5.62389
+5.87337 6.70588
+2.92765 3.50929
+0.412987 0.951057
+3.64594 4.40269
+-0.043401 0.502176
+4.54802 5.44613
+1.20218 1.8732
+2.75547 2.96745
+7.10348 7.7945
+9.74845 9.98835
+4.83718 6.4836
+2.30563 2.5903
+4.74016 6.30789
+6.42192 6.93329
+5.37294 6.73938
+2.4365 3.05787
+1.08283 3.79193
+4.90426 5.93563
+3.8874 4.83301
+0.13909 0.983027
+4.07407 5.61421
+8.62875 10.6851
+8.10233 8.29952
+2.23047 2.4691
+7.34617 7.39475
+1.66309 2.3032
+7.11207 10.0686
+4.52412 6.38666
+2.48323 2.96878
+7.47877 8.86547
+2.67607 4.33436
+6.83659 8.21075
+2.87313 3.39011
+2.81911 4.07729
+0.227877 0.657898
+6.57843 7.14311
+-0.591405 1.56925
+7.08018 7.59
+9.09558 9.3923
+9.48544 9.79474
+0.740233 2.33129
+8.51111 11.134
+7.79219 8.0281
+1.73821 1.89316
+9.21077 9.29488
+5.38354 6.46025
+4.30403 4.5472
+0.0893758 0.919238
+7.94464 8.51053
+5.27119 6.3741
+5.22476 6.00588
diff --git a/wasserstein/tests/data/test_5_A b/wasserstein/tests/data/test_5_A
new file mode 100644
index 0000000..51cff1c
--- /dev/null
+++ b/wasserstein/tests/data/test_5_A
@@ -0,0 +1,5 @@
+7.50638 7.78005
+0.991758 2.12178
+5.18481 6.61702
+6.14703 7.08581
+4.09936 4.83024
diff --git a/wasserstein/tests/data/test_5_A.pd.dipha b/wasserstein/tests/data/test_5_A.pd.dipha
new file mode 100644
index 0000000..be84441
--- /dev/null
+++ b/wasserstein/tests/data/test_5_A.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_5_B b/wasserstein/tests/data/test_5_B
new file mode 100644
index 0000000..be62ed3
--- /dev/null
+++ b/wasserstein/tests/data/test_5_B
@@ -0,0 +1,5 @@
+5.8232 6.36308
+2.16066 2.48668
+2.38754 4.91418
+4.77403 5.43982
+0.291412 1.11147
diff --git a/wasserstein/tests/data/test_5_B.pd.dipha b/wasserstein/tests/data/test_5_B.pd.dipha
new file mode 100644
index 0000000..14ca67c
--- /dev/null
+++ b/wasserstein/tests/data/test_5_B.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_diag1_A b/wasserstein/tests/data/test_diag1_A
new file mode 100644
index 0000000..f7f90ff
--- /dev/null
+++ b/wasserstein/tests/data/test_diag1_A
@@ -0,0 +1 @@
+1.0 1.0
diff --git a/wasserstein/tests/data/test_diag1_A.pd.dipha b/wasserstein/tests/data/test_diag1_A.pd.dipha
new file mode 100644
index 0000000..fa4a4d9
--- /dev/null
+++ b/wasserstein/tests/data/test_diag1_A.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_diag1_B b/wasserstein/tests/data/test_diag1_B
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/wasserstein/tests/data/test_diag1_B
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/wasserstein/tests/data/test_diag1_B.pd.dipha b/wasserstein/tests/data/test_diag1_B.pd.dipha
new file mode 100644
index 0000000..621a55f
--- /dev/null
+++ b/wasserstein/tests/data/test_diag1_B.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_diag2_A b/wasserstein/tests/data/test_diag2_A
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/wasserstein/tests/data/test_diag2_A
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/wasserstein/tests/data/test_diag2_A.pd.dipha b/wasserstein/tests/data/test_diag2_A.pd.dipha
new file mode 100644
index 0000000..621a55f
--- /dev/null
+++ b/wasserstein/tests/data/test_diag2_A.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_diag2_B b/wasserstein/tests/data/test_diag2_B
new file mode 100644
index 0000000..a167a4f
--- /dev/null
+++ b/wasserstein/tests/data/test_diag2_B
@@ -0,0 +1 @@
+5.0 5.0
diff --git a/wasserstein/tests/data/test_diag2_B.pd.dipha b/wasserstein/tests/data/test_diag2_B.pd.dipha
new file mode 100644
index 0000000..621a55f
--- /dev/null
+++ b/wasserstein/tests/data/test_diag2_B.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_diag3_A b/wasserstein/tests/data/test_diag3_A
new file mode 100644
index 0000000..151d4b1
--- /dev/null
+++ b/wasserstein/tests/data/test_diag3_A
@@ -0,0 +1,220 @@
+1.391781911475341 1.391781911475341
+1.395142124726278 1.395142124726278
+1.514181227875788 1.514181227875788
+1.528291566797427 1.528291566797427
+1.585389310674157 1.585389310674157
+1.629232116709072 1.629232116709072
+1.641428662445941 1.641428662445941
+1.646998748860116 1.646998748860116
+1.652915988616469 1.652915988616469
+1.69199679556404 1.69199679556404
+1.705727462482595 1.705727462482595
+1.706819293048617 1.706819293048617
+1.720175733750729 1.720175733750729
+1.728031840308488 1.728031840308488
+1.73797421040929 1.73797421040929
+1.739519744204842 1.739519744204842
+1.76132425248022 1.76132425248022
+1.767766952966369 1.767766952966369
+1.792444271021371 1.792444271021371
+1.831487552809192 1.831487552809192
+1.837086616049901 1.837086616049901
+1.851186504948943 1.851186504948943
+1.860502132730509 1.860502132730509
+1.8619433117852 1.8619433117852
+1.878229072834972 1.878229072834972
+1.880655074837347 1.880655074837347
+1.883647832802556 1.883647832802556
+1.884127769927503 1.884127769927503
+1.892969784466709 1.892969784466709
+1.916936460787894 1.916936460787894
+1.931545068229315 1.931545068229315
+1.937626522143119 1.937626522143119
+1.942267721488891 1.942267721488891
+1.963295334827521 1.963295334827521
+1.975655395743736 1.975655395743736
+1.981448090925679 1.981448090925679
+1.986220565173897 1.986220565173897
+1.98709020812351 1.98709020812351
+1.989420269013254 1.989420269013254
+2.007874648480185 2.007874648480185
+2.012179388983059 2.012179388983059
+2.019051972834053 2.019051972834053
+2.023278848058142 2.023278848058142
+2.026190677562545 2.026190677562545
+2.041594763633561 2.041594763633561
+2.042508934597344 2.042508934597344
+2.04305394648524 2.04305394648524
+2.052514683218775 2.052514683218775
+2.059038785694094 2.059038785694094
+2.062577320792516 2.062577320792516
+2.063488177732052 2.063488177732052
+2.067806664626417 2.067806664626417
+2.073013782498534 2.073013782498534
+2.08646120854976 2.08646120854976
+2.098476357223667 2.098476357223667
+2.101378199886176 2.101378199886176
+2.101927506425904 2.101927506425904
+2.12671744783454 2.12671744783454
+2.143966150630584 2.143966150630584
+2.145312642688415 2.145312642688415
+2.148704396208969 2.148704396208969
+2.153092682531471 2.153092682531471
+2.157553654759374 2.157553654759374
+2.176659075756566 2.176659075756566
+2.177260578806816 2.177260578806816
+2.179141269427014 2.179141269427014
+2.201895416482074 2.201895416482074
+2.202563945779844 2.202563945779844
+2.205113735193028 2.205113735193028
+2.207345865351049 2.207345865351049
+2.208922099676958 2.208922099676958
+2.218057898922937 2.218057898922937
+2.228610453267036 2.228610453267036
+2.241314066596301 2.241314066596301
+2.242145210071643 2.242145210071643
+2.253976266568437 2.253976266568437
+2.255324860119305 2.255324860119305
+2.271300972641221 2.271300972641221
+2.279438361991067 2.279438361991067
+2.286592331830957 2.286592331830957
+2.287159411646074 2.287159411646074
+2.296653147995115 2.296653147995115
+2.301754785182811 2.301754785182811
+2.30409930499031 2.30409930499031
+2.32141477565108 2.32141477565108
+2.347789281926012 2.347789281926012
+2.347827987256373 2.347827987256373
+2.349391321950732 2.349391321950732
+2.350129292983257 2.350129292983257
+2.358679083392328 2.358679083392328
+2.372845273125388 2.372845273125388
+2.385040766846267 2.385040766846267
+2.42114588843816 2.42114588843816
+2.425116524931602 2.425116524931602
+2.426518521893022 2.426518521893022
+2.43211651886311 2.43211651886311
+2.441302771998711 2.441302771998711
+2.446429340510857 2.446429340510857
+2.446547553904861 2.446547553904861
+2.45764765793376 2.45764765793376
+2.461222149682938 2.461222149682938
+2.467900747394114 2.467900747394114
+2.473214152160872 2.473214152160872
+2.5 2.5
+2.503557913626332 2.503557913626332
+2.504315621146863 2.504315621146863
+2.515634290122204 2.515634290122204
+2.516231935083851 2.516231935083851
+2.517558892374071 2.517558892374071
+2.526325773757754 2.526325773757754
+2.531164001388939 2.531164001388939
+2.53128061055404 2.53128061055404
+2.539387277827314 2.539387277827314
+2.540864599180268 2.540864599180268
+2.548084457784768 2.548084457784768
+2.548923292215475 2.548923292215475
+2.551730202825644 2.551730202825644
+2.553178578801818 2.553178578801818
+2.560295747947446 2.560295747947446
+2.566321603108612 2.566321603108612
+2.568932286976676 2.568932286976676
+2.574887688783916 2.574887688783916
+2.581809142325336 2.581809142325336
+2.584541960262555 2.584541960262555
+2.585511915815223 2.585511915815223
+2.592970592044868 2.592970592044868
+2.596055336381078 2.596055336381078
+2.598560573626668 2.598560573626668
+2.614019084614256 2.614019084614256
+2.618463725327216 2.618463725327216
+2.622883674481145 2.622883674481145
+2.627791161528314 2.627791161528314
+2.63535653879261 2.63535653879261
+2.654825898255443 2.654825898255443
+2.660423271276714 2.660423271276714
+2.667148030102869 2.667148030102869
+2.67012591760915 2.67012591760915
+2.698712599567882 2.698712599567882
+2.72180967799905 2.72180967799905
+2.732466204434637 2.732466204434637
+2.734187392905275 2.734187392905275
+2.737296308103857 2.737296308103857
+2.745724923243991 2.745724923243991
+2.749541709159369 2.749541709159369
+2.752925621447035 2.752925621447035
+2.754183973113479 2.754183973113479
+2.763972022430258 2.763972022430258
+2.766941997926879 2.766941997926879
+2.773850925522978 2.773850925522978
+2.777506755238121 2.777506755238121
+2.780333194223143 2.780333194223143
+2.783060349483276 2.783060349483276
+2.78679029681548 2.78679029681548
+2.786792895521339 2.786792895521339
+2.795170825459034 2.795170825459034
+2.801104989227437 2.801104989227437
+2.80525433080833 2.80525433080833
+2.805376738133109 2.805376738133109
+2.806844454092663 2.806844454092663
+2.811611818684648 2.811611818684648
+2.811994908451803 2.811994908451803
+2.816002798930236 2.816002798930236
+2.816814002472584 2.816814002472584
+2.818569391261086 2.818569391261086
+2.821660827076439 2.821660827076439
+2.822317588351085 2.822317588351085
+2.824910409962511 2.824910409962511
+2.829322097471409 2.829322097471409
+2.833852169620359 2.833852169620359
+2.839287537694811 2.839287537694811
+2.841714730677953 2.841714730677953
+2.841715058318205 2.841715058318205
+2.851653306950001 2.851653306950001
+2.853639002902003 2.853639002902003
+2.85515962291442 2.85515962291442
+2.855333736885793 2.855333736885793
+2.872540314564304 2.872540314564304
+2.879449214478037 2.879449214478037
+2.881003856158217 2.881003856158217
+2.881074731438092 2.881074731438092
+2.893589165559115 2.893589165559115
+2.898664743213686 2.898664743213686
+2.90387832180792 2.90387832180792
+2.919095859678745 2.919095859678745
+2.924945175440496 2.924945175440496
+2.931795145696962 2.931795145696962
+2.932285006979528 2.932285006979528
+2.934606807227626 2.934606807227626
+2.936392671567475 2.936392671567475
+2.953794710898493 2.953794710898493
+2.958055395706548 2.958055395706548
+2.960407744013656 2.960407744013656
+2.960759715914242 2.960759715914242
+2.969702548922556 2.969702548922556
+2.970149844982665 2.970149844982665
+2.978953970679893 2.978953970679893
+2.979075864664287 2.979075864664287
+2.984665519558418 2.984665519558418
+3.04548240149063 3.04548240149063
+3.050688336416719 3.050688336416719
+3.05773927378742 3.05773927378742
+3.059596740753369 3.059596740753369
+3.059762479996741 3.059762479996741
+3.088543279751235 3.088543279751235
+3.093580813520995 3.093580813520995
+3.104787362108069 3.104787362108069
+3.173380191779681 3.173380191779681
+3.583124637167399 3.583124637167399
+3.630658112409034 3.630658112409034
+3.631421639368965 3.631421639368965
+3.751087101339956 3.751087101339956
+3.800845709568037 3.800845709568037
+3.846558940956666 3.846558940956666
+4 4
+4 4
+4.076238038291317 4.076238038291317
+4.455547086147983 4.455547086147983
+5.356087357608394 5.356087357608394
+5.54364842773721 5.54364842773721
+7.587654388717225 7.587654388717225
diff --git a/wasserstein/tests/data/test_diag3_A.pd.dipha b/wasserstein/tests/data/test_diag3_A.pd.dipha
new file mode 100644
index 0000000..0dbfb89
--- /dev/null
+++ b/wasserstein/tests/data/test_diag3_A.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_diag3_B b/wasserstein/tests/data/test_diag3_B
new file mode 100644
index 0000000..bb8655a
--- /dev/null
+++ b/wasserstein/tests/data/test_diag3_B
@@ -0,0 +1,193 @@
+1.167089173446239 1.167089173446239
+1.256234452640111 1.256234452640111
+1.303693422257498 1.303693422257498
+1.413255970488646 1.413255970488646
+1.697910382446573 1.697910382446573
+1.718844728805093 1.718844728805093
+1.734124820632724 1.734124820632724
+1.749572938304276 1.749572938304276
+1.770320424526358 1.770320424526358
+1.786344763036807 1.786344763036807
+1.810054737907635 1.810054737907635
+1.815127306170105 1.815127306170105
+1.837806648681218 1.837806648681218
+1.870552189043019 1.870552189043019
+1.897240351979503 1.897240351979503
+1.935562152643027 1.935562152643027
+1.952562418976663 1.952562418976663
+1.959552126104175 1.959552126104175
+1.979899732318601 1.979899732318601
+2.00044500769347 2.00044500769347
+2.028951227523087 2.028951227523087
+2.037678749316724 2.037678749316724
+2.047911420446857 2.047911420446857
+2.075181804515723 2.075181804515723
+2.077245386452578 2.077245386452578
+2.084751316684838 2.084751316684838
+2.084860886126203 2.084860886126203
+2.103286477421968 2.103286477421968
+2.106856827309345 2.106856827309345
+2.113139266068691 2.113139266068691
+2.114594962503455 2.114594962503455
+2.115917727493158 2.115917727493158
+2.122335878797089 2.122335878797089
+2.127359082726206 2.127359082726206
+2.131673381033273 2.131673381033273
+2.155015793320908 2.155015793320908
+2.162480684365264 2.162480684365264
+2.195207236194009 2.195207236194009
+2.203279931784429 2.203279931784429
+2.205567995563669 2.205567995563669
+2.212933962936773 2.212933962936773
+2.215081271089993 2.215081271089993
+2.225989037578865 2.225989037578865
+2.24218929203347 2.24218929203347
+2.246321319993257 2.246321319993257
+2.280059407166517 2.280059407166517
+2.284117669032543 2.284117669032543
+2.293233992770926 2.293233992770926
+2.298815356955373 2.298815356955373
+2.300542634724628 2.300542634724628
+2.326408290042679 2.326408290042679
+2.328797162040625 2.328797162040625
+2.36025798094028 2.36025798094028
+2.365031313604634 2.365031313604634
+2.372266311053883 2.372266311053883
+2.400053902049271 2.400053902049271
+2.409134054334209 2.409134054334209
+2.411368235895246 2.411368235895246
+2.415934766378347 2.415934766378347
+2.420989857074179 2.420989857074179
+2.422520269961376 2.422520269961376
+2.43377629944218 2.43377629944218
+2.449308615746858 2.449308615746858
+2.452936540056068 2.452936540056068
+2.453698388060092 2.453698388060092
+2.454711357943602 2.454711357943602
+2.459202673400056 2.459202673400056
+2.493778305287384 2.493778305287384
+2.537394117473177 2.537394117473177
+2.544674753106669 2.544674753106669
+2.558904304820755 2.558904304820755
+2.563089994365716 2.563089994365716
+2.565476194422898 2.565476194422898
+2.599756049189921 2.599756049189921
+2.603619661709009 2.603619661709009
+2.609775379385211 2.609775379385211
+2.622552038976658 2.622552038976658
+2.623798471910885 2.623798471910885
+2.635711198661633 2.635711198661633
+2.644229304223612 2.644229304223612
+2.661919064427223 2.661919064427223
+2.666783921498494 2.666783921498494
+2.675503310152301 2.675503310152301
+2.684228699964661 2.684228699964661
+2.696854617267681 2.696854617267681
+2.700538654666735 2.700538654666735
+2.744886611436907 2.744886611436907
+2.748618547996708 2.748618547996708
+2.757981496641135 2.757981496641135
+2.774766825791652 2.774766825791652
+2.784491736143893 2.784491736143893
+2.796482184304273 2.796482184304273
+2.800849254751463 2.800849254751463
+2.816963410000067 2.816963410000067
+2.825207379914743 2.825207379914743
+2.831286409028398 2.831286409028398
+2.844827082550712 2.844827082550712
+2.853558438121966 2.853558438121966
+2.859806035663089 2.859806035663089
+2.878956033959891 2.878956033959891
+2.886422825109222 2.886422825109222
+2.891566924618832 2.891566924618832
+2.892028419188578 2.892028419188578
+2.893138900330932 2.893138900330932
+2.894250936382814 2.894250936382814
+2.90112201577666 2.90112201577666
+2.902172795370005 2.902172795370005
+2.90967533504119 2.90967533504119
+2.919687125962211 2.919687125962211
+2.923711238894001 2.923711238894001
+2.929041907338841 2.929041907338841
+2.938734873084349 2.938734873084349
+2.939642428979572 2.939642428979572
+2.943010909640486 2.943010909640486
+2.944210926048103 2.944210926048103
+2.951091358234723 2.951091358234723
+2.953950275008233 2.953950275008233
+2.966943157369611 2.966943157369611
+2.982522008227535 2.982522008227535
+2.992174049247434 2.992174049247434
+2.993098995839607 2.993098995839607
+2.995311055519335 2.995311055519335
+2.996708164866609 2.996708164866609
+2.999922110096644 2.999922110096644
+3 3
+3.000364533251431 3.000364533251431
+3.003840990677832 3.003840990677832
+3.006672301312824 3.006672301312824
+3.016489409140306 3.016489409140306
+3.021123787004333 3.021123787004333
+3.039117818612596 3.039117818612596
+3.039555193616473 3.039555193616473
+3.049952247267922 3.049952247267922
+3.057673482371216 3.057673482371216
+3.06920083507411 3.06920083507411
+3.075505231082782 3.075505231082782
+3.079038628197304 3.079038628197304
+3.084265889701239 3.084265889701239
+3.086837468106297 3.086837468106297
+3.103873984398081 3.103873984398081
+3.11528125482979 3.11528125482979
+3.119720021802376 3.119720021802376
+3.132543753577128 3.132543753577128
+3.141822873359038 3.141822873359038
+3.143502053175705 3.143502053175705
+3.153232877003746 3.153232877003746
+3.157586960809866 3.157586960809866
+3.157966892275408 3.157966892275408
+3.163583225161638 3.163583225161638
+3.178188125342772 3.178188125342772
+3.178475867931057 3.178475867931057
+3.179372297765929 3.179372297765929
+3.186437137237586 3.186437137237586
+3.188053957464282 3.188053957464282
+3.199351610026191 3.199351610026191
+3.204566427513051 3.204566427513051
+3.22885278850648 3.22885278850648
+3.229088648916556 3.229088648916556
+3.236685523936269 3.236685523936269
+3.239854786600373 3.239854786600373
+3.255809161351669 3.255809161351669
+3.287718056143732 3.287718056143732
+3.294038308299402 3.294038308299402
+3.313688277153076 3.313688277153076
+3.325783245946608 3.325783245946608
+3.331072954808429 3.331072954808429
+3.354962852285211 3.354962852285211
+3.357502741262644 3.357502741262644
+3.373668509804576 3.373668509804576
+3.408653045775418 3.408653045775418
+3.416281541503763 3.416281541503763
+3.443144279972986 3.443144279972986
+3.492970564191033 3.492970564191033
+3.493767805580122 3.493767805580122
+3.559084134799019 3.559084134799019
+3.559898699300211 3.559898699300211
+3.833585501974904 3.833585501974904
+4.099502076836052 4.099502076836052
+4.484082147277348 4.484082147277348
+4.505718324707756 4.505718324707756
+4.891723119528026 4.891723119528026
+5.065300494905414 5.065300494905414
+5.188599238535201 5.188599238535201
+5.36134479630535 5.36134479630535
+5.609786508140671 5.609786508140671
+7.08640314680382 7.08640314680382
+7.113765883549079 7.113765883549079
+7.328944131981744 7.328944131981744
+7.63625182217108 7.63625182217108
+7.716743341311718 7.716743341311718
+7.938093404092351 7.938093404092351
+8.112783377863046 8.112783377863046
+8.131485096731454 8.131485096731454
diff --git a/wasserstein/tests/data/test_diag3_B.pd.dipha b/wasserstein/tests/data/test_diag3_B.pd.dipha
new file mode 100644
index 0000000..3fbfd90
--- /dev/null
+++ b/wasserstein/tests/data/test_diag3_B.pd.dipha
Binary files differ
diff --git a/wasserstein/tests/data/test_list.txt b/wasserstein/tests/data/test_list.txt
new file mode 100644
index 0000000..27340d8
--- /dev/null
+++ b/wasserstein/tests/data/test_list.txt
@@ -0,0 +1,21 @@
+test_5_A test_5_B 1.0 -1.0 4.320655
+test_5_A test_5_B 2.0 -1.0 1.7323016335246
+test_5_A test_5_B 3.0 -1.0 1.396199948
+test_5_A test_5_B 1.0 1.0 6.603006
+test_5_A test_5_B 2.0 1.0 2.73426775794691
+test_5_A test_5_B 3.0 1.0 2.13072755216204
+test_5_A test_5_B 1.0 2.0 5.1888795679967
+test_5_A test_5_B 2.0 2.0 2.26649677575857
+test_5_A test_5_B 3.0 2.0 1.86434961396614
+test_100_A test_100_B 1.0 -1.0 27.5573259
+test_100_A test_100_B 2.0 -1.0 3.38004972483238
+test_100_A test_100_B 3.0 -1.0 1.9045814702967
+test_100_A test_100_B 1.0 1.0 40.4375855
+test_100_A test_100_B 2.0 1.0 4.75252460986668
+test_100_A test_100_B 3.0 1.0 2.556594741819
+test_100_A test_100_B 1.0 2.0 31.7187555735287
+test_100_A test_100_B 2.0 2.0 3.81132239777023
+test_100_A test_100_B 3.0 2.0 2.09695346034248
+test_diag1_A test_diag1_B 1.0 -1.0 0.0
+test_diag2_A test_diag2_B 1.0 -1.0 0.0
+test_diag3_A test_diag3_B 1.0 -1.0 0.0
diff --git a/wasserstein/tests/test_hera_wasserstein.cpp b/wasserstein/tests/test_hera_wasserstein.cpp
new file mode 100644
index 0000000..0a80d2f
--- /dev/null
+++ b/wasserstein/tests/test_hera_wasserstein.cpp
@@ -0,0 +1,532 @@
+#define LOG_AUCTION
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+
+
+#undef LOG_AUCTION
+
+#include "wasserstein.h"
+#include "tests_reader.h"
+
+using namespace hera_test;
+
+using PairVector = std::vector<std::pair<double, double>>;
+
+
+TEST_CASE("simple cases", "wasserstein_dist")
+{
+ PairVector diagram_A, diagram_B;
+ hera::AuctionParams<double> params;
+ params.wasserstein_power = 1.0;
+ params.delta = 0.01;
+ params.internal_p = hera::get_infinity<double>();
+ params.initial_epsilon = 0.0;
+ params.epsilon_common_ratio = 0.0;
+ params.max_num_phases = 30;
+ params.gamma_threshold = 0.0;
+ params.max_bids_per_round = 0; // use Jacobi
+
+ SECTION("trivial: two empty diagrams") {
+ REQUIRE( 0.0 == hera::wasserstein_dist<>(diagram_A, diagram_B, params));
+ }
+
+ SECTION("trivial: one empty diagram, one single-point diagram") {
+
+ diagram_A.emplace_back(1.0, 2.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ REQUIRE( fabs(d1 - 0.5) <= 0.00000000001 );
+
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d2 - 0.5) <= 0.00000000001 );
+
+ params.internal_p = 2.0;
+ double corr_answer = 1.0 / std::sqrt(2.0);
+ double d3 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d3 - corr_answer) <= 0.00000000001 );
+
+ }
+
+ SECTION("trivial: two single-point diagrams-1") {
+
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(13.0, 19.0); // (3, 3)
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d1 - d2) <= 0.00000000001 );
+ REQUIRE( fabs(d1 - 3.0) <= 0.00000000001 );
+
+ params.wasserstein_power = 2.0;
+ double d3 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d4 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d3 - d4) <= 0.00000000001 );
+ REQUIRE( fabs(d4 - 9.0) <= 0.00000000001 );
+
+ params.wasserstein_power = 1.0;
+ params.internal_p = 1.0;
+ double d5 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d6 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d5 - d6) <= 0.00000000001 );
+ REQUIRE( fabs(d5 - 4.0) <= 0.00000000001 );
+
+ params.internal_p = 2.0;
+ double d7 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d8 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d7 - d8) <= 0.00000000001 );
+ REQUIRE( fabs(d7 - std::sqrt(10.0)) <= 0.00000000001 );
+
+ }
+
+ SECTION("trivial: two single-point diagrams-2") {
+
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(130.0, 138.0); // (4, 4)
+
+ double d1 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d1 - d2) <= 0.00000000001 );
+ REQUIRE( fabs(d1 - 9.0) <= 0.00000000001 );
+
+ params.wasserstein_power = 2.0;
+ double d3 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d4 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d3 - d4) <= 0.00000000001 );
+ REQUIRE( fabs(d4 - 41.0) <= 0.00000000001 ); // 5^2 + 4^2
+
+ params.wasserstein_power = 1.0;
+ params.internal_p = 1.0;
+ double d5 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d6 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d5 - d6) <= 0.00000000001 );
+ REQUIRE( fabs(d5 - 18.0) <= 0.00000000001 ); // 5 + 5 + 4 + 4
+
+ params.internal_p = 2.0;
+ double d7 = hera::wasserstein_cost<>(diagram_A, diagram_B, params);
+ double d8 = hera::wasserstein_cost<>(diagram_B, diagram_A, params);
+ REQUIRE( fabs(d7 - d8) <= 0.00000000001 );
+ REQUIRE( fabs(d7 - 9 * std::sqrt(2.0)) <= 0.00000000001 ); // sqrt(5^2 + 5^2) + sqrt(4^2 + 4^2) = 9 sqrt(2)
+
+ }
+
+}
+
+
+
+TEST_CASE("file cases", "wasserstein_dist")
+{
+ PairVector diagram_A, diagram_B;
+ hera::AuctionParams<double> params;
+ params.wasserstein_power = 1.0;
+ params.delta = 0.01;
+ params.internal_p = hera::get_infinity<double>();
+ params.initial_epsilon = 0.0;
+ params.epsilon_common_ratio = 0.0;
+ params.max_num_phases = 30;
+ params.gamma_threshold = 0.0;
+ params.max_bids_per_round = 1; // use Jacobi
+
+
+ SECTION("from file:") {
+ const char* file_name = "../tests/data/test_list.txt";
+ std::ifstream f;
+ f.open(file_name);
+ std::vector<TestFromFileCase> test_params;
+ std::string s;
+ while (std::getline(f, s)) {
+ test_params.emplace_back(s);
+ }
+
+ for(const auto& ts : test_params) {
+ params.wasserstein_power = ts.q;
+ params.internal_p = ts.internal_p;
+ bool read_file_A = hera::read_diagram_point_set<double, PairVector>(ts.file_1, diagram_A);
+ bool read_file_B = hera::read_diagram_point_set<double, PairVector>(ts.file_2, diagram_B);
+ REQUIRE( read_file_A );
+ REQUIRE( read_file_B );
+ double hera_answer = hera::wasserstein_dist(diagram_A, diagram_B, params);
+ REQUIRE( fabs(hera_answer - ts.answer) <= 0.01 * hera_answer );
+ std::cout << ts << " PASSED " << std::endl;
+ }
+ }
+
+ SECTION("from DIPHA file:") {
+ const char* file_name = "../tests/data/test_list.txt";
+ std::ifstream f;
+ f.open(file_name);
+ std::vector<TestFromFileCase> test_params;
+ std::string s;
+ while (std::getline(f, s)) {
+ test_params.emplace_back(s);
+ }
+
+ for(const auto& ts : test_params) {
+ params.wasserstein_power = ts.q;
+ params.internal_p = ts.internal_p;
+ bool read_file_A = hera::read_diagram_dipha<double, PairVector>(ts.file_1 + std::string(".pd.dipha"), 1, diagram_A);
+ bool read_file_B = hera::read_diagram_dipha<double, PairVector>(ts.file_2 + std::string(".pd.dipha"), 1, diagram_B);
+ REQUIRE( read_file_A );
+ REQUIRE( read_file_B );
+ double hera_answer = hera::wasserstein_dist(diagram_A, diagram_B, params);
+ REQUIRE( fabs(hera_answer - ts.answer) <= 0.01 * hera_answer );
+ std::cout << ts << " PASSED " << std::endl;
+ }
+ }
+}
+
+
+
+TEST_CASE("infinity points", "wasserstein_dist")
+{
+ PairVector diagram_A, diagram_B;
+ hera::AuctionParams<double> params;
+ params.wasserstein_power = 1.0;
+ params.delta = 0.01;
+ params.internal_p = hera::get_infinity<double>();
+ params.initial_epsilon = 0.0;
+ params.epsilon_common_ratio = 0.0;
+ params.max_num_phases = 30;
+ params.gamma_threshold = 0.0;
+ params.max_bids_per_round = 0; // use Jacobi
+
+ // do not use Hera's infinity! it is -1
+ double inf = std::numeric_limits<double>::infinity();
+
+ SECTION("two points at infinity, no finite points") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double corr_answer = 1.0;
+ REQUIRE( fabs(d - corr_answer) <= 0.00000000001 );
+ }
+
+ SECTION("two points at infinity") {
+
+ // edge cost 3.0
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(13.0, 19.0); // (3, 3)
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double corr_answer = 1.0 + 3.0;
+ REQUIRE( fabs(d - corr_answer) <= 0.00000000001 );
+ }
+
+ SECTION("three points at infinity, no finite points") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double corr_answer = inf;
+ REQUIRE( d == corr_answer );
+ }
+
+ SECTION("three points at infinity") {
+
+ // edge cost 3.0
+ diagram_A.emplace_back(10.0, 20.0); // (5, 5)
+ diagram_B.emplace_back(13.0, 19.0); // (3, 3)
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ double d = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double corr_answer = inf;
+ REQUIRE( d == corr_answer );
+ }
+
+
+ SECTION("all four corners at infinity, no finite points, finite answer") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double corr_answer = 4.0;
+
+ REQUIRE( d == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-1") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-2") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-3") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-4") {
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ // edge cost 1.0
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, with finite points, infinite answer-1") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, with finite points, infinite answer-2") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, with finite points, infinite answer-3") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+ SECTION("all four corners at infinity, no finite points, infinite answer-4") {
+
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.0, -inf);
+ diagram_B.emplace_back(2.0, -inf);
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(-inf, 1.0);
+ diagram_B.emplace_back(-inf, 2.0);
+ diagram_B.emplace_back(-inf, 2.0);
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = inf;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+ }
+
+
+ SECTION("simple small example with finite answer") {
+ diagram_A.emplace_back(1.0, inf);
+ diagram_B.emplace_back(2.0, inf);
+
+ diagram_A.emplace_back(1.9, inf);
+ diagram_B.emplace_back(1.1, inf);
+
+ // 1.1 - 1.0 + 2.0 - 1.9 = 0.2
+
+ diagram_A.emplace_back(inf, 1.0);
+ diagram_B.emplace_back(inf, 2.0);
+
+ diagram_A.emplace_back(inf, 1.9);
+ diagram_B.emplace_back(inf, 1.1);
+
+
+ // finite edge
+ diagram_A.emplace_back(10.0, 20.0);
+ diagram_B.emplace_back(13.0, 19.0);
+
+ double d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ double d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ double corr_answer = 3.0 + 0.2 + 0.2;
+
+ REQUIRE( d1 == corr_answer );
+ REQUIRE( d2 == corr_answer );
+
+ params.wasserstein_power = 2.0;
+
+ d1 = hera::wasserstein_dist<>(diagram_A, diagram_B, params);
+ d2 = hera::wasserstein_dist<>(diagram_B, diagram_A, params);
+ corr_answer = std::sqrt(3.0 * 3.0 + 4 * 0.1 * 0.1);
+
+ REQUIRE( fabs(d1 - corr_answer) < 0.000000000001 );
+ REQUIRE( fabs(d2 - corr_answer) < 0.000000000001 );
+
+ }
+
+}
+
diff --git a/wasserstein/tests/test_hera_wasserstein_pure_geom.cpp b/wasserstein/tests/test_hera_wasserstein_pure_geom.cpp
new file mode 100644
index 0000000..9603ceb
--- /dev/null
+++ b/wasserstein/tests/test_hera_wasserstein_pure_geom.cpp
@@ -0,0 +1,111 @@
+#include "catch/catch.hpp"
+
+#include <sstream>
+#include <iostream>
+
+
+#undef LOG_AUCTION
+
+#include "wasserstein_pure_geom.hpp"
+#include "tests_reader.h"
+
+using namespace hera_test;
+
+TEST_CASE("simple point clouds", "wasserstein_dist_pure_geom")
+{
+// int n_points = 3;
+// int dim = 3;
+// using Traits = hera::ws::dnn::DynamicPointTraits<double>;
+// hera::ws::dnn::DynamicPointTraits<double> traits(dim);
+// hera::ws::dnn::DynamicPointVector<double> dgm_a = traits.container(n_points);
+// hera::ws::dnn::DynamicPointVector<double> dgm_b = traits.container(n_points);
+//
+// dgm_a[0][0] = 0.0;
+// dgm_a[0][1] = 0.0;
+// dgm_a[0][2] = 0.0;
+//
+// dgm_a[1][0] = 1.0;
+// dgm_a[1][1] = 0.0;
+// dgm_a[1][2] = 0.0;
+//
+// dgm_a[2][0] = 0.0;
+// dgm_a[2][1] = 1.0;
+// dgm_a[2][2] = 1.0;
+//
+// dgm_b[0][0] = 0.0;
+// dgm_b[0][1] = 0.1;
+// dgm_b[0][2] = 0.1;
+//
+// dgm_b[1][0] = 1.1;
+// dgm_b[1][1] = 0.0;
+// dgm_b[1][2] = 0.0;
+//
+// dgm_b[2][0] = 0.0;
+// dgm_b[2][1] = 1.1;
+// dgm_b[2][2] = 0.9;
+
+ const int dim = 3;
+ using Traits = hera::ws::dnn::DynamicPointTraits<double>;
+ hera::ws::dnn::DynamicPointTraits<double> traits(dim);
+ hera::AuctionParams<double> params;
+ params.dim = dim;
+ params.wasserstein_power = 1.0;
+ params.delta = 0.01;
+ params.internal_p = hera::get_infinity<double>();
+ params.initial_epsilon = 0.0;
+ params.epsilon_common_ratio = 0.0;
+ params.max_num_phases = 30;
+ params.gamma_threshold = 0.0;
+ params.max_bids_per_round = 0; // use Jacobi
+
+
+ SECTION("trivial: two single-point diagrams-1") {
+
+ int n_points = 1;
+ hera::ws::dnn::DynamicPointVector<double> dgm_a = traits.container(n_points);
+ hera::ws::dnn::DynamicPointVector<double> dgm_b = traits.container(n_points);
+
+ dgm_a[0][0] = 0.0;
+ dgm_a[0][1] = 0.0;
+ dgm_a[0][2] = 0.0;
+
+ dgm_b[0][0] = 1.0;
+ dgm_b[0][1] = 1.0;
+ dgm_b[0][2] = 1.0;
+
+ std::vector<size_t> max_bids { 1, 10, 0 };
+ std::vector<int> internal_ps{ 1, 2, static_cast<int>(hera::get_infinity()) };
+ std::vector<double> wasserstein_powers { 1, 2, 3 };
+
+ for(auto internal_p : internal_ps) {
+ // there is only one point, so the answer does not depend wasserstein power
+ double correct_answer;
+ switch (internal_p) {
+ case 1 :
+ correct_answer = 3.0;
+ break;
+ case 2 :
+ correct_answer = sqrt(3.0);
+ break;
+ case static_cast<int>(hera::get_infinity()) :
+ correct_answer = 1.0;
+ break;
+ default :
+ throw std::runtime_error("Correct answer not specified in test case");
+ }
+
+ for (auto max_bid : max_bids) {
+ for (auto wasserstein_power : wasserstein_powers) {
+ params.max_bids_per_round = max_bid;
+ params.internal_p = internal_p;
+ params.wasserstein_power = wasserstein_power;
+ double d1 = hera::ws::wasserstein_dist(dgm_a, dgm_b, params);
+ double d2 = hera::ws::wasserstein_dist(dgm_b, dgm_a, params);
+ REQUIRE(fabs(d1 - d2) <= 0.00000000001);
+ REQUIRE(fabs(d1 - correct_answer) <= 0.00000000001);
+ }
+ }
+ }
+ }
+}
+
diff --git a/wasserstein/tests/tests_main.cpp b/wasserstein/tests/tests_main.cpp
new file mode 100644
index 0000000..d24407e
--- /dev/null
+++ b/wasserstein/tests/tests_main.cpp
@@ -0,0 +1,3 @@
+#define LOG_AUCTION
+#define CATCH_CONFIG_MAIN
+#include "catch/catch.hpp"
diff --git a/wasserstein/tests/tests_reader.h b/wasserstein/tests/tests_reader.h
new file mode 100644
index 0000000..f2d5735
--- /dev/null
+++ b/wasserstein/tests/tests_reader.h
@@ -0,0 +1,67 @@
+#ifndef WASSERSTEIN_TESTS_READER_H
+#define WASSERSTEIN_TESTS_READER_H
+
+#include <vector>
+#include <string>
+#include <ostream>
+#include <iostream>
+#include <sstream>
+#include <cassert>
+#include <cmath>
+
+#include "hera_infinity.h"
+
+namespace hera_test {
+ inline std::vector<std::string> split_on_delim(const std::string& s, char delim)
+ {
+ std::stringstream ss(s);
+ std::string token;
+ std::vector<std::string> tokens;
+ while (std::getline(ss, token, delim)) {
+ tokens.push_back(token);
+ }
+ return tokens;
+ }
+
+
+ // single row in a file with test cases
+ struct TestFromFileCase
+ {
+
+ std::string file_1;
+ std::string file_2;
+ double q;
+ double internal_p;
+ double answer;
+
+ TestFromFileCase(std::string s)
+ {
+ auto tokens = split_on_delim(s, ' ');
+ assert(tokens.size() == 5);
+
+ file_1 = tokens.at(0);
+ file_2 = tokens.at(1);
+ q = std::stod(tokens.at(2));
+ internal_p = std::stod(tokens.at(3));
+ answer = std::stod(tokens.at(4));
+
+ if (q < 1.0 or std::isinf(q) or
+ (internal_p != hera::get_infinity<double>() and internal_p < 1.0)) {
+ throw std::runtime_error("Bad line in test_list.txt");
+ }
+ }
+ };
+
+ inline std::ostream& operator<<(std::ostream& out, const TestFromFileCase& s)
+ {
+ out << "[" << s.file_1 << ", " << s.file_2 << ", q = " << s.q << ", norm = ";
+ if (s.internal_p != hera::get_infinity()) {
+ out << s.internal_p;
+ } else {
+ out << "infinity";
+ }
+ out << ", answer = " << s.answer << "]";
+ return out;
+ }
+} // namespace hera_test
+#endif //WASSERSTEIN_TESTS_READER_H