• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* auto-generated on 2024-01-29 13:13:24 -0500. Do not edit! */
2 /* begin file src/ada.cpp */
3 #include "ada.h"
4 /* begin file src/checkers.cpp */
5 #include <algorithm>
6 
7 namespace ada::checkers {
8 
is_ipv4(std::string_view view)9 ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept {
10   // The string is not empty and does not contain upper case ASCII characters.
11   //
12   // Optimization. To be considered as a possible ipv4, the string must end
13   // with 'x' or a lowercase hex character.
14   // Most of the time, this will be false so this simple check will save a lot
15   // of effort.
16   char last_char = view.back();
17   // If the address ends with a dot, we need to prune it (special case).
18   if (last_char == '.') {
19     view.remove_suffix(1);
20     if (view.empty()) {
21       return false;
22     }
23     last_char = view.back();
24   }
25   bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
26                        (last_char >= 'a' && last_char <= 'f') ||
27                        last_char == 'x';
28   if (!possible_ipv4) {
29     return false;
30   }
31   // From the last character, find the last dot.
32   size_t last_dot = view.rfind('.');
33   if (last_dot != std::string_view::npos) {
34     // We have at least one dot.
35     view = view.substr(last_dot + 1);
36   }
37   /** Optimization opportunity: we have basically identified the last number of
38      the ipv4 if we return true here. We might as well parse it and have at
39      least one number parsed when we get to parse_ipv4. */
40   if (std::all_of(view.begin(), view.end(), ada::checkers::is_digit)) {
41     return true;
42   }
43   // It could be hex (0x), but not if there is a single character.
44   if (view.size() == 1) {
45     return false;
46   }
47   // It must start with 0x.
48   if (!std::equal(view.begin(), view.begin() + 2, "0x")) {
49     return false;
50   }
51   // We must allow "0x".
52   if (view.size() == 2) {
53     return true;
54   }
55   // We have 0x followed by some characters, we need to check that they are
56   // hexadecimals.
57   return std::all_of(view.begin() + 2, view.end(),
58                      ada::unicode::is_lowercase_hex);
59 }
60 
61 // for use with path_signature, we include all characters that need percent
62 // encoding.
63 static constexpr std::array<uint8_t, 256> path_signature_table =
__anon4ddc785e0102() 64     []() constexpr {
65       std::array<uint8_t, 256> result{};
66       for (size_t i = 0; i < 256; i++) {
67         if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
68             i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7b || i == 0x7d ||
69             i > 0x7e) {
70           result[i] = 1;
71         } else if (i == 0x25) {
72           result[i] = 8;
73         } else if (i == 0x2e) {
74           result[i] = 4;
75         } else if (i == 0x5c) {
76           result[i] = 2;
77         } else {
78           result[i] = 0;
79         }
80       }
81       return result;
82     }();
83 
path_signature(std::string_view input)84 ada_really_inline constexpr uint8_t path_signature(
85     std::string_view input) noexcept {
86   // The path percent-encode set is the query percent-encode set and U+003F (?),
87   // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
88   // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
89   // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
90   // controls and all code points greater than U+007E (~).
91   size_t i = 0;
92   uint8_t accumulator{};
93   for (; i + 7 < input.size(); i += 8) {
94     accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
95                            path_signature_table[uint8_t(input[i + 1])] |
96                            path_signature_table[uint8_t(input[i + 2])] |
97                            path_signature_table[uint8_t(input[i + 3])] |
98                            path_signature_table[uint8_t(input[i + 4])] |
99                            path_signature_table[uint8_t(input[i + 5])] |
100                            path_signature_table[uint8_t(input[i + 6])] |
101                            path_signature_table[uint8_t(input[i + 7])]);
102   }
103   for (; i < input.size(); i++) {
104     accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
105   }
106   return accumulator;
107 }
108 
verify_dns_length(std::string_view input)109 ada_really_inline constexpr bool verify_dns_length(
110     std::string_view input) noexcept {
111   if (input.back() == '.') {
112     if (input.size() > 254) return false;
113   } else if (input.size() > 253)
114     return false;
115 
116   size_t start = 0;
117   while (start < input.size()) {
118     auto dot_location = input.find('.', start);
119     // If not found, it's likely the end of the domain
120     if (dot_location == std::string_view::npos) dot_location = input.size();
121 
122     auto label_size = dot_location - start;
123     if (label_size > 63 || label_size == 0) return false;
124 
125     start = dot_location + 1;
126   }
127 
128   return true;
129 }
130 }  // namespace ada::checkers
131 /* end file src/checkers.cpp */
132 /* begin file src/unicode.cpp */
133 
134 ADA_PUSH_DISABLE_ALL_WARNINGS
135 /* begin file src/ada_idna.cpp */
136 /* auto-generated on 2023-09-19 15:58:51 -0400. Do not edit! */
137 /* begin file src/idna.cpp */
138 /* begin file src/unicode_transcoding.cpp */
139 
140 #include <algorithm>
141 #include <cstdint>
142 #include <cstring>
143 
144 namespace ada::idna {
145 
utf8_to_utf32(const char * buf,size_t len,char32_t * utf32_output)146 size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
147   const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
148   size_t pos = 0;
149   char32_t* start{utf32_output};
150   while (pos < len) {
151     // try to convert the next block of 16 ASCII bytes
152     if (pos + 16 <= len) {  // if it is safe to read 16 more
153                             // bytes, check that they are ascii
154       uint64_t v1;
155       std::memcpy(&v1, data + pos, sizeof(uint64_t));
156       uint64_t v2;
157       std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
158       uint64_t v{v1 | v2};
159       if ((v & 0x8080808080808080) == 0) {
160         size_t final_pos = pos + 16;
161         while (pos < final_pos) {
162           *utf32_output++ = char32_t(buf[pos]);
163           pos++;
164         }
165         continue;
166       }
167     }
168     uint8_t leading_byte = data[pos];  // leading byte
169     if (leading_byte < 0b10000000) {
170       // converting one ASCII byte !!!
171       *utf32_output++ = char32_t(leading_byte);
172       pos++;
173     } else if ((leading_byte & 0b11100000) == 0b11000000) {
174       // We have a two-byte UTF-8
175       if (pos + 1 >= len) {
176         return 0;
177       }  // minimal bound checking
178       if ((data[pos + 1] & 0b11000000) != 0b10000000) {
179         return 0;
180       }
181       // range check
182       uint32_t code_point =
183           (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
184       if (code_point < 0x80 || 0x7ff < code_point) {
185         return 0;
186       }
187       *utf32_output++ = char32_t(code_point);
188       pos += 2;
189     } else if ((leading_byte & 0b11110000) == 0b11100000) {
190       // We have a three-byte UTF-8
191       if (pos + 2 >= len) {
192         return 0;
193       }  // minimal bound checking
194 
195       if ((data[pos + 1] & 0b11000000) != 0b10000000) {
196         return 0;
197       }
198       if ((data[pos + 2] & 0b11000000) != 0b10000000) {
199         return 0;
200       }
201       // range check
202       uint32_t code_point = (leading_byte & 0b00001111) << 12 |
203                             (data[pos + 1] & 0b00111111) << 6 |
204                             (data[pos + 2] & 0b00111111);
205       if (code_point < 0x800 || 0xffff < code_point ||
206           (0xd7ff < code_point && code_point < 0xe000)) {
207         return 0;
208       }
209       *utf32_output++ = char32_t(code_point);
210       pos += 3;
211     } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
212       // we have a 4-byte UTF-8 word.
213       if (pos + 3 >= len) {
214         return 0;
215       }  // minimal bound checking
216       if ((data[pos + 1] & 0b11000000) != 0b10000000) {
217         return 0;
218       }
219       if ((data[pos + 2] & 0b11000000) != 0b10000000) {
220         return 0;
221       }
222       if ((data[pos + 3] & 0b11000000) != 0b10000000) {
223         return 0;
224       }
225 
226       // range check
227       uint32_t code_point = (leading_byte & 0b00000111) << 18 |
228                             (data[pos + 1] & 0b00111111) << 12 |
229                             (data[pos + 2] & 0b00111111) << 6 |
230                             (data[pos + 3] & 0b00111111);
231       if (code_point <= 0xffff || 0x10ffff < code_point) {
232         return 0;
233       }
234       *utf32_output++ = char32_t(code_point);
235       pos += 4;
236     } else {
237       return 0;
238     }
239   }
240   return utf32_output - start;
241 }
242 
utf8_length_from_utf32(const char32_t * buf,size_t len)243 size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
244   // We are not BOM aware.
245   const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
246   size_t counter{0};
247   for (size_t i = 0; i != len; ++i) {
248     ++counter;                                      // ASCII
249     counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
250     counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
251     counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
252   }
253   return counter;
254 }
255 
utf32_length_from_utf8(const char * buf,size_t len)256 size_t utf32_length_from_utf8(const char* buf, size_t len) {
257   const int8_t* p = reinterpret_cast<const int8_t*>(buf);
258   return std::count_if(p, std::next(p, len), [](int8_t c) {
259     // -65 is 0b10111111, anything larger in two-complement's
260     // should start a new code point.
261     return c > -65;
262   });
263 }
264 
utf32_to_utf8(const char32_t * buf,size_t len,char * utf8_output)265 size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
266   const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
267   size_t pos = 0;
268   char* start{utf8_output};
269   while (pos < len) {
270     // try to convert the next block of 2 ASCII characters
271     if (pos + 2 <= len) {  // if it is safe to read 8 more
272                            // bytes, check that they are ascii
273       uint64_t v;
274       std::memcpy(&v, data + pos, sizeof(uint64_t));
275       if ((v & 0xFFFFFF80FFFFFF80) == 0) {
276         *utf8_output++ = char(buf[pos]);
277         *utf8_output++ = char(buf[pos + 1]);
278         pos += 2;
279         continue;
280       }
281     }
282     uint32_t word = data[pos];
283     if ((word & 0xFFFFFF80) == 0) {
284       // will generate one UTF-8 bytes
285       *utf8_output++ = char(word);
286       pos++;
287     } else if ((word & 0xFFFFF800) == 0) {
288       // will generate two UTF-8 bytes
289       // we have 0b110XXXXX 0b10XXXXXX
290       *utf8_output++ = char((word >> 6) | 0b11000000);
291       *utf8_output++ = char((word & 0b111111) | 0b10000000);
292       pos++;
293     } else if ((word & 0xFFFF0000) == 0) {
294       // will generate three UTF-8 bytes
295       // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
296       if (word >= 0xD800 && word <= 0xDFFF) {
297         return 0;
298       }
299       *utf8_output++ = char((word >> 12) | 0b11100000);
300       *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
301       *utf8_output++ = char((word & 0b111111) | 0b10000000);
302       pos++;
303     } else {
304       // will generate four UTF-8 bytes
305       // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
306       // 0b10XXXXXX
307       if (word > 0x10FFFF) {
308         return 0;
309       }
310       *utf8_output++ = char((word >> 18) | 0b11110000);
311       *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
312       *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
313       *utf8_output++ = char((word & 0b111111) | 0b10000000);
314       pos++;
315     }
316   }
317   return utf8_output - start;
318 }
319 }  // namespace ada::idna
320 /* end file src/unicode_transcoding.cpp */
321 /* begin file src/mapping.cpp */
322 
323 #include <algorithm>
324 #include <array>
325 #include <string>
326 
327 /* begin file src/mapping_tables.cpp */
328 // IDNA  15.0.0
329 
330 // clang-format off
331 #ifndef ADA_IDNA_TABLES_H
332 #define ADA_IDNA_TABLES_H
333 #include <cstdint>
334 
335 namespace ada::idna {
336 
337 const uint32_t mappings[5164] =
338 {
339 	97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
340 	114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
341 	956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
342 	228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
343 	244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
344 	269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
345 	301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
346 	110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
347 	361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
348 	392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
349 	417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
350 	100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
351 	483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
352 	513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
353 	414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
354 	649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
355 	32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
356 	953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
357 	949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
358 	968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
359 	1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
360 	1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
361 	1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
362 	1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
363 	1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
364 	1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
365 	1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
366 	1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243, 1245,
367 	1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, 1273,
368 	1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1301,
369 	1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, 1377,
370 	1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391,
371 	1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405,
372 	1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652, 1608,
373 	1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364, 2337,
374 	2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492, 2610,
375 	2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876, 2850,
376 	2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916, 4023,
377 	3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018, 3968,
378 	4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001, 4023,
379 	4006, 4023, 4011, 4023, 3984, 4021, 11559, 11565, 4316, 5104, 5105, 5106, 5107,
380 	5108, 5109, 42571, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314,
381 	4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329,
382 	4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343,
383 	4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604, 7446, 7447, 7453, 7461,
384 	594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671, 625, 624, 627, 628, 632,
385 	642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697,
386 	7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725,
387 	7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753,
388 	7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781,
389 	7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809,
390 	7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 97, 702, 115, 115, 7841,
391 	7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869,
392 	7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897,
393 	7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925,
394 	7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952,
395 	7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984,
396 	7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017,
397 	8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 7936, 953, 7937,
398 	953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953, 7943, 953, 7968, 953,
399 	7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974, 953, 7975, 953, 8032,
400 	953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953, 8038, 953, 8039, 953,
401 	8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32, 787, 32, 834, 32, 776,
402 	834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32, 787, 768, 32, 787, 769,
403 	32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788, 769, 32, 788, 834, 944,
404 	8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969, 953, 974, 953, 8182, 953,
405 	8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, 8245, 8245,
406 	33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55, 56, 57, 43, 8722, 61, 40,
407 	41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99, 47, 117, 176, 102, 115, 109,
408 	116, 101, 108, 116, 109, 1488, 1489, 1490, 1491, 102, 97, 120, 8721, 49, 8260, 55,
409 	49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51, 50, 8260, 51, 49, 8260, 53, 50, 8260,
410 	53, 51, 8260, 53, 52, 8260, 53, 49, 8260, 54, 53, 8260, 54, 49, 8260, 56, 51, 8260,
411 	56, 53, 8260, 56, 55, 8260, 56, 105, 105, 105, 105, 105, 105, 118, 118, 105, 118,
412 	105, 105, 118, 105, 105, 105, 105, 120, 120, 105, 120, 105, 105, 48, 8260, 51, 8747,
413 	8747, 8747, 8747, 8747, 8750, 8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49,
414 	51, 49, 52, 49, 53, 49, 54, 49, 55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50,
415 	41, 40, 51, 41, 40, 52, 41, 40, 53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40,
416 	57, 41, 40, 49, 48, 41, 40, 49, 49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49,
417 	52, 41, 40, 49, 53, 41, 40, 49, 54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49,
418 	57, 41, 40, 50, 48, 41, 40, 97, 41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101,
419 	41, 40, 102, 41, 40, 103, 41, 40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41,
420 	40, 108, 41, 40, 109, 41, 40, 110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40,
421 	114, 41, 40, 115, 41, 40, 116, 41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120,
422 	41, 40, 121, 41, 40, 122, 41, 58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314,
423 	11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326,
424 	11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338,
425 	11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350,
426 	11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359, 11361, 619, 7549,
427 	637, 11368, 11370, 11372, 11379, 11382, 575, 576, 11393, 11395, 11397, 11399, 11401,
428 	11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425,
429 	11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449,
430 	11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473,
431 	11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507,
432 	11617, 27597, 40863, 19968, 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154,
433 	20799, 20837, 20843, 20866, 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269,
434 	21274, 21304, 21313, 21340, 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763,
435 	22786, 22794, 22805, 22823, 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662,
436 	23665, 24027, 24037, 24049, 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339,
437 	24400, 24417, 24435, 24515, 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020,
438 	26041, 26080, 26085, 26352, 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604,
439 	27611, 27663, 27668, 27700, 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275,
440 	29356, 29572, 29577, 29916, 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326,
441 	30333, 30382, 30399, 30446, 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435,
442 	31481, 31859, 31992, 32566, 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895,
443 	32905, 33251, 33258, 33267, 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381,
444 	34411, 34880, 34892, 34915, 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960,
445 	35997, 36196, 36208, 36275, 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318,
446 	37324, 37329, 38263, 38272, 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761,
447 	38859, 38893, 38899, 38913, 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640,
448 	39647, 39717, 39727, 39730, 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643,
449 	40653, 40657, 40697, 40701, 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860,
450 	40864, 46, 12306, 21316, 21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488,
451 	4352, 4353, 4522, 4354, 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532,
452 	4533, 4378, 4358, 4359, 4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368,
453 	4369, 4370, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460,
454 	4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556,
455 	4558, 4563, 4567, 4569, 4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393,
456 	4395, 4396, 4397, 4398, 4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440,
457 	4441, 4484, 4485, 4488, 4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013,
458 	19979, 30002, 19993, 19969, 22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355,
459 	41, 40, 4357, 41, 40, 4358, 41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364,
460 	41, 40, 4366, 41, 40, 4367, 41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032,
461 	41, 40, 45208, 41, 40, 45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40,
462 	49324, 41, 40, 50500, 41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440,
463 	41, 40, 54028, 41, 40, 54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724,
464 	54980, 41, 40, 19968, 41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116,
465 	41, 40, 20845, 41, 40, 19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40,
466 	26376, 41, 40, 28779, 41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303,
467 	41, 40, 26085, 41, 40, 26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40,
468 	29305, 41, 40, 36001, 41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628,
469 	41, 40, 23398, 41, 40, 30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40,
470 	31085, 41, 40, 20241, 41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112,
471 	116, 101, 50, 50, 50, 52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51,
472 	51, 52, 51, 53, 52280, 44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360,
473 	27880, 38917, 20889, 27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51,
474 	56, 51, 57, 52, 48, 52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49,
475 	26376, 50, 26376, 51, 26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376,
476 	57, 26376, 49, 48, 26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103,
477 	101, 118, 108, 116, 100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463,
478 	12465, 12469, 12471, 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491,
479 	12492, 12493, 12494, 12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513,
480 	12514, 12516, 12518, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529,
481 	12530, 20196, 21644, 12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450,
482 	12531, 12506, 12450, 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531,
483 	12481, 12454, 12457, 12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459,
484 	12540, 12458, 12531, 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521,
485 	12483, 12488, 12459, 12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510,
486 	12462, 12460, 12462, 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480,
487 	12540, 12461, 12525, 12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540,
488 	12488, 12523, 12461, 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531,
489 	12463, 12523, 12476, 12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473,
490 	12467, 12523, 12490, 12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531,
491 	12481, 12540, 12512, 12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531,
492 	12488, 12480, 12540, 12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483,
493 	12488, 12495, 12452, 12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484,
494 	12496, 12540, 12524, 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523,
495 	12500, 12467, 12499, 12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540,
496 	12488, 12502, 12483, 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479,
497 	12540, 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531,
498 	12473, 12506, 12540, 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508,
499 	12523, 12488, 12507, 12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540,
500 	12531, 12510, 12452, 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510,
501 	12523, 12463, 12510, 12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511,
502 	12522, 12511, 12522, 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531,
503 	12516, 12540, 12489, 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488,
504 	12523, 12522, 12521, 12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512,
505 	12524, 12531, 12488, 12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52,
506 	28857, 53, 28857, 54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49,
507 	49, 28857, 49, 50, 28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857,
508 	49, 55, 28857, 49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50,
509 	28857, 50, 51, 28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114,
510 	111, 118, 112, 99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104,
511 	26157, 21644, 22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956,
512 	97, 109, 97, 107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108,
513 	112, 102, 110, 102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104,
514 	122, 109, 104, 122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110,
515 	109, 956, 109, 109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109,
516 	50, 109, 109, 51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50,
517 	107, 112, 97, 109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115,
518 	114, 97, 100, 8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110,
519 	118, 956, 118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107,
520 	119, 107, 969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97,
521 	105, 110, 107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108,
522 	109, 111, 108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725,
523 	109, 97, 8725, 109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085,
524 	55, 26085, 56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49,
525 	51, 26085, 49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085,
526 	49, 57, 26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52,
527 	26085, 50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085,
528 	51, 48, 26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573,
529 	42575, 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597,
530 	42599, 42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639,
531 	42641, 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797,
532 	42799, 42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823,
533 	42825, 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847,
534 	42849, 42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879,
535 	42881, 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911,
536 	42913, 42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939,
537 	42941, 42943, 42945, 42947, 42900, 7566, 42952, 42954, 42961, 42967, 42969, 42998,
538 	43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034,
539 	5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048,
540 	5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062,
541 	5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076,
542 	5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090,
543 	5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 35912,
544 	26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856, 25078, 30313, 32645, 34367,
545 	34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, 21365,
546 	27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172, 25289, 33240, 34847, 24266,
547 	26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, 34310,
548 	34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160, 33737, 37636, 35542, 22751,
549 	24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, 28431,
550 	32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260, 32190, 33777, 38517, 35712,
551 	25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, 19981,
552 	27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498, 27578, 27784, 25342, 33509,
553 	25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, 21570,
554 	24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654, 26310, 27511, 36706, 24180,
555 	24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, 36899,
556 	37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565, 25467, 27566, 31806, 29557,
557 	22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, 38936, 20363,
558 	31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, 26009, 29134, 30274, 34044,
559 	36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, 30827, 32016,
560 	39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, 24900, 26647, 38534, 21033,
561 	21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, 35041, 38626,
562 	21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, 40607, 26519, 28107, 33256,
563 	31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, 25299, 31958,
564 	23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, 22618, 26228, 20958, 29482,
565 	30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, 37117, 39151,
566 	39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, 21193, 21220, 21329, 21917,
567 	22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, 26082, 26257,
568 	26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, 31049, 31048, 31056, 31062,
569 	31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, 33401, 33879,
570 	35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, 38911, 38971, 24693, 148206,
571 	33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, 21845, 21913, 21986,
572 	22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425, 24493, 24792, 24910, 24840,
573 	24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, 28363, 28702, 30631,
574 	29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427, 30452, 30538, 30528, 30924,
575 	31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, 35519, 35531, 35565,
576 	35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923, 39698, 141386, 141380, 144341,
577 	15261, 16408, 16441, 152137, 154832, 163539, 40771, 40846, 102, 102, 102, 105, 102,
578 	108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396, 1387, 1406, 1398, 1396, 1389,
579 	1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, 1513, 1473, 1513,
580 	1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463, 1488, 1464, 1488, 1468, 1489,
581 	1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, 1494, 1468, 1496, 1468, 1497,
582 	1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, 1504, 1468, 1505, 1468, 1507,
583 	1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468, 1514, 1468, 1493, 1465, 1489,
584 	1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659, 1662, 1664, 1658, 1663, 1657,
585 	1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678, 1672, 1688, 1681, 1705, 1711,
586 	1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, 1709, 1734, 1736, 1739, 1733,
587 	1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, 1574, 1735, 1574, 1734, 1574,
588 	1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, 1581, 1574, 1605, 1574, 1610,
589 	1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576, 1609, 1576, 1610, 1578, 1580,
590 	1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578, 1610, 1579, 1580, 1579, 1605,
591 	1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, 1605, 1582, 1580, 1582, 1581,
592 	1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, 1605, 1589, 1581, 1589, 1605,
593 	1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, 1581, 1591, 1605, 1592, 1605,
594 	1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601, 1580, 1601, 1581, 1601, 1582,
595 	1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602, 1605, 1602, 1609, 1602, 1610,
596 	1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, 1604, 1603, 1605, 1603, 1609,
597 	1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, 1605, 1604, 1609, 1604, 1610,
598 	1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606, 1580, 1606, 1581, 1606, 1582,
599 	1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, 1605, 1607, 1609, 1607, 1610,
600 	1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585, 1648, 1609, 1648, 32, 1612,
601 	1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617, 32, 1616, 1617, 32, 1617,
602 	1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585, 1576, 1586, 1576, 1606, 1578,
603 	1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586, 1579, 1606, 1605, 1575, 1606,
604 	1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586, 1574, 1582, 1574, 1607, 1576,
605 	1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607, 1607, 1648, 1579, 1607, 1587,
606 	1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600, 1615, 1617, 1600, 1616, 1617,
607 	1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594, 1609, 1594, 1610, 1587, 1609,
608 	1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580, 1609, 1580, 1610, 1582, 1609,
609 	1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588, 1580, 1588, 1581, 1588, 1582,
610 	1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575, 1611, 1578, 1580, 1605, 1578,
611 	1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578, 1605, 1580, 1578, 1605, 1581,
612 	1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609, 1587, 1581, 1580, 1587, 1580,
613 	1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605, 1580, 1587, 1605, 1605, 1589,
614 	1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588, 1580, 1610, 1588, 1605, 1582,
615 	1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, 1591, 1605, 1581, 1591, 1605,
616 	1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, 1605, 1593, 1605, 1609, 1594,
617 	1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601, 1582, 1605, 1602, 1605, 1581,
618 	1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610, 1604, 1581, 1609, 1604, 1580,
619 	1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, 1580, 1605, 1581, 1610, 1605,
620 	1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607, 1605, 1580, 1607, 1605, 1605,
621 	1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605, 1606, 1580, 1609, 1606, 1605,
622 	1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582, 1610, 1578, 1580, 1610, 1578,
623 	1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578, 1605, 1610, 1578, 1605, 1609,
624 	1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609, 1587, 1582, 1609, 1589, 1581,
625 	1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580, 1610, 1604, 1605, 1610, 1610,
626 	1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, 1605, 1610, 1606, 1581, 1610,
627 	1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581, 1605, 1582, 1610, 1604, 1580,
628 	1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, 1601,
629 	1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, 1580, 1610, 1589, 1604, 1746,
630 	1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, 1576, 1585, 1605, 1581, 1605,
631 	1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604, 1593, 1604, 1610, 1607, 1608,
632 	1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607,
633 	32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 1580, 1604, 32, 1580, 1604,
634 	1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289, 12310, 12311, 8212, 8211, 95,
635 	123, 125, 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, 12302, 12303,
636 	91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32, 1611, 1600, 1611, 1600, 1617,
637 	32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, 1577, 1604, 1570, 1604, 1571,
638 	1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539, 12453, 12515, 162, 163, 172,
639 	166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, 66600, 66601, 66602, 66603,
640 	66604, 66605, 66606, 66607, 66608, 66609, 66610, 66611, 66612, 66613, 66614, 66615,
641 	66616, 66617, 66618, 66619, 66620, 66621, 66622, 66623, 66624, 66625, 66626, 66627,
642 	66628, 66629, 66630, 66631, 66632, 66633, 66634, 66635, 66636, 66637, 66638, 66639,
643 	66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787,
644 	66788, 66789, 66790, 66791, 66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799,
645 	66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807, 66808, 66809, 66810, 66811,
646 	66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, 66975, 66976, 66977, 66979,
647 	66980, 66981, 66982, 66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, 66991,
648 	66992, 66993, 66995, 66996, 66997, 66998, 66999, 67000, 67001, 67003, 67004, 720,
649 	721, 665, 675, 43878, 677, 676, 7569, 600, 606, 681, 612, 610, 667, 668, 615, 644,
650 	682, 683, 122628, 42894, 622, 122629, 654, 122630, 630, 631, 634, 122632, 638, 680,
651 	678, 43879, 679, 11377, 655, 673, 674, 664, 448, 449, 450, 122634, 122654, 68800,
652 	68801, 68802, 68803, 68804, 68805, 68806, 68807, 68808, 68809, 68810, 68811, 68812,
653 	68813, 68814, 68815, 68816, 68817, 68818, 68819, 68820, 68821, 68822, 68823, 68824,
654 	68825, 68826, 68827, 68828, 68829, 68830, 68831, 68832, 68833, 68834, 68835, 68836,
655 	68837, 68838, 68839, 68840, 68841, 68842, 68843, 68844, 68845, 68846, 68847, 68848,
656 	68849, 68850, 71872, 71873, 71874, 71875, 71876, 71877, 71878, 71879, 71880, 71881,
657 	71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890, 71891, 71892, 71893,
658 	71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, 71903, 93792, 93793,
659 	93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, 93803, 93804, 93805,
660 	93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814, 93815, 93816, 93817,
661 	93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128, 119141, 119128,
662 	119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152, 119128, 119141,
663 	119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141, 119225, 119141,
664 	119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226, 119141, 119151,
665 	305, 567, 8711, 8706, 1231, 125218, 125219, 125220, 125221, 125222, 125223, 125224,
666 	125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233, 125234,
667 	125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, 125244,
668 	125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647, 48, 44,
669 	49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44, 12308, 115,
670 	12309, 119, 122, 104, 118, 115, 100, 112, 112, 118, 119, 99, 109, 114, 100, 106,
671 	12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132, 26144, 28961, 21069,
672 	24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, 25429, 36938,
673 	25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942, 37197, 12308, 26412,
674 	12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, 12308, 28857,
675 	12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213, 12309, 12308, 25943,
676 	12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411, 20482, 20602, 20633,
677 	20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839, 132427, 20887,
678 	20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589, 21253, 21254,
679 	21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987, 21483, 21489,
680 	21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931,
681 	21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541, 22411, 22578,
682 	22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938, 23020,
683 	23067, 23079, 23000, 23142, 14062, 23304, 23358, 137672, 23491, 23512, 23539, 138008,
684 	23551, 23558, 14209, 23648, 23744, 23693, 138724, 23875, 138726, 23918, 23915, 23932,
685 	24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651, 14460, 24240, 24243,
686 	24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122, 24418, 24427, 14563,
687 	24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775, 24904, 24908, 24954,
688 	25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424, 142092, 25405, 25340,
689 	25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705, 25726, 25757, 25719,
690 	14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, 26368,
691 	26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618, 26501, 26706, 144493,
692 	26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355, 15384, 27425, 145575,
693 	27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170, 27726, 146620, 27839,
694 	27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956, 28207, 28270, 15667,
695 	28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729, 28699, 15766, 28746,
696 	28797, 28791, 28845, 132389, 28997, 148067, 29084, 29224, 29264, 149000, 29312,
697 	29333, 149301, 149524, 29562, 29579, 16044, 29605, 16056, 29767, 29788, 29829, 29898,
698 	16155, 29988, 150582, 30014, 150674, 139679, 30224, 151457, 151480, 151620, 16380,
699 	16392, 151795, 151794, 151833, 151859, 30494, 30495, 30603, 16454, 16534, 152605,
700 	30798, 16611, 153126, 153242, 153285, 31211, 16687, 31306, 31311, 153980, 154279,
701 	16898, 154539, 31686, 31689, 16935, 154752, 31954, 17056, 31976, 31971, 32000, 155526,
702 	32099, 17153, 32199, 32258, 32325, 17204, 156200, 156231, 17241, 156377, 32634,
703 	156478, 32661, 32762, 156890, 156963, 32864, 157096, 32880, 144223, 17365, 32946,
704 	33027, 17419, 33086, 23221, 157607, 157621, 144275, 144284, 33284, 36766, 17515,
705 	33425, 33419, 33437, 21171, 33457, 33459, 33469, 33510, 158524, 33565, 33635, 33709,
706 	33571, 33725, 33767, 33619, 33738, 33740, 33756, 158774, 159083, 158933, 17707,
707 	34033, 34035, 34070, 160714, 34148, 159532, 17757, 17761, 159665, 159954, 17771,
708 	34384, 34407, 34409, 34473, 34440, 34574, 34530, 34600, 34667, 34694, 34785, 34817,
709 	17913, 34912, 161383, 35031, 35038, 17973, 35066, 13499, 161966, 162150, 18110,
710 	18119, 35488, 162984, 36011, 36033, 36123, 36215, 163631, 133124, 36299, 36284,
711 	36336, 133342, 36564, 165330, 165357, 37012, 37105, 37137, 165678, 37147, 37432,
712 	37591, 37592, 37500, 37881, 37909, 166906, 38283, 18837, 38327, 167287, 18918, 38595,
713 	23986, 38691, 168261, 168474, 19054, 19062, 38880, 168970, 19122, 169110, 38953,
714 	169398, 39138, 19251, 39209, 39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662,
715 	19693, 40295, 172238, 19704, 172293, 172558, 172689, 19798, 40702, 40709, 40719,
716 	40726, 173568,
717 
718 };
719 const uint32_t table[8000][2] =
720 {
721 	{0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
722 	{68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
723 	{72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
724 	{76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
725 	{80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
726 	{84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
727 	{88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
728 	{128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
729 	{169, 1}, {170, 16777219}, {171, 1}, {173, 0},
730 	{174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
731 	{179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
732 	{184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
733 	{188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
734 	{192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
735 	{196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
736 	{200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
737 	{204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
738 	{208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
739 	{212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
740 	{216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
741 	{220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
742 	{256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
743 	{260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
744 	{264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
745 	{268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
746 	{272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
747 	{276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
748 	{280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
749 	{284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
750 	{288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
751 	{292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
752 	{296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
753 	{300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
754 	{304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
755 	{309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
756 	{314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
757 	{318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
758 	{323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
759 	{327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
760 	{331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
761 	{335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
762 	{339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
763 	{343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
764 	{347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
765 	{351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
766 	{355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
767 	{359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
768 	{363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
769 	{367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
770 	{371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
771 	{375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
772 	{379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
773 	{383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
774 	{387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
775 	{391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
776 	{395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
777 	{400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
778 	{404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
779 	{408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
780 	{414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
781 	{418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
782 	{422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
783 	{426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
784 	{431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
785 	{435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
786 	{439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
787 	{445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
788 	{461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
789 	{465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
790 	{469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
791 	{473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
792 	{478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
793 	{482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
794 	{486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
795 	{490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
796 	{494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
797 	{501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
798 	{505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
799 	{509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
800 	{513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
801 	{517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
802 	{521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
803 	{525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
804 	{529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
805 	{533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
806 	{537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
807 	{541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
808 	{545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
809 	{549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
810 	{553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
811 	{557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
812 	{561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
813 	{571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
814 	{575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
815 	{580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
816 	{584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
817 	{588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
818 	{688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
819 	{692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
820 	{696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
821 	{730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
822 	{734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
823 	{739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
824 	{833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
825 	{837, 16846851}, {838, 1}, {847, 0}, {848, 1},
826 	{880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
827 	{884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
828 	{888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
829 	{895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
830 	{902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
831 	{906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
832 	{910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
833 	{914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
834 	{918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
835 	{922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
836 	{926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
837 	{930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
838 	{934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
839 	{938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
840 	{976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
841 	{980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
842 	{984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
843 	{988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
844 	{992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
845 	{996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
846 	{1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
847 	{1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
848 	{1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
849 	{1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
850 	{1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
851 	{1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
852 	{1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
853 	{1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
854 	{1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
855 	{1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
856 	{1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
857 	{1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
858 	{1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
859 	{1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
860 	{1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
861 	{1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
862 	{1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
863 	{1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
864 	{1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
865 	{1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
866 	{1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
867 	{1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
868 	{1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
869 	{1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
870 	{1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
871 	{1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
872 	{1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
873 	{1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
874 	{1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
875 	{1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
876 	{1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
877 	{1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
878 	{1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
879 	{1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
880 	{1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
881 	{1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
882 	{1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
883 	{1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
884 	{1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
885 	{1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
886 	{1216, 2}, {1217, 16886019}, {1218, 1}, {1219, 16886275},
887 	{1220, 1}, {1221, 16886531}, {1222, 1}, {1223, 16886787},
888 	{1224, 1}, {1225, 16887043}, {1226, 1}, {1227, 16887299},
889 	{1228, 1}, {1229, 16887555}, {1230, 1}, {1232, 16887811},
890 	{1233, 1}, {1234, 16888067}, {1235, 1}, {1236, 16888323},
891 	{1237, 1}, {1238, 16888579}, {1239, 1}, {1240, 16888835},
892 	{1241, 1}, {1242, 16889091}, {1243, 1}, {1244, 16889347},
893 	{1245, 1}, {1246, 16889603}, {1247, 1}, {1248, 16889859},
894 	{1249, 1}, {1250, 16890115}, {1251, 1}, {1252, 16890371},
895 	{1253, 1}, {1254, 16890627}, {1255, 1}, {1256, 16890883},
896 	{1257, 1}, {1258, 16891139}, {1259, 1}, {1260, 16891395},
897 	{1261, 1}, {1262, 16891651}, {1263, 1}, {1264, 16891907},
898 	{1265, 1}, {1266, 16892163}, {1267, 1}, {1268, 16892419},
899 	{1269, 1}, {1270, 16892675}, {1271, 1}, {1272, 16892931},
900 	{1273, 1}, {1274, 16893187}, {1275, 1}, {1276, 16893443},
901 	{1277, 1}, {1278, 16893699}, {1279, 1}, {1280, 16893955},
902 	{1281, 1}, {1282, 16894211}, {1283, 1}, {1284, 16894467},
903 	{1285, 1}, {1286, 16894723}, {1287, 1}, {1288, 16894979},
904 	{1289, 1}, {1290, 16895235}, {1291, 1}, {1292, 16895491},
905 	{1293, 1}, {1294, 16895747}, {1295, 1}, {1296, 16896003},
906 	{1297, 1}, {1298, 16896259}, {1299, 1}, {1300, 16896515},
907 	{1301, 1}, {1302, 16896771}, {1303, 1}, {1304, 16897027},
908 	{1305, 1}, {1306, 16897283}, {1307, 1}, {1308, 16897539},
909 	{1309, 1}, {1310, 16897795}, {1311, 1}, {1312, 16898051},
910 	{1313, 1}, {1314, 16898307}, {1315, 1}, {1316, 16898563},
911 	{1317, 1}, {1318, 16898819}, {1319, 1}, {1320, 16899075},
912 	{1321, 1}, {1322, 16899331}, {1323, 1}, {1324, 16899587},
913 	{1325, 1}, {1326, 16899843}, {1327, 1}, {1328, 2},
914 	{1329, 16900099}, {1330, 16900355}, {1331, 16900611}, {1332, 16900867},
915 	{1333, 16901123}, {1334, 16901379}, {1335, 16901635}, {1336, 16901891},
916 	{1337, 16902147}, {1338, 16902403}, {1339, 16902659}, {1340, 16902915},
917 	{1341, 16903171}, {1342, 16903427}, {1343, 16903683}, {1344, 16903939},
918 	{1345, 16904195}, {1346, 16904451}, {1347, 16904707}, {1348, 16904963},
919 	{1349, 16905219}, {1350, 16905475}, {1351, 16905731}, {1352, 16905987},
920 	{1353, 16906243}, {1354, 16906499}, {1355, 16906755}, {1356, 16907011},
921 	{1357, 16907267}, {1358, 16907523}, {1359, 16907779}, {1360, 16908035},
922 	{1361, 16908291}, {1362, 16908547}, {1363, 16908803}, {1364, 16909059},
923 	{1365, 16909315}, {1366, 16909571}, {1367, 2}, {1369, 1},
924 	{1415, 33687043}, {1416, 1}, {1419, 2}, {1421, 1},
925 	{1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
926 	{1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
927 	{1564, 2}, {1565, 1}, {1653, 33687555}, {1654, 33688067},
928 	{1655, 33688579}, {1656, 33689091}, {1657, 1}, {1757, 2},
929 	{1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
930 	{1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
931 	{2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
932 	{2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
933 	{2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
934 	{2200, 1}, {2274, 2}, {2275, 1}, {2392, 33689603},
935 	{2393, 33690115}, {2394, 33690627}, {2395, 33691139}, {2396, 33691651},
936 	{2397, 33692163}, {2398, 33692675}, {2399, 33693187}, {2400, 1},
937 	{2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
938 	{2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
939 	{2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
940 	{2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
941 	{2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
942 	{2520, 2}, {2524, 33693699}, {2525, 33694211}, {2526, 2},
943 	{2527, 33694723}, {2528, 1}, {2532, 2}, {2534, 1},
944 	{2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
945 	{2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
946 	{2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
947 	{2611, 33695235}, {2612, 2}, {2613, 1}, {2614, 33695747},
948 	{2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
949 	{2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
950 	{2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
951 	{2642, 2}, {2649, 33696259}, {2650, 33696771}, {2651, 33697283},
952 	{2652, 1}, {2653, 2}, {2654, 33697795}, {2655, 2},
953 	{2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
954 	{2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
955 	{2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
956 	{2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
957 	{2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
958 	{2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
959 	{2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
960 	{2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
961 	{2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
962 	{2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
963 	{2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
964 	{2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
965 	{2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
966 	{2908, 33698307}, {2909, 33698819}, {2910, 2}, {2911, 1},
967 	{2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
968 	{2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
969 	{2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
970 	{2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
971 	{2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
972 	{2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
973 	{3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
974 	{3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
975 	{3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
976 	{3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
977 	{3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
978 	{3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
979 	{3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
980 	{3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
981 	{3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
982 	{3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
983 	{3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
984 	{3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
985 	{3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
986 	{3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
987 	{3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
988 	{3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
989 	{3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
990 	{3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
991 	{3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
992 	{3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
993 	{3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
994 	{3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
995 	{3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
996 	{3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
997 	{3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
998 	{3635, 33699331}, {3636, 1}, {3643, 2}, {3647, 1},
999 	{3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1000 	{3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1001 	{3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1002 	{3763, 33699843}, {3764, 1}, {3774, 2}, {3776, 1},
1003 	{3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1004 	{3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700355},
1005 	{3805, 33700867}, {3806, 1}, {3808, 2}, {3840, 1},
1006 	{3852, 16924163}, {3853, 1}, {3907, 33701635}, {3908, 1},
1007 	{3912, 2}, {3913, 1}, {3917, 33702147}, {3918, 1},
1008 	{3922, 33702659}, {3923, 1}, {3927, 33703171}, {3928, 1},
1009 	{3932, 33703683}, {3933, 1}, {3945, 33704195}, {3946, 1},
1010 	{3949, 2}, {3953, 1}, {3955, 33704707}, {3956, 1},
1011 	{3957, 33705219}, {3958, 33705731}, {3959, 50483459}, {3960, 33707011},
1012 	{3961, 50484739}, {3962, 1}, {3969, 33706499}, {3970, 1},
1013 	{3987, 33708291}, {3988, 1}, {3992, 2}, {3993, 1},
1014 	{3997, 33708803}, {3998, 1}, {4002, 33709315}, {4003, 1},
1015 	{4007, 33709827}, {4008, 1}, {4012, 33710339}, {4013, 1},
1016 	{4025, 33710851}, {4026, 1}, {4029, 2}, {4030, 1},
1017 	{4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1018 	{4256, 2}, {4295, 16934147}, {4296, 2}, {4301, 16934403},
1019 	{4302, 2}, {4304, 1}, {4348, 16934659}, {4349, 1},
1020 	{4447, 2}, {4449, 1}, {4681, 2}, {4682, 1},
1021 	{4686, 2}, {4688, 1}, {4695, 2}, {4696, 1},
1022 	{4697, 2}, {4698, 1}, {4702, 2}, {4704, 1},
1023 	{4745, 2}, {4746, 1}, {4750, 2}, {4752, 1},
1024 	{4785, 2}, {4786, 1}, {4790, 2}, {4792, 1},
1025 	{4799, 2}, {4800, 1}, {4801, 2}, {4802, 1},
1026 	{4806, 2}, {4808, 1}, {4823, 2}, {4824, 1},
1027 	{4881, 2}, {4882, 1}, {4886, 2}, {4888, 1},
1028 	{4955, 2}, {4957, 1}, {4989, 2}, {4992, 1},
1029 	{5018, 2}, {5024, 1}, {5110, 2}, {5112, 16934915},
1030 	{5113, 16935171}, {5114, 16935427}, {5115, 16935683}, {5116, 16935939},
1031 	{5117, 16936195}, {5118, 2}, {5120, 1}, {5760, 2},
1032 	{5761, 1}, {5789, 2}, {5792, 1}, {5881, 2},
1033 	{5888, 1}, {5910, 2}, {5919, 1}, {5943, 2},
1034 	{5952, 1}, {5972, 2}, {5984, 1}, {5997, 2},
1035 	{5998, 1}, {6001, 2}, {6002, 1}, {6004, 2},
1036 	{6016, 1}, {6068, 2}, {6070, 1}, {6110, 2},
1037 	{6112, 1}, {6122, 2}, {6128, 1}, {6138, 2},
1038 	{6144, 1}, {6150, 2}, {6151, 1}, {6155, 0},
1039 	{6158, 2}, {6159, 0}, {6160, 1}, {6170, 2},
1040 	{6176, 1}, {6265, 2}, {6272, 1}, {6315, 2},
1041 	{6320, 1}, {6390, 2}, {6400, 1}, {6431, 2},
1042 	{6432, 1}, {6444, 2}, {6448, 1}, {6460, 2},
1043 	{6464, 1}, {6465, 2}, {6468, 1}, {6510, 2},
1044 	{6512, 1}, {6517, 2}, {6528, 1}, {6572, 2},
1045 	{6576, 1}, {6602, 2}, {6608, 1}, {6619, 2},
1046 	{6622, 1}, {6684, 2}, {6686, 1}, {6751, 2},
1047 	{6752, 1}, {6781, 2}, {6783, 1}, {6794, 2},
1048 	{6800, 1}, {6810, 2}, {6816, 1}, {6830, 2},
1049 	{6832, 1}, {6863, 2}, {6912, 1}, {6989, 2},
1050 	{6992, 1}, {7039, 2}, {7040, 1}, {7156, 2},
1051 	{7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1052 	{7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1053 	{7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1054 	{7304, 16936451}, {7305, 2}, {7312, 16936707}, {7313, 16936963},
1055 	{7314, 16937219}, {7315, 16937475}, {7316, 16937731}, {7317, 16937987},
1056 	{7318, 16938243}, {7319, 16938499}, {7320, 16938755}, {7321, 16939011},
1057 	{7322, 16939267}, {7323, 16939523}, {7324, 16934659}, {7325, 16939779},
1058 	{7326, 16940035}, {7327, 16940291}, {7328, 16940547}, {7329, 16940803},
1059 	{7330, 16941059}, {7331, 16941315}, {7332, 16941571}, {7333, 16941827},
1060 	{7334, 16942083}, {7335, 16942339}, {7336, 16942595}, {7337, 16942851},
1061 	{7338, 16943107}, {7339, 16943363}, {7340, 16943619}, {7341, 16943875},
1062 	{7342, 16944131}, {7343, 16944387}, {7344, 16944643}, {7345, 16944899},
1063 	{7346, 16945155}, {7347, 16945411}, {7348, 16945667}, {7349, 16945923},
1064 	{7350, 16946179}, {7351, 16946435}, {7352, 16946691}, {7353, 16946947},
1065 	{7354, 16947203}, {7355, 2}, {7357, 16947459}, {7358, 16947715},
1066 	{7359, 16947971}, {7360, 1}, {7368, 2}, {7376, 1},
1067 	{7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043},
1068 	{7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243},
1069 	{7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267},
1070 	{7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291},
1071 	{7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843},
1072 	{7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339},
1073 	{7490, 16782851}, {7491, 16777219}, {7492, 16948227}, {7493, 16948483},
1074 	{7494, 16948739}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243},
1075 	{7498, 16816387}, {7499, 16816643}, {7500, 16948995}, {7501, 16778755},
1076 	{7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171},
1077 	{7506, 16780803}, {7507, 16814851}, {7508, 16949251}, {7509, 16949507},
1078 	{7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16949763},
1079 	{7514, 16818435}, {7515, 16782595}, {7516, 16950019}, {7517, 16851971},
1080 	{7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579},
1081 	{7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595},
1082 	{7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323},
1083 	{7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1},
1084 	{7579, 16950275}, {7580, 16777731}, {7581, 16950531}, {7582, 16793603},
1085 	{7583, 16948995}, {7584, 16778499}, {7585, 16950787}, {7586, 16951043},
1086 	{7587, 16951299}, {7588, 16817923}, {7589, 16817667}, {7590, 16951555},
1087 	{7591, 16951811}, {7592, 16952067}, {7593, 16952323}, {7594, 16952579},
1088 	{7595, 16952835}, {7596, 16953091}, {7597, 16953347}, {7598, 16818691},
1089 	{7599, 16953603}, {7600, 16953859}, {7601, 16818947}, {7602, 16954115},
1090 	{7603, 16954371}, {7604, 16820483}, {7605, 16954627}, {7606, 16839683},
1091 	{7607, 16821507}, {7608, 16954883}, {7609, 16821763}, {7610, 16839939},
1092 	{7611, 16783619}, {7612, 16955139}, {7613, 16955395}, {7614, 16822531},
1093 	{7615, 16853507}, {7616, 1}, {7680, 16955651}, {7681, 1},
1094 	{7682, 16955907}, {7683, 1}, {7684, 16956163}, {7685, 1},
1095 	{7686, 16956419}, {7687, 1}, {7688, 16956675}, {7689, 1},
1096 	{7690, 16956931}, {7691, 1}, {7692, 16957187}, {7693, 1},
1097 	{7694, 16957443}, {7695, 1}, {7696, 16957699}, {7697, 1},
1098 	{7698, 16957955}, {7699, 1}, {7700, 16958211}, {7701, 1},
1099 	{7702, 16958467}, {7703, 1}, {7704, 16958723}, {7705, 1},
1100 	{7706, 16958979}, {7707, 1}, {7708, 16959235}, {7709, 1},
1101 	{7710, 16959491}, {7711, 1}, {7712, 16959747}, {7713, 1},
1102 	{7714, 16960003}, {7715, 1}, {7716, 16960259}, {7717, 1},
1103 	{7718, 16960515}, {7719, 1}, {7720, 16960771}, {7721, 1},
1104 	{7722, 16961027}, {7723, 1}, {7724, 16961283}, {7725, 1},
1105 	{7726, 16961539}, {7727, 1}, {7728, 16961795}, {7729, 1},
1106 	{7730, 16962051}, {7731, 1}, {7732, 16962307}, {7733, 1},
1107 	{7734, 16962563}, {7735, 1}, {7736, 16962819}, {7737, 1},
1108 	{7738, 16963075}, {7739, 1}, {7740, 16963331}, {7741, 1},
1109 	{7742, 16963587}, {7743, 1}, {7744, 16963843}, {7745, 1},
1110 	{7746, 16964099}, {7747, 1}, {7748, 16964355}, {7749, 1},
1111 	{7750, 16964611}, {7751, 1}, {7752, 16964867}, {7753, 1},
1112 	{7754, 16965123}, {7755, 1}, {7756, 16965379}, {7757, 1},
1113 	{7758, 16965635}, {7759, 1}, {7760, 16965891}, {7761, 1},
1114 	{7762, 16966147}, {7763, 1}, {7764, 16966403}, {7765, 1},
1115 	{7766, 16966659}, {7767, 1}, {7768, 16966915}, {7769, 1},
1116 	{7770, 16967171}, {7771, 1}, {7772, 16967427}, {7773, 1},
1117 	{7774, 16967683}, {7775, 1}, {7776, 16967939}, {7777, 1},
1118 	{7778, 16968195}, {7779, 1}, {7780, 16968451}, {7781, 1},
1119 	{7782, 16968707}, {7783, 1}, {7784, 16968963}, {7785, 1},
1120 	{7786, 16969219}, {7787, 1}, {7788, 16969475}, {7789, 1},
1121 	{7790, 16969731}, {7791, 1}, {7792, 16969987}, {7793, 1},
1122 	{7794, 16970243}, {7795, 1}, {7796, 16970499}, {7797, 1},
1123 	{7798, 16970755}, {7799, 1}, {7800, 16971011}, {7801, 1},
1124 	{7802, 16971267}, {7803, 1}, {7804, 16971523}, {7805, 1},
1125 	{7806, 16971779}, {7807, 1}, {7808, 16972035}, {7809, 1},
1126 	{7810, 16972291}, {7811, 1}, {7812, 16972547}, {7813, 1},
1127 	{7814, 16972803}, {7815, 1}, {7816, 16973059}, {7817, 1},
1128 	{7818, 16973315}, {7819, 1}, {7820, 16973571}, {7821, 1},
1129 	{7822, 16973827}, {7823, 1}, {7824, 16974083}, {7825, 1},
1130 	{7826, 16974339}, {7827, 1}, {7828, 16974595}, {7829, 1},
1131 	{7834, 33752067}, {7835, 16967939}, {7836, 1}, {7838, 33752579},
1132 	{7839, 1}, {7840, 16975875}, {7841, 1}, {7842, 16976131},
1133 	{7843, 1}, {7844, 16976387}, {7845, 1}, {7846, 16976643},
1134 	{7847, 1}, {7848, 16976899}, {7849, 1}, {7850, 16977155},
1135 	{7851, 1}, {7852, 16977411}, {7853, 1}, {7854, 16977667},
1136 	{7855, 1}, {7856, 16977923}, {7857, 1}, {7858, 16978179},
1137 	{7859, 1}, {7860, 16978435}, {7861, 1}, {7862, 16978691},
1138 	{7863, 1}, {7864, 16978947}, {7865, 1}, {7866, 16979203},
1139 	{7867, 1}, {7868, 16979459}, {7869, 1}, {7870, 16979715},
1140 	{7871, 1}, {7872, 16979971}, {7873, 1}, {7874, 16980227},
1141 	{7875, 1}, {7876, 16980483}, {7877, 1}, {7878, 16980739},
1142 	{7879, 1}, {7880, 16980995}, {7881, 1}, {7882, 16981251},
1143 	{7883, 1}, {7884, 16981507}, {7885, 1}, {7886, 16981763},
1144 	{7887, 1}, {7888, 16982019}, {7889, 1}, {7890, 16982275},
1145 	{7891, 1}, {7892, 16982531}, {7893, 1}, {7894, 16982787},
1146 	{7895, 1}, {7896, 16983043}, {7897, 1}, {7898, 16983299},
1147 	{7899, 1}, {7900, 16983555}, {7901, 1}, {7902, 16983811},
1148 	{7903, 1}, {7904, 16984067}, {7905, 1}, {7906, 16984323},
1149 	{7907, 1}, {7908, 16984579}, {7909, 1}, {7910, 16984835},
1150 	{7911, 1}, {7912, 16985091}, {7913, 1}, {7914, 16985347},
1151 	{7915, 1}, {7916, 16985603}, {7917, 1}, {7918, 16985859},
1152 	{7919, 1}, {7920, 16986115}, {7921, 1}, {7922, 16986371},
1153 	{7923, 1}, {7924, 16986627}, {7925, 1}, {7926, 16986883},
1154 	{7927, 1}, {7928, 16987139}, {7929, 1}, {7930, 16987395},
1155 	{7931, 1}, {7932, 16987651}, {7933, 1}, {7934, 16987907},
1156 	{7935, 1}, {7944, 16988163}, {7945, 16988419}, {7946, 16988675},
1157 	{7947, 16988931}, {7948, 16989187}, {7949, 16989443}, {7950, 16989699},
1158 	{7951, 16989955}, {7952, 1}, {7958, 2}, {7960, 16990211},
1159 	{7961, 16990467}, {7962, 16990723}, {7963, 16990979}, {7964, 16991235},
1160 	{7965, 16991491}, {7966, 2}, {7968, 1}, {7976, 16991747},
1161 	{7977, 16992003}, {7978, 16992259}, {7979, 16992515}, {7980, 16992771},
1162 	{7981, 16993027}, {7982, 16993283}, {7983, 16993539}, {7984, 1},
1163 	{7992, 16993795}, {7993, 16994051}, {7994, 16994307}, {7995, 16994563},
1164 	{7996, 16994819}, {7997, 16995075}, {7998, 16995331}, {7999, 16995587},
1165 	{8000, 1}, {8006, 2}, {8008, 16995843}, {8009, 16996099},
1166 	{8010, 16996355}, {8011, 16996611}, {8012, 16996867}, {8013, 16997123},
1167 	{8014, 2}, {8016, 1}, {8024, 2}, {8025, 16997379},
1168 	{8026, 2}, {8027, 16997635}, {8028, 2}, {8029, 16997891},
1169 	{8030, 2}, {8031, 16998147}, {8032, 1}, {8040, 16998403},
1170 	{8041, 16998659}, {8042, 16998915}, {8043, 16999171}, {8044, 16999427},
1171 	{8045, 16999683}, {8046, 16999939}, {8047, 17000195}, {8048, 1},
1172 	{8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1},
1173 	{8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1},
1174 	{8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1},
1175 	{8061, 16851459}, {8062, 2}, {8064, 33777667}, {8065, 33778179},
1176 	{8066, 33778691}, {8067, 33779203}, {8068, 33779715}, {8069, 33780227},
1177 	{8070, 33780739}, {8071, 33781251}, {8072, 33777667}, {8073, 33778179},
1178 	{8074, 33778691}, {8075, 33779203}, {8076, 33779715}, {8077, 33780227},
1179 	{8078, 33780739}, {8079, 33781251}, {8080, 33781763}, {8081, 33782275},
1180 	{8082, 33782787}, {8083, 33783299}, {8084, 33783811}, {8085, 33784323},
1181 	{8086, 33784835}, {8087, 33785347}, {8088, 33781763}, {8089, 33782275},
1182 	{8090, 33782787}, {8091, 33783299}, {8092, 33783811}, {8093, 33784323},
1183 	{8094, 33784835}, {8095, 33785347}, {8096, 33785859}, {8097, 33786371},
1184 	{8098, 33786883}, {8099, 33787395}, {8100, 33787907}, {8101, 33788419},
1185 	{8102, 33788931}, {8103, 33789443}, {8104, 33785859}, {8105, 33786371},
1186 	{8106, 33786883}, {8107, 33787395}, {8108, 33787907}, {8109, 33788419},
1187 	{8110, 33788931}, {8111, 33789443}, {8112, 1}, {8114, 33789955},
1188 	{8115, 33790467}, {8116, 33790979}, {8117, 2}, {8118, 1},
1189 	{8119, 33791491}, {8120, 17014787}, {8121, 17015043}, {8122, 17012739},
1190 	{8123, 16849923}, {8124, 33790467}, {8125, 33792515}, {8126, 16846851},
1191 	{8127, 33792515}, {8128, 33793027}, {8129, 50570755}, {8130, 33794307},
1192 	{8131, 33794819}, {8132, 33795331}, {8133, 2}, {8134, 1},
1193 	{8135, 33795843}, {8136, 17019139}, {8137, 16850179}, {8138, 17017091},
1194 	{8139, 16850435}, {8140, 33794819}, {8141, 50573827}, {8142, 50574595},
1195 	{8143, 50575363}, {8144, 1}, {8147, 17021699}, {8148, 2},
1196 	{8150, 1}, {8152, 17021955}, {8153, 17022211}, {8154, 17022467},
1197 	{8155, 16850691}, {8156, 2}, {8157, 50577155}, {8158, 50577923},
1198 	{8159, 50578691}, {8160, 1}, {8163, 17025027}, {8164, 1},
1199 	{8168, 17025283}, {8169, 17025539}, {8170, 17025795}, {8171, 16851203},
1200 	{8172, 17026051}, {8173, 50580739}, {8174, 50403587}, {8175, 17027075},
1201 	{8176, 2}, {8178, 33804547}, {8179, 33805059}, {8180, 33805571},
1202 	{8181, 2}, {8182, 1}, {8183, 33806083}, {8184, 17029379},
1203 	{8185, 16850947}, {8186, 17027331}, {8187, 16851459}, {8188, 33805059},
1204 	{8189, 33562883}, {8190, 33799939}, {8191, 2}, {8192, 16783875},
1205 	{8203, 0}, {8204, 1}, {8206, 2}, {8208, 1},
1206 	{8209, 17029635}, {8210, 1}, {8215, 33807107}, {8216, 1},
1207 	{8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875},
1208 	{8240, 1}, {8243, 33807619}, {8244, 50585347}, {8245, 1},
1209 	{8246, 33808899}, {8247, 50586627}, {8248, 1}, {8252, 33810179},
1210 	{8253, 1}, {8254, 33810691}, {8255, 1}, {8263, 33811203},
1211 	{8264, 33811715}, {8265, 33812227}, {8266, 1}, {8279, 67362051},
1212 	{8280, 1}, {8287, 16783875}, {8288, 0}, {8289, 2},
1213 	{8292, 0}, {8293, 2}, {8304, 17035523}, {8305, 16779267},
1214 	{8306, 2}, {8308, 16787715}, {8309, 17035779}, {8310, 17036035},
1215 	{8311, 17036291}, {8312, 17036547}, {8313, 17036803}, {8314, 17037059},
1216 	{8315, 17037315}, {8316, 17037571}, {8317, 17037827}, {8318, 17038083},
1217 	{8319, 16780547}, {8320, 17035523}, {8321, 16786947}, {8322, 16785155},
1218 	{8323, 16785411}, {8324, 16787715}, {8325, 17035779}, {8326, 17036035},
1219 	{8327, 17036291}, {8328, 17036547}, {8329, 17036803}, {8330, 17037059},
1220 	{8331, 17037315}, {8332, 17037571}, {8333, 17037827}, {8334, 17038083},
1221 	{8335, 2}, {8336, 16777219}, {8337, 16778243}, {8338, 16780803},
1222 	{8339, 16783107}, {8340, 16816387}, {8341, 16779011}, {8342, 16779779},
1223 	{8343, 16780035}, {8344, 16780291}, {8345, 16780547}, {8346, 16781059},
1224 	{8347, 16781827}, {8348, 16782083}, {8349, 2}, {8352, 1},
1225 	{8360, 33558787}, {8361, 1}, {8385, 2}, {8400, 1},
1226 	{8433, 2}, {8448, 50592771}, {8449, 50593539}, {8450, 16777731},
1227 	{8451, 33817091}, {8452, 1}, {8453, 50594819}, {8454, 50595587},
1228 	{8455, 16816643}, {8456, 1}, {8457, 33819139}, {8458, 16778755},
1229 	{8459, 16779011}, {8463, 16802051}, {8464, 16779267}, {8466, 16780035},
1230 	{8468, 1}, {8469, 16780547}, {8470, 33557763}, {8471, 1},
1231 	{8473, 16781059}, {8474, 16781315}, {8475, 16781571}, {8478, 1},
1232 	{8480, 33819651}, {8481, 50597379}, {8482, 33820931}, {8483, 1},
1233 	{8484, 16783619}, {8485, 1}, {8486, 16857091}, {8487, 1},
1234 	{8488, 16783619}, {8489, 1}, {8490, 16779779}, {8491, 16790787},
1235 	{8492, 16777475}, {8493, 16777731}, {8494, 1}, {8495, 16778243},
1236 	{8497, 16778499}, {8498, 2}, {8499, 16780291}, {8500, 16780803},
1237 	{8501, 17044227}, {8502, 17044483}, {8503, 17044739}, {8504, 17044995},
1238 	{8505, 16779267}, {8506, 1}, {8507, 50599683}, {8508, 16855043},
1239 	{8509, 16852227}, {8511, 16855043}, {8512, 17046019}, {8513, 1},
1240 	{8517, 16777987}, {8519, 16778243}, {8520, 16779267}, {8521, 16779523},
1241 	{8522, 1}, {8528, 50600707}, {8529, 50601475}, {8530, 67379459},
1242 	{8531, 50603267}, {8532, 50604035}, {8533, 50604803}, {8534, 50605571},
1243 	{8535, 50606339}, {8536, 50607107}, {8537, 50607875}, {8538, 50608643},
1244 	{8539, 50609411}, {8540, 50610179}, {8541, 50610947}, {8542, 50611715},
1245 	{8543, 33564419}, {8544, 16779267}, {8545, 33835267}, {8546, 50612995},
1246 	{8547, 33836547}, {8548, 16782595}, {8549, 33837059}, {8550, 50614787},
1247 	{8551, 67392771}, {8552, 33839363}, {8553, 16783107}, {8554, 33839875},
1248 	{8555, 50617603}, {8556, 16780035}, {8557, 16777731}, {8558, 16777987},
1249 	{8559, 16780291}, {8560, 16779267}, {8561, 33835267}, {8562, 50612483},
1250 	{8563, 33836547}, {8564, 16782595}, {8565, 33837059}, {8566, 50614787},
1251 	{8567, 67392771}, {8568, 33839363}, {8569, 16783107}, {8570, 33839875},
1252 	{8571, 50617603}, {8572, 16780035}, {8573, 16777731}, {8574, 16777987},
1253 	{8575, 16780291}, {8576, 1}, {8579, 2}, {8580, 1},
1254 	{8585, 50618371}, {8586, 1}, {8588, 2}, {8592, 1},
1255 	{8748, 33841923}, {8749, 50619651}, {8750, 1}, {8751, 33843203},
1256 	{8752, 50620931}, {8753, 1}, {9001, 17067267}, {9002, 17067523},
1257 	{9003, 1}, {9255, 2}, {9280, 1}, {9291, 2},
1258 	{9312, 16786947}, {9313, 16785155}, {9314, 16785411}, {9315, 16787715},
1259 	{9316, 17035779}, {9317, 17036035}, {9318, 17036291}, {9319, 17036547},
1260 	{9320, 17036803}, {9321, 33825539}, {9322, 33564163}, {9323, 33844995},
1261 	{9324, 33845507}, {9325, 33846019}, {9326, 33846531}, {9327, 33847043},
1262 	{9328, 33847555}, {9329, 33848067}, {9330, 33848579}, {9331, 33849091},
1263 	{9332, 50626819}, {9333, 50627587}, {9334, 50628355}, {9335, 50629123},
1264 	{9336, 50629891}, {9337, 50630659}, {9338, 50631427}, {9339, 50632195},
1265 	{9340, 50632963}, {9341, 67410947}, {9342, 67411971}, {9343, 67412995},
1266 	{9344, 67414019}, {9345, 67415043}, {9346, 67416067}, {9347, 67417091},
1267 	{9348, 67418115}, {9349, 67419139}, {9350, 67420163}, {9351, 67421187},
1268 	{9352, 2}, {9372, 50644995}, {9373, 50645763}, {9374, 50646531},
1269 	{9375, 50647299}, {9376, 50648067}, {9377, 50648835}, {9378, 50649603},
1270 	{9379, 50650371}, {9380, 50651139}, {9381, 50651907}, {9382, 50652675},
1271 	{9383, 50653443}, {9384, 50654211}, {9385, 50654979}, {9386, 50655747},
1272 	{9387, 50656515}, {9388, 50657283}, {9389, 50658051}, {9390, 50658819},
1273 	{9391, 50659587}, {9392, 50660355}, {9393, 50661123}, {9394, 50661891},
1274 	{9395, 50662659}, {9396, 50663427}, {9397, 50664195}, {9398, 16777219},
1275 	{9399, 16777475}, {9400, 16777731}, {9401, 16777987}, {9402, 16778243},
1276 	{9403, 16778499}, {9404, 16778755}, {9405, 16779011}, {9406, 16779267},
1277 	{9407, 16779523}, {9408, 16779779}, {9409, 16780035}, {9410, 16780291},
1278 	{9411, 16780547}, {9412, 16780803}, {9413, 16781059}, {9414, 16781315},
1279 	{9415, 16781571}, {9416, 16781827}, {9417, 16782083}, {9418, 16782339},
1280 	{9419, 16782595}, {9420, 16782851}, {9421, 16783107}, {9422, 16783363},
1281 	{9423, 16783619}, {9424, 16777219}, {9425, 16777475}, {9426, 16777731},
1282 	{9427, 16777987}, {9428, 16778243}, {9429, 16778499}, {9430, 16778755},
1283 	{9431, 16779011}, {9432, 16779267}, {9433, 16779523}, {9434, 16779779},
1284 	{9435, 16780035}, {9436, 16780291}, {9437, 16780547}, {9438, 16780803},
1285 	{9439, 16781059}, {9440, 16781315}, {9441, 16781571}, {9442, 16781827},
1286 	{9443, 16782083}, {9444, 16782339}, {9445, 16782595}, {9446, 16782851},
1287 	{9447, 16783107}, {9448, 16783363}, {9449, 16783619}, {9450, 17035523},
1288 	{9451, 1}, {10764, 67396355}, {10765, 1}, {10868, 50664963},
1289 	{10869, 33888515}, {10870, 50665475}, {10871, 1}, {10972, 33889027},
1290 	{10973, 1}, {11124, 2}, {11126, 1}, {11158, 2},
1291 	{11159, 1}, {11264, 17112323}, {11265, 17112579}, {11266, 17112835},
1292 	{11267, 17113091}, {11268, 17113347}, {11269, 17113603}, {11270, 17113859},
1293 	{11271, 17114115}, {11272, 17114371}, {11273, 17114627}, {11274, 17114883},
1294 	{11275, 17115139}, {11276, 17115395}, {11277, 17115651}, {11278, 17115907},
1295 	{11279, 17116163}, {11280, 17116419}, {11281, 17116675}, {11282, 17116931},
1296 	{11283, 17117187}, {11284, 17117443}, {11285, 17117699}, {11286, 17117955},
1297 	{11287, 17118211}, {11288, 17118467}, {11289, 17118723}, {11290, 17118979},
1298 	{11291, 17119235}, {11292, 17119491}, {11293, 17119747}, {11294, 17120003},
1299 	{11295, 17120259}, {11296, 17120515}, {11297, 17120771}, {11298, 17121027},
1300 	{11299, 17121283}, {11300, 17121539}, {11301, 17121795}, {11302, 17122051},
1301 	{11303, 17122307}, {11304, 17122563}, {11305, 17122819}, {11306, 17123075},
1302 	{11307, 17123331}, {11308, 17123587}, {11309, 17123843}, {11310, 17124099},
1303 	{11311, 17124355}, {11312, 1}, {11360, 17124611}, {11361, 1},
1304 	{11362, 17124867}, {11363, 17125123}, {11364, 17125379}, {11365, 1},
1305 	{11367, 17125635}, {11368, 1}, {11369, 17125891}, {11370, 1},
1306 	{11371, 17126147}, {11372, 1}, {11373, 16948483}, {11374, 16953091},
1307 	{11375, 16948227}, {11376, 16950275}, {11377, 1}, {11378, 17126403},
1308 	{11379, 1}, {11381, 17126659}, {11382, 1}, {11388, 16779523},
1309 	{11389, 16782595}, {11390, 17126915}, {11391, 17127171}, {11392, 17127427},
1310 	{11393, 1}, {11394, 17127683}, {11395, 1}, {11396, 17127939},
1311 	{11397, 1}, {11398, 17128195}, {11399, 1}, {11400, 17128451},
1312 	{11401, 1}, {11402, 17128707}, {11403, 1}, {11404, 17128963},
1313 	{11405, 1}, {11406, 17129219}, {11407, 1}, {11408, 17129475},
1314 	{11409, 1}, {11410, 17129731}, {11411, 1}, {11412, 17129987},
1315 	{11413, 1}, {11414, 17130243}, {11415, 1}, {11416, 17130499},
1316 	{11417, 1}, {11418, 17130755}, {11419, 1}, {11420, 17131011},
1317 	{11421, 1}, {11422, 17131267}, {11423, 1}, {11424, 17131523},
1318 	{11425, 1}, {11426, 17131779}, {11427, 1}, {11428, 17132035},
1319 	{11429, 1}, {11430, 17132291}, {11431, 1}, {11432, 17132547},
1320 	{11433, 1}, {11434, 17132803}, {11435, 1}, {11436, 17133059},
1321 	{11437, 1}, {11438, 17133315}, {11439, 1}, {11440, 17133571},
1322 	{11441, 1}, {11442, 17133827}, {11443, 1}, {11444, 17134083},
1323 	{11445, 1}, {11446, 17134339}, {11447, 1}, {11448, 17134595},
1324 	{11449, 1}, {11450, 17134851}, {11451, 1}, {11452, 17135107},
1325 	{11453, 1}, {11454, 17135363}, {11455, 1}, {11456, 17135619},
1326 	{11457, 1}, {11458, 17135875}, {11459, 1}, {11460, 17136131},
1327 	{11461, 1}, {11462, 17136387}, {11463, 1}, {11464, 17136643},
1328 	{11465, 1}, {11466, 17136899}, {11467, 1}, {11468, 17137155},
1329 	{11469, 1}, {11470, 17137411}, {11471, 1}, {11472, 17137667},
1330 	{11473, 1}, {11474, 17137923}, {11475, 1}, {11476, 17138179},
1331 	{11477, 1}, {11478, 17138435}, {11479, 1}, {11480, 17138691},
1332 	{11481, 1}, {11482, 17138947}, {11483, 1}, {11484, 17139203},
1333 	{11485, 1}, {11486, 17139459}, {11487, 1}, {11488, 17139715},
1334 	{11489, 1}, {11490, 17139971}, {11491, 1}, {11499, 17140227},
1335 	{11500, 1}, {11501, 17140483}, {11502, 1}, {11506, 17140739},
1336 	{11507, 1}, {11508, 2}, {11513, 1}, {11558, 2},
1337 	{11559, 1}, {11560, 2}, {11565, 1}, {11566, 2},
1338 	{11568, 1}, {11624, 2}, {11631, 17140995}, {11632, 1},
1339 	{11633, 2}, {11647, 1}, {11671, 2}, {11680, 1},
1340 	{11687, 2}, {11688, 1}, {11695, 2}, {11696, 1},
1341 	{11703, 2}, {11704, 1}, {11711, 2}, {11712, 1},
1342 	{11719, 2}, {11720, 1}, {11727, 2}, {11728, 1},
1343 	{11735, 2}, {11736, 1}, {11743, 2}, {11744, 1},
1344 	{11870, 2}, {11904, 1}, {11930, 2}, {11931, 1},
1345 	{11935, 17141251}, {11936, 1}, {12019, 17141507}, {12020, 2},
1346 	{12032, 17141763}, {12033, 17142019}, {12034, 17142275}, {12035, 17142531},
1347 	{12036, 17142787}, {12037, 17143043}, {12038, 17143299}, {12039, 17143555},
1348 	{12040, 17143811}, {12041, 17144067}, {12042, 17144323}, {12043, 17144579},
1349 	{12044, 17144835}, {12045, 17145091}, {12046, 17145347}, {12047, 17145603},
1350 	{12048, 17145859}, {12049, 17146115}, {12050, 17146371}, {12051, 17146627},
1351 	{12052, 17146883}, {12053, 17147139}, {12054, 17147395}, {12055, 17147651},
1352 	{12056, 17147907}, {12057, 17148163}, {12058, 17148419}, {12059, 17148675},
1353 	{12060, 17148931}, {12061, 17149187}, {12062, 17149443}, {12063, 17149699},
1354 	{12064, 17149955}, {12065, 17150211}, {12066, 17150467}, {12067, 17150723},
1355 	{12068, 17150979}, {12069, 17151235}, {12070, 17151491}, {12071, 17151747},
1356 	{12072, 17152003}, {12073, 17152259}, {12074, 17152515}, {12075, 17152771},
1357 	{12076, 17153027}, {12077, 17153283}, {12078, 17153539}, {12079, 17153795},
1358 	{12080, 17154051}, {12081, 17154307}, {12082, 17154563}, {12083, 17154819},
1359 	{12084, 17155075}, {12085, 17155331}, {12086, 17155587}, {12087, 17155843},
1360 	{12088, 17156099}, {12089, 17156355}, {12090, 17156611}, {12091, 17156867},
1361 	{12092, 17157123}, {12093, 17157379}, {12094, 17157635}, {12095, 17157891},
1362 	{12096, 17158147}, {12097, 17158403}, {12098, 17158659}, {12099, 17158915},
1363 	{12100, 17159171}, {12101, 17159427}, {12102, 17159683}, {12103, 17159939},
1364 	{12104, 17160195}, {12105, 17160451}, {12106, 17160707}, {12107, 17160963},
1365 	{12108, 17161219}, {12109, 17161475}, {12110, 17161731}, {12111, 17161987},
1366 	{12112, 17162243}, {12113, 17162499}, {12114, 17162755}, {12115, 17163011},
1367 	{12116, 17163267}, {12117, 17163523}, {12118, 17163779}, {12119, 17164035},
1368 	{12120, 17164291}, {12121, 17164547}, {12122, 17164803}, {12123, 17165059},
1369 	{12124, 17165315}, {12125, 17165571}, {12126, 17165827}, {12127, 17166083},
1370 	{12128, 17166339}, {12129, 17166595}, {12130, 17166851}, {12131, 17167107},
1371 	{12132, 17167363}, {12133, 17167619}, {12134, 17167875}, {12135, 17168131},
1372 	{12136, 17168387}, {12137, 17168643}, {12138, 17168899}, {12139, 17169155},
1373 	{12140, 17169411}, {12141, 17169667}, {12142, 17169923}, {12143, 17170179},
1374 	{12144, 17170435}, {12145, 17170691}, {12146, 17170947}, {12147, 17171203},
1375 	{12148, 17171459}, {12149, 17171715}, {12150, 17171971}, {12151, 17172227},
1376 	{12152, 17172483}, {12153, 17172739}, {12154, 17172995}, {12155, 17173251},
1377 	{12156, 17173507}, {12157, 17173763}, {12158, 17174019}, {12159, 17174275},
1378 	{12160, 17174531}, {12161, 17174787}, {12162, 17175043}, {12163, 17175299},
1379 	{12164, 17175555}, {12165, 17175811}, {12166, 17176067}, {12167, 17176323},
1380 	{12168, 17176579}, {12169, 17176835}, {12170, 17177091}, {12171, 17177347},
1381 	{12172, 17177603}, {12173, 17177859}, {12174, 17178115}, {12175, 17178371},
1382 	{12176, 17178627}, {12177, 17178883}, {12178, 17179139}, {12179, 17179395},
1383 	{12180, 17179651}, {12181, 17179907}, {12182, 17180163}, {12183, 17180419},
1384 	{12184, 17180675}, {12185, 17180931}, {12186, 17181187}, {12187, 17181443},
1385 	{12188, 17181699}, {12189, 17181955}, {12190, 17182211}, {12191, 17182467},
1386 	{12192, 17182723}, {12193, 17182979}, {12194, 17183235}, {12195, 17183491},
1387 	{12196, 17183747}, {12197, 17184003}, {12198, 17184259}, {12199, 17184515},
1388 	{12200, 17184771}, {12201, 17185027}, {12202, 17185283}, {12203, 17185539},
1389 	{12204, 17185795}, {12205, 17186051}, {12206, 17186307}, {12207, 17186563},
1390 	{12208, 17186819}, {12209, 17187075}, {12210, 17187331}, {12211, 17187587},
1391 	{12212, 17187843}, {12213, 17188099}, {12214, 17188355}, {12215, 17188611},
1392 	{12216, 17188867}, {12217, 17189123}, {12218, 17189379}, {12219, 17189635},
1393 	{12220, 17189891}, {12221, 17190147}, {12222, 17190403}, {12223, 17190659},
1394 	{12224, 17190915}, {12225, 17191171}, {12226, 17191427}, {12227, 17191683},
1395 	{12228, 17191939}, {12229, 17192195}, {12230, 17192451}, {12231, 17192707},
1396 	{12232, 17192963}, {12233, 17193219}, {12234, 17193475}, {12235, 17193731},
1397 	{12236, 17193987}, {12237, 17194243}, {12238, 17194499}, {12239, 17194755},
1398 	{12240, 17195011}, {12241, 17195267}, {12242, 17195523}, {12243, 17195779},
1399 	{12244, 17196035}, {12245, 17196291}, {12246, 2}, {12288, 16783875},
1400 	{12289, 1}, {12290, 17196547}, {12291, 1}, {12342, 17196803},
1401 	{12343, 1}, {12344, 17147651}, {12345, 17197059}, {12346, 17197315},
1402 	{12347, 1}, {12352, 2}, {12353, 1}, {12439, 2},
1403 	{12441, 1}, {12443, 33974787}, {12444, 33975299}, {12445, 1},
1404 	{12447, 33975811}, {12448, 1}, {12543, 33976323}, {12544, 2},
1405 	{12549, 1}, {12592, 2}, {12593, 17199619}, {12594, 17199875},
1406 	{12595, 17200131}, {12596, 17200387}, {12597, 17200643}, {12598, 17200899},
1407 	{12599, 17201155}, {12600, 17201411}, {12601, 17201667}, {12602, 17201923},
1408 	{12603, 17202179}, {12604, 17202435}, {12605, 17202691}, {12606, 17202947},
1409 	{12607, 17203203}, {12608, 17203459}, {12609, 17203715}, {12610, 17203971},
1410 	{12611, 17204227}, {12612, 17204483}, {12613, 17204739}, {12614, 17204995},
1411 	{12615, 17205251}, {12616, 17205507}, {12617, 17205763}, {12618, 17206019},
1412 	{12619, 17206275}, {12620, 17206531}, {12621, 17206787}, {12622, 17207043},
1413 	{12623, 17207299}, {12624, 17207555}, {12625, 17207811}, {12626, 17208067},
1414 	{12627, 17208323}, {12628, 17208579}, {12629, 17208835}, {12630, 17209091},
1415 	{12631, 17209347}, {12632, 17209603}, {12633, 17209859}, {12634, 17210115},
1416 	{12635, 17210371}, {12636, 17210627}, {12637, 17210883}, {12638, 17211139},
1417 	{12639, 17211395}, {12640, 17211651}, {12641, 17211907}, {12642, 17212163},
1418 	{12643, 17212419}, {12644, 2}, {12645, 17212675}, {12646, 17212931},
1419 	{12647, 17213187}, {12648, 17213443}, {12649, 17213699}, {12650, 17213955},
1420 	{12651, 17214211}, {12652, 17214467}, {12653, 17214723}, {12654, 17214979},
1421 	{12655, 17215235}, {12656, 17215491}, {12657, 17215747}, {12658, 17216003},
1422 	{12659, 17216259}, {12660, 17216515}, {12661, 17216771}, {12662, 17217027},
1423 	{12663, 17217283}, {12664, 17217539}, {12665, 17217795}, {12666, 17218051},
1424 	{12667, 17218307}, {12668, 17218563}, {12669, 17218819}, {12670, 17219075},
1425 	{12671, 17219331}, {12672, 17219587}, {12673, 17219843}, {12674, 17220099},
1426 	{12675, 17220355}, {12676, 17220611}, {12677, 17220867}, {12678, 17221123},
1427 	{12679, 17221379}, {12680, 17221635}, {12681, 17221891}, {12682, 17222147},
1428 	{12683, 17222403}, {12684, 17222659}, {12685, 17222915}, {12686, 17223171},
1429 	{12687, 2}, {12688, 1}, {12690, 17141763}, {12691, 17143299},
1430 	{12692, 17223427}, {12693, 17223683}, {12694, 17223939}, {12695, 17224195},
1431 	{12696, 17224451}, {12697, 17224707}, {12698, 17142787}, {12699, 17224963},
1432 	{12700, 17225219}, {12701, 17225475}, {12702, 17225731}, {12703, 17143811},
1433 	{12704, 1}, {12772, 2}, {12784, 1}, {12800, 50780419},
1434 	{12801, 50781187}, {12802, 50781955}, {12803, 50782723}, {12804, 50783491},
1435 	{12805, 50784259}, {12806, 50785027}, {12807, 50785795}, {12808, 50786563},
1436 	{12809, 50787331}, {12810, 50788099}, {12811, 50788867}, {12812, 50789635},
1437 	{12813, 50790403}, {12814, 50791171}, {12815, 50791939}, {12816, 50792707},
1438 	{12817, 50793475}, {12818, 50794243}, {12819, 50795011}, {12820, 50795779},
1439 	{12821, 50796547}, {12822, 50797315}, {12823, 50798083}, {12824, 50798851},
1440 	{12825, 50799619}, {12826, 50800387}, {12827, 50801155}, {12828, 50801923},
1441 	{12829, 67579907}, {12830, 67580931}, {12831, 2}, {12832, 50804739},
1442 	{12833, 50805507}, {12834, 50806275}, {12835, 50807043}, {12836, 50807811},
1443 	{12837, 50808579}, {12838, 50809347}, {12839, 50810115}, {12840, 50810883},
1444 	{12841, 50811651}, {12842, 50812419}, {12843, 50813187}, {12844, 50813955},
1445 	{12845, 50814723}, {12846, 50815491}, {12847, 50816259}, {12848, 50817027},
1446 	{12849, 50817795}, {12850, 50818563}, {12851, 50819331}, {12852, 50820099},
1447 	{12853, 50820867}, {12854, 50821635}, {12855, 50822403}, {12856, 50823171},
1448 	{12857, 50823939}, {12858, 50824707}, {12859, 50825475}, {12860, 50826243},
1449 	{12861, 50827011}, {12862, 50827779}, {12863, 50828547}, {12864, 50829315},
1450 	{12865, 50830083}, {12866, 50830851}, {12867, 50831619}, {12868, 17277955},
1451 	{12869, 17278211}, {12870, 17158659}, {12871, 17278467}, {12872, 1},
1452 	{12880, 50833155}, {12881, 33845251}, {12882, 34056707}, {12883, 33562371},
1453 	{12884, 34057219}, {12885, 34057731}, {12886, 34058243}, {12887, 34058755},
1454 	{12888, 34059267}, {12889, 34059779}, {12890, 34060291}, {12891, 33827331},
1455 	{12892, 33826563}, {12893, 34060803}, {12894, 34061315}, {12895, 34061827},
1456 	{12896, 17199619}, {12897, 17200387}, {12898, 17201155}, {12899, 17201667},
1457 	{12900, 17203715}, {12901, 17203971}, {12902, 17204739}, {12903, 17205251},
1458 	{12904, 17205507}, {12905, 17206019}, {12906, 17206275}, {12907, 17206531},
1459 	{12908, 17206787}, {12909, 17207043}, {12910, 17236995}, {12911, 17237763},
1460 	{12912, 17238531}, {12913, 17239299}, {12914, 17240067}, {12915, 17240835},
1461 	{12916, 17241603}, {12917, 17242371}, {12918, 17243139}, {12919, 17243907},
1462 	{12920, 17244675}, {12921, 17245443}, {12922, 17246211}, {12923, 17246979},
1463 	{12924, 34062339}, {12925, 34062851}, {12926, 17286147}, {12927, 1},
1464 	{12928, 17141763}, {12929, 17143299}, {12930, 17223427}, {12931, 17223683},
1465 	{12932, 17253635}, {12933, 17254403}, {12934, 17255171}, {12935, 17144579},
1466 	{12936, 17256707}, {12937, 17147651}, {12938, 17160451}, {12939, 17163523},
1467 	{12940, 17163267}, {12941, 17160707}, {12942, 17184259}, {12943, 17149699},
1468 	{12944, 17159939}, {12945, 17263619}, {12946, 17264387}, {12947, 17265155},
1469 	{12948, 17265923}, {12949, 17266691}, {12950, 17267459}, {12951, 17268227},
1470 	{12952, 17268995}, {12953, 17286403}, {12954, 17286659}, {12955, 17151235},
1471 	{12956, 17286915}, {12957, 17287171}, {12958, 17287427}, {12959, 17287683},
1472 	{12960, 17287939}, {12961, 17275907}, {12962, 17288195}, {12963, 17288451},
1473 	{12964, 17223939}, {12965, 17224195}, {12966, 17224451}, {12967, 17288707},
1474 	{12968, 17288963}, {12969, 17289219}, {12970, 17289475}, {12971, 17271299},
1475 	{12972, 17272067}, {12973, 17272835}, {12974, 17273603}, {12975, 17274371},
1476 	{12976, 17289731}, {12977, 34067203}, {12978, 34067715}, {12979, 34068227},
1477 	{12980, 34068739}, {12981, 34069251}, {12982, 33564931}, {12983, 34057475},
1478 	{12984, 34061571}, {12985, 34069763}, {12986, 34070275}, {12987, 34070787},
1479 	{12988, 34071299}, {12989, 34071811}, {12990, 34072323}, {12991, 34072835},
1480 	{12992, 34073347}, {12993, 34073859}, {12994, 34074371}, {12995, 34074883},
1481 	{12996, 34075395}, {12997, 34075907}, {12998, 34076419}, {12999, 34076931},
1482 	{13000, 34077443}, {13001, 50855171}, {13002, 50855939}, {13003, 50856707},
1483 	{13004, 34080259}, {13005, 50857987}, {13006, 34081539}, {13007, 50859267},
1484 	{13008, 17305603}, {13009, 17305859}, {13010, 17306115}, {13011, 17306371},
1485 	{13012, 17306627}, {13013, 17306883}, {13014, 17307139}, {13015, 17307395},
1486 	{13016, 17307651}, {13017, 17199107}, {13018, 17307907}, {13019, 17308163},
1487 	{13020, 17308419}, {13021, 17308675}, {13022, 17308931}, {13023, 17309187},
1488 	{13024, 17309443}, {13025, 17309699}, {13026, 17309955}, {13027, 17199363},
1489 	{13028, 17310211}, {13029, 17310467}, {13030, 17310723}, {13031, 17310979},
1490 	{13032, 17311235}, {13033, 17311491}, {13034, 17311747}, {13035, 17312003},
1491 	{13036, 17312259}, {13037, 17312515}, {13038, 17312771}, {13039, 17313027},
1492 	{13040, 17313283}, {13041, 17313539}, {13042, 17313795}, {13043, 17314051},
1493 	{13044, 17314307}, {13045, 17314563}, {13046, 17314819}, {13047, 17315075},
1494 	{13048, 17315331}, {13049, 17315587}, {13050, 17315843}, {13051, 17316099},
1495 	{13052, 17316355}, {13053, 17316611}, {13054, 17316867}, {13055, 34094339},
1496 	{13056, 67649283}, {13057, 67650307}, {13058, 67651331}, {13059, 50875139},
1497 	{13060, 67653123}, {13061, 50876931}, {13062, 50877699}, {13063, 84432899},
1498 	{13064, 67656963}, {13065, 50880771}, {13066, 50881539}, {13067, 50882307},
1499 	{13068, 67660291}, {13069, 67661315}, {13070, 50885123}, {13071, 50885891},
1500 	{13072, 34109443}, {13073, 50887171}, {13074, 67665155}, {13075, 67666179},
1501 	{13076, 34112771}, {13077, 84444931}, {13078, 101223427}, {13079, 84447747},
1502 	{13080, 50891011}, {13081, 84449027}, {13082, 84450307}, {13083, 67674371},
1503 	{13084, 50898179}, {13085, 50898947}, {13086, 50899715}, {13087, 67677699},
1504 	{13088, 84455939}, {13089, 67680003}, {13090, 50903811}, {13091, 50904579},
1505 	{13092, 50905347}, {13093, 34128899}, {13094, 34129411}, {13095, 34118147},
1506 	{13096, 34129923}, {13097, 50907651}, {13098, 50908419}, {13099, 84463619},
1507 	{13100, 50910467}, {13101, 67688451}, {13102, 84466691}, {13103, 50913539},
1508 	{13104, 34137091}, {13105, 34137603}, {13106, 84469763}, {13107, 67693827},
1509 	{13108, 84472067}, {13109, 50918915}, {13110, 84474115}, {13111, 34143747},
1510 	{13112, 50921475}, {13113, 50922243}, {13114, 50923011}, {13115, 50923779},
1511 	{13116, 50924547}, {13117, 67702531}, {13118, 50926339}, {13119, 34149891},
1512 	{13120, 50927619}, {13121, 50928387}, {13122, 50929155}, {13123, 67707139},
1513 	{13124, 50930947}, {13125, 50931715}, {13126, 50932483}, {13127, 84487683},
1514 	{13128, 67711747}, {13129, 34158339}, {13130, 84490499}, {13131, 34160131},
1515 	{13132, 67715075}, {13133, 67669507}, {13134, 50938883}, {13135, 50939651},
1516 	{13136, 50940419}, {13137, 67718403}, {13138, 34164995}, {13139, 50942723},
1517 	{13140, 67720707}, {13141, 34167299}, {13142, 84499459}, {13143, 50893827},
1518 	{13144, 34169091}, {13145, 34169603}, {13146, 34170115}, {13147, 34170627},
1519 	{13148, 34171139}, {13149, 34171651}, {13150, 34172163}, {13151, 34172675},
1520 	{13152, 34173187}, {13153, 34173699}, {13154, 50951427}, {13155, 50952195},
1521 	{13156, 50952963}, {13157, 50953731}, {13158, 50954499}, {13159, 50955267},
1522 	{13160, 50956035}, {13161, 50956803}, {13162, 50957571}, {13163, 50958339},
1523 	{13164, 50959107}, {13165, 50959875}, {13166, 50960643}, {13167, 50961411},
1524 	{13168, 50962179}, {13169, 50962947}, {13170, 34186499}, {13171, 34187011},
1525 	{13172, 50964739}, {13173, 34188291}, {13174, 34188803}, {13175, 34189315},
1526 	{13176, 50967043}, {13177, 50967811}, {13178, 34191363}, {13179, 34191875},
1527 	{13180, 34192387}, {13181, 34192899}, {13182, 34193411}, {13183, 67748355},
1528 	{13184, 34185987}, {13185, 34194947}, {13186, 34195459}, {13187, 34195971},
1529 	{13188, 34196483}, {13189, 34196995}, {13190, 34197507}, {13191, 34198019},
1530 	{13192, 50975747}, {13193, 67753731}, {13194, 34200323}, {13195, 34200835},
1531 	{13196, 34201347}, {13197, 34201859}, {13198, 34202371}, {13199, 34202883},
1532 	{13200, 34203395}, {13201, 50981123}, {13202, 50981891}, {13203, 50980355},
1533 	{13204, 50982659}, {13205, 34206211}, {13206, 34206723}, {13207, 34207235},
1534 	{13208, 33556995}, {13209, 34207747}, {13210, 34208259}, {13211, 34208771},
1535 	{13212, 34209283}, {13213, 34209795}, {13214, 34210307}, {13215, 50988035},
1536 	{13216, 50988803}, {13217, 34190083}, {13218, 50989571}, {13219, 50990339},
1537 	{13220, 50991107}, {13221, 34190851}, {13222, 50991875}, {13223, 50992643},
1538 	{13224, 67770627}, {13225, 34185987}, {13226, 50994435}, {13227, 50995203},
1539 	{13228, 50995971}, {13229, 50996739}, {13230, 84551939}, {13231, 101330435},
1540 	{13232, 34223107}, {13233, 34223619}, {13234, 34224131}, {13235, 34224643},
1541 	{13236, 34225155}, {13237, 34225667}, {13238, 34226179}, {13239, 34226691},
1542 	{13240, 34227203}, {13241, 34226691}, {13242, 34227715}, {13243, 34228227},
1543 	{13244, 34228739}, {13245, 34229251}, {13246, 34229763}, {13247, 34229251},
1544 	{13248, 34230275}, {13249, 34230787}, {13250, 2}, {13251, 34231299},
1545 	{13252, 33817347}, {13253, 33554947}, {13254, 67786243}, {13255, 2},
1546 	{13256, 34232835}, {13257, 34233347}, {13258, 34233859}, {13259, 34185731},
1547 	{13260, 34234371}, {13261, 34234883}, {13262, 34210307}, {13263, 34235395},
1548 	{13264, 33557251}, {13265, 34235907}, {13266, 51013635}, {13267, 34237187},
1549 	{13268, 34197507}, {13269, 51014915}, {13270, 51015683}, {13271, 34239235},
1550 	{13272, 2}, {13273, 51016963}, {13274, 34240515}, {13275, 34221315},
1551 	{13276, 34241027}, {13277, 34241539}, {13278, 51019267}, {13279, 51020035},
1552 	{13280, 34243587}, {13281, 34244099}, {13282, 34244611}, {13283, 34245123},
1553 	{13284, 34245635}, {13285, 34246147}, {13286, 34246659}, {13287, 34247171},
1554 	{13288, 34247683}, {13289, 51025411}, {13290, 51026179}, {13291, 51026947},
1555 	{13292, 51027715}, {13293, 51028483}, {13294, 51029251}, {13295, 51030019},
1556 	{13296, 51030787}, {13297, 51031555}, {13298, 51032323}, {13299, 51033091},
1557 	{13300, 51033859}, {13301, 51034627}, {13302, 51035395}, {13303, 51036163},
1558 	{13304, 51036931}, {13305, 51037699}, {13306, 51038467}, {13307, 51039235},
1559 	{13308, 51040003}, {13309, 51040771}, {13310, 51041539}, {13311, 51042307},
1560 	{13312, 1}, {42125, 2}, {42128, 1}, {42183, 2},
1561 	{42192, 1}, {42540, 2}, {42560, 17488643}, {42561, 1},
1562 	{42562, 17488899}, {42563, 1}, {42564, 17489155}, {42565, 1},
1563 	{42566, 17489411}, {42567, 1}, {42568, 17489667}, {42569, 1},
1564 	{42570, 16936451}, {42571, 1}, {42572, 17489923}, {42573, 1},
1565 	{42574, 17490179}, {42575, 1}, {42576, 17490435}, {42577, 1},
1566 	{42578, 17490691}, {42579, 1}, {42580, 17490947}, {42581, 1},
1567 	{42582, 17491203}, {42583, 1}, {42584, 17491459}, {42585, 1},
1568 	{42586, 17491715}, {42587, 1}, {42588, 17491971}, {42589, 1},
1569 	{42590, 17492227}, {42591, 1}, {42592, 17492483}, {42593, 1},
1570 	{42594, 17492739}, {42595, 1}, {42596, 17492995}, {42597, 1},
1571 	{42598, 17493251}, {42599, 1}, {42600, 17493507}, {42601, 1},
1572 	{42602, 17493763}, {42603, 1}, {42604, 17494019}, {42605, 1},
1573 	{42624, 17494275}, {42625, 1}, {42626, 17494531}, {42627, 1},
1574 	{42628, 17494787}, {42629, 1}, {42630, 17495043}, {42631, 1},
1575 	{42632, 17495299}, {42633, 1}, {42634, 17495555}, {42635, 1},
1576 	{42636, 17495811}, {42637, 1}, {42638, 17496067}, {42639, 1},
1577 	{42640, 17496323}, {42641, 1}, {42642, 17496579}, {42643, 1},
1578 	{42644, 17496835}, {42645, 1}, {42646, 17497091}, {42647, 1},
1579 	{42648, 17497347}, {42649, 1}, {42650, 17497603}, {42651, 1},
1580 	{42652, 16873219}, {42653, 16873731}, {42654, 1}, {42744, 2},
1581 	{42752, 1}, {42786, 17497859}, {42787, 1}, {42788, 17498115},
1582 	{42789, 1}, {42790, 17498371}, {42791, 1}, {42792, 17498627},
1583 	{42793, 1}, {42794, 17498883}, {42795, 1}, {42796, 17499139},
1584 	{42797, 1}, {42798, 17499395}, {42799, 1}, {42802, 17499651},
1585 	{42803, 1}, {42804, 17499907}, {42805, 1}, {42806, 17500163},
1586 	{42807, 1}, {42808, 17500419}, {42809, 1}, {42810, 17500675},
1587 	{42811, 1}, {42812, 17500931}, {42813, 1}, {42814, 17501187},
1588 	{42815, 1}, {42816, 17501443}, {42817, 1}, {42818, 17501699},
1589 	{42819, 1}, {42820, 17501955}, {42821, 1}, {42822, 17502211},
1590 	{42823, 1}, {42824, 17502467}, {42825, 1}, {42826, 17502723},
1591 	{42827, 1}, {42828, 17502979}, {42829, 1}, {42830, 17503235},
1592 	{42831, 1}, {42832, 17503491}, {42833, 1}, {42834, 17503747},
1593 	{42835, 1}, {42836, 17504003}, {42837, 1}, {42838, 17504259},
1594 	{42839, 1}, {42840, 17504515}, {42841, 1}, {42842, 17504771},
1595 	{42843, 1}, {42844, 17505027}, {42845, 1}, {42846, 17505283},
1596 	{42847, 1}, {42848, 17505539}, {42849, 1}, {42850, 17505795},
1597 	{42851, 1}, {42852, 17506051}, {42853, 1}, {42854, 17506307},
1598 	{42855, 1}, {42856, 17506563}, {42857, 1}, {42858, 17506819},
1599 	{42859, 1}, {42860, 17507075}, {42861, 1}, {42862, 17507331},
1600 	{42863, 1}, {42864, 17507331}, {42865, 1}, {42873, 17507587},
1601 	{42874, 1}, {42875, 17507843}, {42876, 1}, {42877, 17508099},
1602 	{42878, 17508355}, {42879, 1}, {42880, 17508611}, {42881, 1},
1603 	{42882, 17508867}, {42883, 1}, {42884, 17509123}, {42885, 1},
1604 	{42886, 17509379}, {42887, 1}, {42891, 17509635}, {42892, 1},
1605 	{42893, 16951299}, {42894, 1}, {42896, 17509891}, {42897, 1},
1606 	{42898, 17510147}, {42899, 1}, {42902, 17510403}, {42903, 1},
1607 	{42904, 17510659}, {42905, 1}, {42906, 17510915}, {42907, 1},
1608 	{42908, 17511171}, {42909, 1}, {42910, 17511427}, {42911, 1},
1609 	{42912, 17511683}, {42913, 1}, {42914, 17511939}, {42915, 1},
1610 	{42916, 17512195}, {42917, 1}, {42918, 17512451}, {42919, 1},
1611 	{42920, 17512707}, {42921, 1}, {42922, 16841475}, {42923, 16948995},
1612 	{42924, 16951043}, {42925, 17512963}, {42926, 16951555}, {42927, 1},
1613 	{42928, 17513219}, {42929, 17513475}, {42930, 16952067}, {42931, 17513731},
1614 	{42932, 17513987}, {42933, 1}, {42934, 17514243}, {42935, 1},
1615 	{42936, 17514499}, {42937, 1}, {42938, 17514755}, {42939, 1},
1616 	{42940, 17515011}, {42941, 1}, {42942, 17515267}, {42943, 1},
1617 	{42944, 17515523}, {42945, 1}, {42946, 17515779}, {42947, 1},
1618 	{42948, 17516035}, {42949, 16954371}, {42950, 17516291}, {42951, 17516547},
1619 	{42952, 1}, {42953, 17516803}, {42954, 1}, {42955, 2},
1620 	{42960, 17517059}, {42961, 1}, {42962, 2}, {42963, 1},
1621 	{42964, 2}, {42965, 1}, {42966, 17517315}, {42967, 1},
1622 	{42968, 17517571}, {42969, 1}, {42970, 2}, {42994, 16777731},
1623 	{42995, 16778499}, {42996, 16781315}, {42997, 17517827}, {42998, 1},
1624 	{43000, 16802051}, {43001, 16808195}, {43002, 1}, {43053, 2},
1625 	{43056, 1}, {43066, 2}, {43072, 1}, {43128, 2},
1626 	{43136, 1}, {43206, 2}, {43214, 1}, {43226, 2},
1627 	{43232, 1}, {43348, 2}, {43359, 1}, {43389, 2},
1628 	{43392, 1}, {43470, 2}, {43471, 1}, {43482, 2},
1629 	{43486, 1}, {43519, 2}, {43520, 1}, {43575, 2},
1630 	{43584, 1}, {43598, 2}, {43600, 1}, {43610, 2},
1631 	{43612, 1}, {43715, 2}, {43739, 1}, {43767, 2},
1632 	{43777, 1}, {43783, 2}, {43785, 1}, {43791, 2},
1633 	{43793, 1}, {43799, 2}, {43808, 1}, {43815, 2},
1634 	{43816, 1}, {43823, 2}, {43824, 1}, {43868, 17498371},
1635 	{43869, 17518083}, {43870, 17124867}, {43871, 17518339}, {43872, 1},
1636 	{43881, 17518595}, {43882, 1}, {43884, 2}, {43888, 17518851},
1637 	{43889, 17519107}, {43890, 17519363}, {43891, 17519619}, {43892, 17519875},
1638 	{43893, 17520131}, {43894, 17520387}, {43895, 17520643}, {43896, 17520899},
1639 	{43897, 17521155}, {43898, 17521411}, {43899, 17521667}, {43900, 17521923},
1640 	{43901, 17522179}, {43902, 17522435}, {43903, 17522691}, {43904, 17522947},
1641 	{43905, 17523203}, {43906, 17523459}, {43907, 17523715}, {43908, 17523971},
1642 	{43909, 17524227}, {43910, 17524483}, {43911, 17524739}, {43912, 17524995},
1643 	{43913, 17525251}, {43914, 17525507}, {43915, 17525763}, {43916, 17526019},
1644 	{43917, 17526275}, {43918, 17526531}, {43919, 17526787}, {43920, 17527043},
1645 	{43921, 17527299}, {43922, 17527555}, {43923, 17527811}, {43924, 17528067},
1646 	{43925, 17528323}, {43926, 17528579}, {43927, 17528835}, {43928, 17529091},
1647 	{43929, 17529347}, {43930, 17529603}, {43931, 17529859}, {43932, 17530115},
1648 	{43933, 17530371}, {43934, 17530627}, {43935, 17530883}, {43936, 17531139},
1649 	{43937, 17531395}, {43938, 17531651}, {43939, 17531907}, {43940, 17532163},
1650 	{43941, 17532419}, {43942, 17532675}, {43943, 17532931}, {43944, 17533187},
1651 	{43945, 17533443}, {43946, 17533699}, {43947, 17533955}, {43948, 17534211},
1652 	{43949, 17534467}, {43950, 17534723}, {43951, 17534979}, {43952, 17535235},
1653 	{43953, 17535491}, {43954, 17535747}, {43955, 17536003}, {43956, 17536259},
1654 	{43957, 17536515}, {43958, 17536771}, {43959, 17537027}, {43960, 17537283},
1655 	{43961, 17537539}, {43962, 17537795}, {43963, 17538051}, {43964, 17538307},
1656 	{43965, 17538563}, {43966, 17538819}, {43967, 17539075}, {43968, 1},
1657 	{44014, 2}, {44016, 1}, {44026, 2}, {44032, 1},
1658 	{55204, 2}, {55216, 1}, {55239, 2}, {55243, 1},
1659 	{55292, 2}, {63744, 17539331}, {63745, 17539587}, {63746, 17182211},
1660 	{63747, 17539843}, {63748, 17540099}, {63749, 17540355}, {63750, 17540611},
1661 	{63751, 17196035}, {63753, 17540867}, {63754, 17184259}, {63755, 17541123},
1662 	{63756, 17541379}, {63757, 17541635}, {63758, 17541891}, {63759, 17542147},
1663 	{63760, 17542403}, {63761, 17542659}, {63762, 17542915}, {63763, 17543171},
1664 	{63764, 17543427}, {63765, 17543683}, {63766, 17543939}, {63767, 17544195},
1665 	{63768, 17544451}, {63769, 17544707}, {63770, 17544963}, {63771, 17545219},
1666 	{63772, 17545475}, {63773, 17545731}, {63774, 17545987}, {63775, 17546243},
1667 	{63776, 17546499}, {63777, 17546755}, {63778, 17547011}, {63779, 17547267},
1668 	{63780, 17547523}, {63781, 17547779}, {63782, 17548035}, {63783, 17548291},
1669 	{63784, 17548547}, {63785, 17548803}, {63786, 17549059}, {63787, 17549315},
1670 	{63788, 17549571}, {63789, 17549827}, {63790, 17550083}, {63791, 17550339},
1671 	{63792, 17550595}, {63793, 17550851}, {63794, 17551107}, {63795, 17551363},
1672 	{63796, 17173507}, {63797, 17551619}, {63798, 17551875}, {63799, 17552131},
1673 	{63800, 17552387}, {63801, 17552643}, {63802, 17552899}, {63803, 17553155},
1674 	{63804, 17553411}, {63805, 17553667}, {63806, 17553923}, {63807, 17554179},
1675 	{63808, 17192195}, {63809, 17554435}, {63810, 17554691}, {63811, 17554947},
1676 	{63812, 17555203}, {63813, 17555459}, {63814, 17555715}, {63815, 17555971},
1677 	{63816, 17556227}, {63817, 17556483}, {63818, 17556739}, {63819, 17556995},
1678 	{63820, 17557251}, {63821, 17557507}, {63822, 17557763}, {63823, 17558019},
1679 	{63824, 17558275}, {63825, 17558531}, {63826, 17558787}, {63827, 17559043},
1680 	{63828, 17559299}, {63829, 17559555}, {63830, 17559811}, {63831, 17560067},
1681 	{63832, 17560323}, {63833, 17560579}, {63834, 17560835}, {63835, 17561091},
1682 	{63836, 17543427}, {63837, 17561347}, {63838, 17561603}, {63839, 17561859},
1683 	{63840, 17562115}, {63841, 17562371}, {63842, 17562627}, {63843, 17562883},
1684 	{63844, 17563139}, {63845, 17563395}, {63846, 17563651}, {63847, 17563907},
1685 	{63848, 17564163}, {63849, 17564419}, {63850, 17564675}, {63851, 17564931},
1686 	{63852, 17565187}, {63853, 17565443}, {63854, 17565699}, {63855, 17565955},
1687 	{63856, 17566211}, {63857, 17182723}, {63858, 17566467}, {63859, 17566723},
1688 	{63860, 17566979}, {63861, 17567235}, {63862, 17567491}, {63863, 17567747},
1689 	{63864, 17568003}, {63865, 17568259}, {63866, 17568515}, {63867, 17568771},
1690 	{63868, 17569027}, {63869, 17569283}, {63870, 17569539}, {63871, 17569795},
1691 	{63872, 17570051}, {63873, 17151235}, {63874, 17570307}, {63875, 17570563},
1692 	{63876, 17570819}, {63877, 17571075}, {63878, 17571331}, {63879, 17571587},
1693 	{63880, 17571843}, {63881, 17572099}, {63882, 17146371}, {63883, 17572355},
1694 	{63884, 17572611}, {63885, 17572867}, {63886, 17573123}, {63887, 17573379},
1695 	{63888, 17573635}, {63889, 17573891}, {63890, 17574147}, {63891, 17574403},
1696 	{63892, 17574659}, {63893, 17574915}, {63894, 17575171}, {63895, 17575427},
1697 	{63896, 17575683}, {63897, 17575939}, {63898, 17576195}, {63899, 17576451},
1698 	{63900, 17576707}, {63901, 17576963}, {63902, 17577219}, {63903, 17577475},
1699 	{63904, 17577731}, {63905, 17565955}, {63906, 17577987}, {63907, 17578243},
1700 	{63908, 17578499}, {63909, 17578755}, {63910, 17579011}, {63911, 17579267},
1701 	{63912, 17317123}, {63913, 17579523}, {63914, 17561859}, {63915, 17579779},
1702 	{63916, 17580035}, {63917, 17580291}, {63918, 17580547}, {63919, 17580803},
1703 	{63920, 17581059}, {63921, 17581315}, {63922, 17581571}, {63923, 17581827},
1704 	{63924, 17582083}, {63925, 17582339}, {63926, 17582595}, {63927, 17582851},
1705 	{63928, 17583107}, {63929, 17583363}, {63930, 17583619}, {63931, 17583875},
1706 	{63932, 17584131}, {63933, 17584387}, {63934, 17584643}, {63935, 17543427},
1707 	{63936, 17584899}, {63937, 17585155}, {63938, 17585411}, {63939, 17585667},
1708 	{63940, 17195779}, {63941, 17585923}, {63942, 17586179}, {63943, 17586435},
1709 	{63944, 17586691}, {63945, 17586947}, {63946, 17587203}, {63947, 17587459},
1710 	{63948, 17587715}, {63949, 17587971}, {63950, 17588227}, {63951, 17588483},
1711 	{63952, 17588739}, {63953, 17254403}, {63954, 17588995}, {63955, 17589251},
1712 	{63956, 17589507}, {63957, 17589763}, {63958, 17590019}, {63959, 17590275},
1713 	{63960, 17590531}, {63961, 17590787}, {63962, 17591043}, {63963, 17562371},
1714 	{63964, 17591299}, {63965, 17591555}, {63966, 17591811}, {63967, 17592067},
1715 	{63968, 17592323}, {63969, 17592579}, {63970, 17592835}, {63971, 17593091},
1716 	{63972, 17593347}, {63973, 17593603}, {63974, 17593859}, {63975, 17594115},
1717 	{63976, 17594371}, {63977, 17184003}, {63978, 17594627}, {63979, 17594883},
1718 	{63980, 17595139}, {63981, 17595395}, {63982, 17595651}, {63983, 17595907},
1719 	{63984, 17596163}, {63985, 17596419}, {63986, 17596675}, {63987, 17596931},
1720 	{63988, 17597187}, {63989, 17597443}, {63990, 17597699}, {63991, 17171459},
1721 	{63992, 17597955}, {63993, 17598211}, {63994, 17598467}, {63995, 17598723},
1722 	{63996, 17598979}, {63997, 17599235}, {63998, 17599491}, {63999, 17599747},
1723 	{64000, 17600003}, {64001, 17600259}, {64002, 17600515}, {64003, 17600771},
1724 	{64004, 17601027}, {64005, 17601283}, {64006, 17601539}, {64007, 17601795},
1725 	{64008, 17178371}, {64009, 17602051}, {64010, 17179139}, {64011, 17602307},
1726 	{64012, 17602563}, {64013, 17602819}, {64014, 1}, {64016, 17603075},
1727 	{64017, 1}, {64018, 17603331}, {64019, 1}, {64021, 17603587},
1728 	{64022, 17603843}, {64023, 17604099}, {64024, 17604355}, {64025, 17604611},
1729 	{64026, 17604867}, {64027, 17605123}, {64028, 17605379}, {64029, 17605635},
1730 	{64030, 17173251}, {64031, 1}, {64032, 17605891}, {64033, 1},
1731 	{64034, 17606147}, {64035, 1}, {64037, 17606403}, {64038, 17606659},
1732 	{64039, 1}, {64042, 17606915}, {64043, 17607171}, {64044, 17607427},
1733 	{64045, 17607683}, {64046, 17607939}, {64047, 17608195}, {64048, 17608451},
1734 	{64049, 17608707}, {64050, 17608963}, {64051, 17609219}, {64052, 17609475},
1735 	{64053, 17609731}, {64054, 17609987}, {64055, 17610243}, {64056, 17610499},
1736 	{64057, 17610755}, {64058, 17611011}, {64059, 17611267}, {64060, 17153027},
1737 	{64061, 17611523}, {64062, 17611779}, {64063, 17612035}, {64064, 17612291},
1738 	{64065, 17612547}, {64066, 17612803}, {64067, 17613059}, {64068, 17613315},
1739 	{64069, 17613571}, {64070, 17613827}, {64071, 17614083}, {64072, 17614339},
1740 	{64073, 17614595}, {64074, 17614851}, {64075, 17615107}, {64076, 17265155},
1741 	{64077, 17615363}, {64078, 17615619}, {64079, 17615875}, {64080, 17616131},
1742 	{64081, 17268227}, {64082, 17616387}, {64083, 17616643}, {64084, 17616899},
1743 	{64085, 17617155}, {64086, 17617411}, {64087, 17575171}, {64088, 17617667},
1744 	{64089, 17617923}, {64090, 17618179}, {64091, 17618435}, {64092, 17618691},
1745 	{64093, 17618947}, {64095, 17619203}, {64096, 17619459}, {64097, 17619715},
1746 	{64098, 17619971}, {64099, 17620227}, {64100, 17620483}, {64101, 17620739},
1747 	{64102, 17620995}, {64103, 17606403}, {64104, 17621251}, {64105, 17621507},
1748 	{64106, 17621763}, {64107, 17622019}, {64108, 17622275}, {64109, 17622531},
1749 	{64110, 2}, {64112, 17622787}, {64113, 17623043}, {64114, 17623299},
1750 	{64115, 17623555}, {64116, 17623811}, {64117, 17624067}, {64118, 17624323},
1751 	{64119, 17624579}, {64120, 17609987}, {64121, 17624835}, {64122, 17625091},
1752 	{64123, 17625347}, {64124, 17603075}, {64125, 17625603}, {64126, 17625859},
1753 	{64127, 17626115}, {64128, 17626371}, {64129, 17626627}, {64130, 17626883},
1754 	{64131, 17627139}, {64132, 17627395}, {64133, 17627651}, {64134, 17627907},
1755 	{64135, 17628163}, {64136, 17628419}, {64137, 17612035}, {64138, 17628675},
1756 	{64139, 17612291}, {64140, 17628931}, {64141, 17629187}, {64142, 17629443},
1757 	{64143, 17629699}, {64144, 17629955}, {64145, 17603331}, {64146, 17548803},
1758 	{64147, 17630211}, {64148, 17630467}, {64149, 17161475}, {64150, 17566211},
1759 	{64151, 17587203}, {64152, 17630723}, {64153, 17630979}, {64154, 17614083},
1760 	{64155, 17631235}, {64156, 17614339}, {64157, 17631491}, {64158, 17631747},
1761 	{64159, 17632003}, {64160, 17603843}, {64161, 17632259}, {64162, 17632515},
1762 	{64163, 17632771}, {64164, 17633027}, {64165, 17633283}, {64166, 17604099},
1763 	{64167, 17633539}, {64168, 17633795}, {64169, 17634051}, {64170, 17634307},
1764 	{64171, 17634563}, {64172, 17634819}, {64173, 17617411}, {64174, 17635075},
1765 	{64175, 17635331}, {64176, 17575171}, {64177, 17635587}, {64178, 17618435},
1766 	{64179, 17635843}, {64180, 17636099}, {64181, 17636355}, {64182, 17636611},
1767 	{64183, 17636867}, {64184, 17619715}, {64185, 17637123}, {64186, 17606147},
1768 	{64187, 17637379}, {64188, 17619971}, {64189, 17561347}, {64190, 17637635},
1769 	{64191, 17620227}, {64192, 17637891}, {64193, 17620739}, {64194, 17638147},
1770 	{64195, 17638403}, {64196, 17638659}, {64197, 17638915}, {64198, 17639171},
1771 	{64199, 17621251}, {64200, 17605379}, {64201, 17639427}, {64202, 17621507},
1772 	{64203, 17639683}, {64204, 17621763}, {64205, 17639939}, {64206, 17196035},
1773 	{64207, 17640195}, {64208, 17640451}, {64209, 17640707}, {64210, 17640963},
1774 	{64211, 17641219}, {64212, 17641475}, {64213, 17641731}, {64214, 17641987},
1775 	{64215, 17642243}, {64216, 17642499}, {64217, 17642755}, {64218, 2},
1776 	{64256, 34420227}, {64257, 34420739}, {64258, 34421251}, {64259, 51197699},
1777 	{64260, 51198979}, {64261, 33559043}, {64263, 2}, {64275, 34422531},
1778 	{64276, 34423043}, {64277, 34423555}, {64278, 34424067}, {64279, 34424579},
1779 	{64280, 2}, {64285, 34425091}, {64286, 1}, {64287, 34425603},
1780 	{64288, 17648899}, {64289, 17044227}, {64290, 17044995}, {64291, 17649155},
1781 	{64292, 17649411}, {64293, 17649667}, {64294, 17649923}, {64295, 17650179},
1782 	{64296, 17650435}, {64297, 17037059}, {64298, 34427907}, {64299, 34428419},
1783 	{64300, 51206147}, {64301, 51206915}, {64302, 34430467}, {64303, 34430979},
1784 	{64304, 34431491}, {64305, 34432003}, {64306, 34432515}, {64307, 34433027},
1785 	{64308, 34433539}, {64309, 34434051}, {64310, 34434563}, {64311, 2},
1786 	{64312, 34435075}, {64313, 34435587}, {64314, 34436099}, {64315, 34436611},
1787 	{64316, 34437123}, {64317, 2}, {64318, 34437635}, {64319, 2},
1788 	{64320, 34438147}, {64321, 34438659}, {64322, 2}, {64323, 34439171},
1789 	{64324, 34439683}, {64325, 2}, {64326, 34440195}, {64327, 34440707},
1790 	{64328, 34441219}, {64329, 34428931}, {64330, 34441731}, {64331, 34442243},
1791 	{64332, 34442755}, {64333, 34443267}, {64334, 34443779}, {64335, 34444291},
1792 	{64336, 17667587}, {64338, 17667843}, {64342, 17668099}, {64346, 17668355},
1793 	{64350, 17668611}, {64354, 17668867}, {64358, 17669123}, {64362, 17669379},
1794 	{64366, 17669635}, {64370, 17669891}, {64374, 17670147}, {64378, 17670403},
1795 	{64382, 17670659}, {64386, 17670915}, {64388, 17671171}, {64390, 17671427},
1796 	{64392, 17671683}, {64394, 17671939}, {64396, 17672195}, {64398, 17672451},
1797 	{64402, 17672707}, {64406, 17672963}, {64410, 17673219}, {64414, 17673475},
1798 	{64416, 17673731}, {64420, 17673987}, {64422, 17674243}, {64426, 17674499},
1799 	{64430, 17674755}, {64432, 17675011}, {64434, 1}, {64451, 2},
1800 	{64467, 17675267}, {64471, 16911363}, {64473, 17675523}, {64475, 17675779},
1801 	{64477, 33688579}, {64478, 17676035}, {64480, 17676291}, {64482, 17676547},
1802 	{64484, 17676803}, {64488, 17677059}, {64490, 34454531}, {64492, 34455043},
1803 	{64494, 34455555}, {64496, 34456067}, {64498, 34456579}, {64500, 34457091},
1804 	{64502, 34457603}, {64505, 34458115}, {64508, 17681411}, {64512, 34458883},
1805 	{64513, 34459395}, {64514, 34459907}, {64515, 34458115}, {64516, 34460419},
1806 	{64517, 34460931}, {64518, 34461443}, {64519, 34461955}, {64520, 34462467},
1807 	{64521, 34462979}, {64522, 34463491}, {64523, 34464003}, {64524, 34464515},
1808 	{64525, 34465027}, {64526, 34465539}, {64527, 34466051}, {64528, 34466563},
1809 	{64529, 34467075}, {64530, 34467587}, {64531, 34468099}, {64532, 34468611},
1810 	{64533, 34469123}, {64534, 34469635}, {64535, 34469379}, {64536, 34470147},
1811 	{64537, 34470659}, {64538, 34471171}, {64539, 34471683}, {64540, 34472195},
1812 	{64541, 34472707}, {64542, 34473219}, {64543, 34473731}, {64544, 34474243},
1813 	{64545, 34474755}, {64546, 34475267}, {64547, 34475779}, {64548, 34476291},
1814 	{64549, 34476803}, {64550, 34477315}, {64551, 34477827}, {64552, 34478339},
1815 	{64553, 34478851}, {64554, 34479363}, {64555, 34479875}, {64556, 34480387},
1816 	{64557, 34480899}, {64558, 34481411}, {64559, 34481923}, {64560, 34482435},
1817 	{64561, 34482947}, {64562, 34483459}, {64563, 34483971}, {64564, 34484483},
1818 	{64565, 34484995}, {64566, 34485507}, {64567, 34486019}, {64568, 34486531},
1819 	{64569, 34487043}, {64570, 34487555}, {64571, 34488067}, {64572, 34488579},
1820 	{64573, 34489091}, {64574, 34489603}, {64575, 34490115}, {64576, 34490627},
1821 	{64577, 34491139}, {64578, 34491651}, {64579, 34492163}, {64580, 34492675},
1822 	{64581, 34493187}, {64582, 34469891}, {64583, 34470403}, {64584, 34493699},
1823 	{64585, 34494211}, {64586, 34494723}, {64587, 34495235}, {64588, 34495747},
1824 	{64589, 34496259}, {64590, 34496771}, {64591, 34497283}, {64592, 34497795},
1825 	{64593, 34498307}, {64594, 34498819}, {64595, 34499331}, {64596, 34499843},
1826 	{64597, 34468867}, {64598, 34500355}, {64599, 34500867}, {64600, 34492931},
1827 	{64601, 34501379}, {64602, 34500099}, {64603, 34501891}, {64604, 34502403},
1828 	{64605, 34502915}, {64606, 51280643}, {64607, 51281411}, {64608, 51282179},
1829 	{64609, 51282947}, {64610, 51283715}, {64611, 51284483}, {64612, 34508035},
1830 	{64613, 34508547}, {64614, 34459907}, {64615, 34509059}, {64616, 34458115},
1831 	{64617, 34460419}, {64618, 34509571}, {64619, 34510083}, {64620, 34462467},
1832 	{64621, 34510595}, {64622, 34462979}, {64623, 34463491}, {64624, 34511107},
1833 	{64625, 34511619}, {64626, 34465539}, {64627, 34512131}, {64628, 34466051},
1834 	{64629, 34466563}, {64630, 34512643}, {64631, 34513155}, {64632, 34467587},
1835 	{64633, 34513667}, {64634, 34468099}, {64635, 34468611}, {64636, 34482947},
1836 	{64637, 34483459}, {64638, 34484995}, {64639, 34485507}, {64640, 34486019},
1837 	{64641, 34488067}, {64642, 34488579}, {64643, 34489091}, {64644, 34489603},
1838 	{64645, 34491651}, {64646, 34492163}, {64647, 34492675}, {64648, 34514179},
1839 	{64649, 34493699}, {64650, 34514691}, {64651, 34515203}, {64652, 34496771},
1840 	{64653, 34515715}, {64654, 34497283}, {64655, 34497795}, {64656, 34502915},
1841 	{64657, 34516227}, {64658, 34516739}, {64659, 34492931}, {64660, 34494979},
1842 	{64661, 34501379}, {64662, 34500099}, {64663, 34458883}, {64664, 34459395},
1843 	{64665, 34517251}, {64666, 34459907}, {64667, 34517763}, {64668, 34460931},
1844 	{64669, 34461443}, {64670, 34461955}, {64671, 34462467}, {64672, 34518275},
1845 	{64673, 34464003}, {64674, 34464515}, {64675, 34465027}, {64676, 34465539},
1846 	{64677, 34518787}, {64678, 34467587}, {64679, 34469123}, {64680, 34469635},
1847 	{64681, 34469379}, {64682, 34470147}, {64683, 34470659}, {64684, 34471683},
1848 	{64685, 34472195}, {64686, 34472707}, {64687, 34473219}, {64688, 34473731},
1849 	{64689, 34474243}, {64690, 34519299}, {64691, 34474755}, {64692, 34475267},
1850 	{64693, 34475779}, {64694, 34476291}, {64695, 34476803}, {64696, 34477315},
1851 	{64697, 34478339}, {64698, 34478851}, {64699, 34479363}, {64700, 34479875},
1852 	{64701, 34480387}, {64702, 34480899}, {64703, 34481411}, {64704, 34481923},
1853 	{64705, 34482435}, {64706, 34483971}, {64707, 34484483}, {64708, 34486531},
1854 	{64709, 34487043}, {64710, 34487555}, {64711, 34488067}, {64712, 34488579},
1855 	{64713, 34490115}, {64714, 34490627}, {64715, 34491139}, {64716, 34491651},
1856 	{64717, 34519811}, {64718, 34493187}, {64719, 34469891}, {64720, 34470403},
1857 	{64721, 34493699}, {64722, 34495235}, {64723, 34495747}, {64724, 34496259},
1858 	{64725, 34496771}, {64726, 34520323}, {64727, 34498307}, {64728, 34498819},
1859 	{64729, 34520835}, {64730, 34468867}, {64731, 34500355}, {64732, 34500867},
1860 	{64733, 34492931}, {64734, 34498051}, {64735, 34459907}, {64736, 34517763},
1861 	{64737, 34462467}, {64738, 34518275}, {64739, 34465539}, {64740, 34518787},
1862 	{64741, 34467587}, {64742, 34521347}, {64743, 34473731}, {64744, 34521859},
1863 	{64745, 34522371}, {64746, 34522883}, {64747, 34488067}, {64748, 34488579},
1864 	{64749, 34491651}, {64750, 34496771}, {64751, 34520323}, {64752, 34492931},
1865 	{64753, 34498051}, {64754, 51300611}, {64755, 51301379}, {64756, 51302147},
1866 	{64757, 34525699}, {64758, 34526211}, {64759, 34526723}, {64760, 34527235},
1867 	{64761, 34527747}, {64762, 34528259}, {64763, 34528771}, {64764, 34529283},
1868 	{64765, 34529795}, {64766, 34530307}, {64767, 34530819}, {64768, 34500611},
1869 	{64769, 34531331}, {64770, 34531843}, {64771, 34532355}, {64772, 34501123},
1870 	{64773, 34532867}, {64774, 34533379}, {64775, 34533891}, {64776, 34534403},
1871 	{64777, 34534915}, {64778, 34535427}, {64779, 34535939}, {64780, 34522371},
1872 	{64781, 34536451}, {64782, 34536963}, {64783, 34537475}, {64784, 34537987},
1873 	{64785, 34525699}, {64786, 34526211}, {64787, 34526723}, {64788, 34527235},
1874 	{64789, 34527747}, {64790, 34528259}, {64791, 34528771}, {64792, 34529283},
1875 	{64793, 34529795}, {64794, 34530307}, {64795, 34530819}, {64796, 34500611},
1876 	{64797, 34531331}, {64798, 34531843}, {64799, 34532355}, {64800, 34501123},
1877 	{64801, 34532867}, {64802, 34533379}, {64803, 34533891}, {64804, 34534403},
1878 	{64805, 34534915}, {64806, 34535427}, {64807, 34535939}, {64808, 34522371},
1879 	{64809, 34536451}, {64810, 34536963}, {64811, 34537475}, {64812, 34537987},
1880 	{64813, 34534915}, {64814, 34535427}, {64815, 34535939}, {64816, 34522371},
1881 	{64817, 34521859}, {64818, 34522883}, {64819, 34477827}, {64820, 34472195},
1882 	{64821, 34472707}, {64822, 34473219}, {64823, 34534915}, {64824, 34535427},
1883 	{64825, 34535939}, {64826, 34477827}, {64827, 34478339}, {64828, 34538499},
1884 	{64830, 1}, {64848, 51316227}, {64849, 51316995}, {64851, 51317763},
1885 	{64852, 51318531}, {64853, 51319299}, {64854, 51320067}, {64855, 51320835},
1886 	{64856, 51246851}, {64858, 51321603}, {64859, 51322371}, {64860, 51323139},
1887 	{64861, 51323907}, {64862, 51324675}, {64863, 51325443}, {64865, 51326211},
1888 	{64866, 51326979}, {64868, 51327747}, {64870, 51328515}, {64871, 51329283},
1889 	{64873, 51330051}, {64874, 51330819}, {64876, 51331587}, {64878, 51332355},
1890 	{64879, 51333123}, {64881, 51333891}, {64883, 51334659}, {64884, 51335427},
1891 	{64885, 51336195}, {64886, 51336963}, {64888, 51337731}, {64889, 51338499},
1892 	{64890, 51339267}, {64891, 51340035}, {64892, 51340803}, {64894, 51341571},
1893 	{64895, 51342339}, {64896, 51343107}, {64897, 51343875}, {64898, 51344643},
1894 	{64899, 51345411}, {64901, 51346179}, {64903, 51346947}, {64905, 51347715},
1895 	{64906, 51247107}, {64907, 51348483}, {64908, 51349251}, {64909, 51270403},
1896 	{64910, 51247619}, {64911, 51350019}, {64912, 2}, {64914, 51350787},
1897 	{64915, 51351555}, {64916, 51352323}, {64917, 51353091}, {64918, 51353859},
1898 	{64919, 51354627}, {64921, 51355395}, {64922, 51356163}, {64923, 51356931},
1899 	{64924, 51357699}, {64926, 51358467}, {64927, 51359235}, {64928, 51360003},
1900 	{64929, 51360771}, {64930, 51361539}, {64931, 51362307}, {64932, 51363075},
1901 	{64933, 51363843}, {64934, 51364611}, {64935, 51365379}, {64936, 51366147},
1902 	{64937, 51366915}, {64938, 51367683}, {64939, 51368451}, {64940, 51369219},
1903 	{64941, 51369987}, {64942, 51277571}, {64943, 51370755}, {64944, 51371523},
1904 	{64945, 51372291}, {64946, 51373059}, {64947, 51373827}, {64948, 51341571},
1905 	{64949, 51343107}, {64950, 51374595}, {64951, 51375363}, {64952, 51376131},
1906 	{64953, 51376899}, {64954, 51377667}, {64955, 51378435}, {64956, 51377667},
1907 	{64957, 51376131}, {64958, 51379203}, {64959, 51379971}, {64960, 51380739},
1908 	{64961, 51381507}, {64962, 51382275}, {64963, 51378435}, {64964, 51336195},
1909 	{64965, 51328515}, {64966, 51383043}, {64967, 51383811}, {64968, 2},
1910 	{64975, 1}, {64976, 2}, {65008, 51384579}, {65009, 51385347},
1911 	{65010, 68163331}, {65011, 68164355}, {65012, 68165379}, {65013, 68166403},
1912 	{65014, 68167427}, {65015, 68168451}, {65016, 68169475}, {65017, 51393283},
1913 	{65018, 303052291}, {65019, 135284739}, {65020, 68177923}, {65021, 1},
1914 	{65024, 0}, {65040, 17847299}, {65041, 17847555}, {65042, 2},
1915 	{65043, 17110531}, {65044, 16848643}, {65045, 17032963}, {65046, 17033987},
1916 	{65047, 17847811}, {65048, 17848067}, {65049, 2}, {65056, 1},
1917 	{65072, 2}, {65073, 17848323}, {65074, 17848579}, {65075, 17848835},
1918 	{65077, 17037827}, {65078, 17038083}, {65079, 17849091}, {65080, 17849347},
1919 	{65081, 17849603}, {65082, 17849859}, {65083, 17850115}, {65084, 17850371},
1920 	{65085, 17850627}, {65086, 17850883}, {65087, 17067267}, {65088, 17067523},
1921 	{65089, 17851139}, {65090, 17851395}, {65091, 17851651}, {65092, 17851907},
1922 	{65093, 1}, {65095, 17852163}, {65096, 17852419}, {65097, 33810691},
1923 	{65101, 17848835}, {65104, 17847299}, {65105, 17847555}, {65106, 2},
1924 	{65108, 16848643}, {65109, 17110531}, {65110, 17033987}, {65111, 17032963},
1925 	{65112, 17848323}, {65113, 17037827}, {65114, 17038083}, {65115, 17849091},
1926 	{65116, 17849347}, {65117, 17849603}, {65118, 17849859}, {65119, 17852675},
1927 	{65120, 17852931}, {65121, 17853187}, {65122, 17037059}, {65123, 17853443},
1928 	{65124, 17853699}, {65125, 17853955}, {65126, 17037571}, {65127, 2},
1929 	{65128, 17854211}, {65129, 17854467}, {65130, 17854723}, {65131, 17854979},
1930 	{65132, 2}, {65136, 34632451}, {65137, 34632963}, {65138, 34503427},
1931 	{65139, 1}, {65140, 34504195}, {65141, 2}, {65142, 34504963},
1932 	{65143, 34523395}, {65144, 34505731}, {65145, 34524163}, {65146, 34506499},
1933 	{65147, 34524931}, {65148, 34507267}, {65149, 34633475}, {65150, 34633987},
1934 	{65151, 34634499}, {65152, 17857795}, {65153, 17858051}, {65155, 17858307},
1935 	{65157, 17858563}, {65159, 17858819}, {65161, 17677315}, {65165, 16910339},
1936 	{65167, 17683715}, {65171, 17859075}, {65173, 17686787}, {65177, 17689859},
1937 	{65181, 17681923}, {65185, 17682435}, {65189, 17684995}, {65193, 17834499},
1938 	{65195, 17724675}, {65197, 17725187}, {65199, 17731587}, {65201, 17694979},
1939 	{65205, 17745155}, {65209, 17697027}, {65213, 17698051}, {65217, 17700099},
1940 	{65221, 17701123}, {65225, 17701635}, {65229, 17702659}, {65233, 17703683},
1941 	{65237, 17706755}, {65241, 17708803}, {65245, 17711107}, {65249, 17682947},
1942 	{65253, 17718019}, {65257, 17721091}, {65261, 16910851}, {65263, 17677059},
1943 	{65265, 16911875}, {65269, 34636547}, {65271, 34637059}, {65273, 34637571},
1944 	{65275, 34622467}, {65277, 2}, {65279, 0}, {65280, 2},
1945 	{65281, 17032963}, {65282, 17860867}, {65283, 17852675}, {65284, 17854467},
1946 	{65285, 17854723}, {65286, 17852931}, {65287, 17861123}, {65288, 17037827},
1947 	{65289, 17038083}, {65290, 17853187}, {65291, 17037059}, {65292, 17847299},
1948 	{65293, 17853443}, {65294, 17196547}, {65295, 17038595}, {65296, 17035523},
1949 	{65297, 16786947}, {65298, 16785155}, {65299, 16785411}, {65300, 16787715},
1950 	{65301, 17035779}, {65302, 17036035}, {65303, 17036291}, {65304, 17036547},
1951 	{65305, 17036803}, {65306, 17110531}, {65307, 16848643}, {65308, 17853699},
1952 	{65309, 17037571}, {65310, 17853955}, {65311, 17033987}, {65312, 17854979},
1953 	{65313, 16777219}, {65314, 16777475}, {65315, 16777731}, {65316, 16777987},
1954 	{65317, 16778243}, {65318, 16778499}, {65319, 16778755}, {65320, 16779011},
1955 	{65321, 16779267}, {65322, 16779523}, {65323, 16779779}, {65324, 16780035},
1956 	{65325, 16780291}, {65326, 16780547}, {65327, 16780803}, {65328, 16781059},
1957 	{65329, 16781315}, {65330, 16781571}, {65331, 16781827}, {65332, 16782083},
1958 	{65333, 16782339}, {65334, 16782595}, {65335, 16782851}, {65336, 16783107},
1959 	{65337, 16783363}, {65338, 16783619}, {65339, 17852163}, {65340, 17854211},
1960 	{65341, 17852419}, {65342, 17861379}, {65343, 17848835}, {65344, 17027075},
1961 	{65345, 16777219}, {65346, 16777475}, {65347, 16777731}, {65348, 16777987},
1962 	{65349, 16778243}, {65350, 16778499}, {65351, 16778755}, {65352, 16779011},
1963 	{65353, 16779267}, {65354, 16779523}, {65355, 16779779}, {65356, 16780035},
1964 	{65357, 16780291}, {65358, 16780547}, {65359, 16780803}, {65360, 16781059},
1965 	{65361, 16781315}, {65362, 16781571}, {65363, 16781827}, {65364, 16782083},
1966 	{65365, 16782339}, {65366, 16782595}, {65367, 16782851}, {65368, 16783107},
1967 	{65369, 16783363}, {65370, 16783619}, {65371, 17849091}, {65372, 17861635},
1968 	{65373, 17849347}, {65374, 17861891}, {65375, 17862147}, {65376, 17862403},
1969 	{65377, 17196547}, {65378, 17851139}, {65379, 17851395}, {65380, 17847555},
1970 	{65381, 17862659}, {65382, 17316867}, {65383, 17319427}, {65384, 17362435},
1971 	{65385, 17862915}, {65386, 17363971}, {65387, 17323523}, {65388, 17863171},
1972 	{65389, 17333763}, {65390, 17379587}, {65391, 17329155}, {65392, 17318147},
1973 	{65393, 17305603}, {65394, 17305859}, {65395, 17306115}, {65396, 17306371},
1974 	{65397, 17306627}, {65398, 17306883}, {65399, 17307139}, {65400, 17307395},
1975 	{65401, 17307651}, {65402, 17199107}, {65403, 17307907}, {65404, 17308163},
1976 	{65405, 17308419}, {65406, 17308675}, {65407, 17308931}, {65408, 17309187},
1977 	{65409, 17309443}, {65410, 17309699}, {65411, 17309955}, {65412, 17199363},
1978 	{65413, 17310211}, {65414, 17310467}, {65415, 17310723}, {65416, 17310979},
1979 	{65417, 17311235}, {65418, 17311491}, {65419, 17311747}, {65420, 17312003},
1980 	{65421, 17312259}, {65422, 17312515}, {65423, 17312771}, {65424, 17313027},
1981 	{65425, 17313283}, {65426, 17313539}, {65427, 17313795}, {65428, 17314051},
1982 	{65429, 17314307}, {65430, 17314563}, {65431, 17314819}, {65432, 17315075},
1983 	{65433, 17315331}, {65434, 17315587}, {65435, 17315843}, {65436, 17316099},
1984 	{65437, 17319939}, {65438, 17197827}, {65439, 17198339}, {65440, 2},
1985 	{65441, 17199619}, {65442, 17199875}, {65443, 17200131}, {65444, 17200387},
1986 	{65445, 17200643}, {65446, 17200899}, {65447, 17201155}, {65448, 17201411},
1987 	{65449, 17201667}, {65450, 17201923}, {65451, 17202179}, {65452, 17202435},
1988 	{65453, 17202691}, {65454, 17202947}, {65455, 17203203}, {65456, 17203459},
1989 	{65457, 17203715}, {65458, 17203971}, {65459, 17204227}, {65460, 17204483},
1990 	{65461, 17204739}, {65462, 17204995}, {65463, 17205251}, {65464, 17205507},
1991 	{65465, 17205763}, {65466, 17206019}, {65467, 17206275}, {65468, 17206531},
1992 	{65469, 17206787}, {65470, 17207043}, {65471, 2}, {65474, 17207299},
1993 	{65475, 17207555}, {65476, 17207811}, {65477, 17208067}, {65478, 17208323},
1994 	{65479, 17208579}, {65480, 2}, {65482, 17208835}, {65483, 17209091},
1995 	{65484, 17209347}, {65485, 17209603}, {65486, 17209859}, {65487, 17210115},
1996 	{65488, 2}, {65490, 17210371}, {65491, 17210627}, {65492, 17210883},
1997 	{65493, 17211139}, {65494, 17211395}, {65495, 17211651}, {65496, 2},
1998 	{65498, 17211907}, {65499, 17212163}, {65500, 17212419}, {65501, 2},
1999 	{65504, 17863427}, {65505, 17863683}, {65506, 17863939}, {65507, 33561859},
2000 	{65508, 17864195}, {65509, 17864451}, {65510, 17864707}, {65511, 2},
2001 	{65512, 17864963}, {65513, 17865219}, {65514, 17865475}, {65515, 17865731},
2002 	{65516, 17865987}, {65517, 17866243}, {65518, 17866499}, {65519, 2},
2003 	{65536, 1}, {65548, 2}, {65549, 1}, {65575, 2},
2004 	{65576, 1}, {65595, 2}, {65596, 1}, {65598, 2},
2005 	{65599, 1}, {65614, 2}, {65616, 1}, {65630, 2},
2006 	{65664, 1}, {65787, 2}, {65792, 1}, {65795, 2},
2007 	{65799, 1}, {65844, 2}, {65847, 1}, {65935, 2},
2008 	{65936, 1}, {65949, 2}, {65952, 1}, {65953, 2},
2009 	{66000, 1}, {66046, 2}, {66176, 1}, {66205, 2},
2010 	{66208, 1}, {66257, 2}, {66272, 1}, {66300, 2},
2011 	{66304, 1}, {66340, 2}, {66349, 1}, {66379, 2},
2012 	{66384, 1}, {66427, 2}, {66432, 1}, {66462, 2},
2013 	{66463, 1}, {66500, 2}, {66504, 1}, {66518, 2},
2014 	{66560, 17866755}, {66561, 17867011}, {66562, 17867267}, {66563, 17867523},
2015 	{66564, 17867779}, {66565, 17868035}, {66566, 17868291}, {66567, 17868547},
2016 	{66568, 17868803}, {66569, 17869059}, {66570, 17869315}, {66571, 17869571},
2017 	{66572, 17869827}, {66573, 17870083}, {66574, 17870339}, {66575, 17870595},
2018 	{66576, 17870851}, {66577, 17871107}, {66578, 17871363}, {66579, 17871619},
2019 	{66580, 17871875}, {66581, 17872131}, {66582, 17872387}, {66583, 17872643},
2020 	{66584, 17872899}, {66585, 17873155}, {66586, 17873411}, {66587, 17873667},
2021 	{66588, 17873923}, {66589, 17874179}, {66590, 17874435}, {66591, 17874691},
2022 	{66592, 17874947}, {66593, 17875203}, {66594, 17875459}, {66595, 17875715},
2023 	{66596, 17875971}, {66597, 17876227}, {66598, 17876483}, {66599, 17876739},
2024 	{66600, 1}, {66718, 2}, {66720, 1}, {66730, 2},
2025 	{66736, 17876995}, {66737, 17877251}, {66738, 17877507}, {66739, 17877763},
2026 	{66740, 17878019}, {66741, 17878275}, {66742, 17878531}, {66743, 17878787},
2027 	{66744, 17879043}, {66745, 17879299}, {66746, 17879555}, {66747, 17879811},
2028 	{66748, 17880067}, {66749, 17880323}, {66750, 17880579}, {66751, 17880835},
2029 	{66752, 17881091}, {66753, 17881347}, {66754, 17881603}, {66755, 17881859},
2030 	{66756, 17882115}, {66757, 17882371}, {66758, 17882627}, {66759, 17882883},
2031 	{66760, 17883139}, {66761, 17883395}, {66762, 17883651}, {66763, 17883907},
2032 	{66764, 17884163}, {66765, 17884419}, {66766, 17884675}, {66767, 17884931},
2033 	{66768, 17885187}, {66769, 17885443}, {66770, 17885699}, {66771, 17885955},
2034 	{66772, 2}, {66776, 1}, {66812, 2}, {66816, 1},
2035 	{66856, 2}, {66864, 1}, {66916, 2}, {66927, 1},
2036 	{66928, 17886211}, {66929, 17886467}, {66930, 17886723}, {66931, 17886979},
2037 	{66932, 17887235}, {66933, 17887491}, {66934, 17887747}, {66935, 17888003},
2038 	{66936, 17888259}, {66937, 17888515}, {66938, 17888771}, {66939, 2},
2039 	{66940, 17889027}, {66941, 17889283}, {66942, 17889539}, {66943, 17889795},
2040 	{66944, 17890051}, {66945, 17890307}, {66946, 17890563}, {66947, 17890819},
2041 	{66948, 17891075}, {66949, 17891331}, {66950, 17891587}, {66951, 17891843},
2042 	{66952, 17892099}, {66953, 17892355}, {66954, 17892611}, {66955, 2},
2043 	{66956, 17892867}, {66957, 17893123}, {66958, 17893379}, {66959, 17893635},
2044 	{66960, 17893891}, {66961, 17894147}, {66962, 17894403}, {66963, 2},
2045 	{66964, 17894659}, {66965, 17894915}, {66966, 2}, {66967, 1},
2046 	{66978, 2}, {66979, 1}, {66994, 2}, {66995, 1},
2047 	{67002, 2}, {67003, 1}, {67005, 2}, {67072, 1},
2048 	{67383, 2}, {67392, 1}, {67414, 2}, {67424, 1},
2049 	{67432, 2}, {67456, 1}, {67457, 17895171}, {67458, 17895427},
2050 	{67459, 16791043}, {67460, 17895683}, {67461, 16814083}, {67462, 2},
2051 	{67463, 17895939}, {67464, 17896195}, {67465, 17896451}, {67466, 17896707},
2052 	{67467, 16815363}, {67468, 16815619}, {67469, 17896963}, {67470, 17897219},
2053 	{67471, 17897475}, {67472, 17897731}, {67473, 17897987}, {67474, 17898243},
2054 	{67475, 16817155}, {67476, 17898499}, {67477, 16802051}, {67478, 17898755},
2055 	{67479, 17899011}, {67480, 17899267}, {67481, 17899523}, {67482, 17899779},
2056 	{67483, 17512963}, {67484, 17900035}, {67485, 17900291}, {67486, 17900547},
2057 	{67487, 17900803}, {67488, 17901059}, {67489, 17901315}, {67490, 16795395},
2058 	{67491, 17901571}, {67492, 17901827}, {67493, 16781315}, {67494, 17902083},
2059 	{67495, 17902339}, {67496, 17125379}, {67497, 17902595}, {67498, 16819971},
2060 	{67499, 17902851}, {67500, 17903107}, {67501, 17903363}, {67502, 17903619},
2061 	{67503, 16820995}, {67504, 17903875}, {67505, 2}, {67506, 17904131},
2062 	{67507, 17904387}, {67508, 17904643}, {67509, 17904899}, {67510, 17905155},
2063 	{67511, 17905411}, {67512, 17905667}, {67513, 17905923}, {67514, 17906179},
2064 	{67515, 2}, {67584, 1}, {67590, 2}, {67592, 1},
2065 	{67593, 2}, {67594, 1}, {67638, 2}, {67639, 1},
2066 	{67641, 2}, {67644, 1}, {67645, 2}, {67647, 1},
2067 	{67670, 2}, {67671, 1}, {67743, 2}, {67751, 1},
2068 	{67760, 2}, {67808, 1}, {67827, 2}, {67828, 1},
2069 	{67830, 2}, {67835, 1}, {67868, 2}, {67871, 1},
2070 	{67898, 2}, {67903, 1}, {67904, 2}, {67968, 1},
2071 	{68024, 2}, {68028, 1}, {68048, 2}, {68050, 1},
2072 	{68100, 2}, {68101, 1}, {68103, 2}, {68108, 1},
2073 	{68116, 2}, {68117, 1}, {68120, 2}, {68121, 1},
2074 	{68150, 2}, {68152, 1}, {68155, 2}, {68159, 1},
2075 	{68169, 2}, {68176, 1}, {68185, 2}, {68192, 1},
2076 	{68256, 2}, {68288, 1}, {68327, 2}, {68331, 1},
2077 	{68343, 2}, {68352, 1}, {68406, 2}, {68409, 1},
2078 	{68438, 2}, {68440, 1}, {68467, 2}, {68472, 1},
2079 	{68498, 2}, {68505, 1}, {68509, 2}, {68521, 1},
2080 	{68528, 2}, {68608, 1}, {68681, 2}, {68736, 17906435},
2081 	{68737, 17906691}, {68738, 17906947}, {68739, 17907203}, {68740, 17907459},
2082 	{68741, 17907715}, {68742, 17907971}, {68743, 17908227}, {68744, 17908483},
2083 	{68745, 17908739}, {68746, 17908995}, {68747, 17909251}, {68748, 17909507},
2084 	{68749, 17909763}, {68750, 17910019}, {68751, 17910275}, {68752, 17910531},
2085 	{68753, 17910787}, {68754, 17911043}, {68755, 17911299}, {68756, 17911555},
2086 	{68757, 17911811}, {68758, 17912067}, {68759, 17912323}, {68760, 17912579},
2087 	{68761, 17912835}, {68762, 17913091}, {68763, 17913347}, {68764, 17913603},
2088 	{68765, 17913859}, {68766, 17914115}, {68767, 17914371}, {68768, 17914627},
2089 	{68769, 17914883}, {68770, 17915139}, {68771, 17915395}, {68772, 17915651},
2090 	{68773, 17915907}, {68774, 17916163}, {68775, 17916419}, {68776, 17916675},
2091 	{68777, 17916931}, {68778, 17917187}, {68779, 17917443}, {68780, 17917699},
2092 	{68781, 17917955}, {68782, 17918211}, {68783, 17918467}, {68784, 17918723},
2093 	{68785, 17918979}, {68786, 17919235}, {68787, 2}, {68800, 1},
2094 	{68851, 2}, {68858, 1}, {68904, 2}, {68912, 1},
2095 	{68922, 2}, {69216, 1}, {69247, 2}, {69248, 1},
2096 	{69290, 2}, {69291, 1}, {69294, 2}, {69296, 1},
2097 	{69298, 2}, {69373, 1}, {69416, 2}, {69424, 1},
2098 	{69466, 2}, {69488, 1}, {69514, 2}, {69552, 1},
2099 	{69580, 2}, {69600, 1}, {69623, 2}, {69632, 1},
2100 	{69710, 2}, {69714, 1}, {69750, 2}, {69759, 1},
2101 	{69821, 2}, {69822, 1}, {69827, 2}, {69840, 1},
2102 	{69865, 2}, {69872, 1}, {69882, 2}, {69888, 1},
2103 	{69941, 2}, {69942, 1}, {69960, 2}, {69968, 1},
2104 	{70007, 2}, {70016, 1}, {70112, 2}, {70113, 1},
2105 	{70133, 2}, {70144, 1}, {70162, 2}, {70163, 1},
2106 	{70210, 2}, {70272, 1}, {70279, 2}, {70280, 1},
2107 	{70281, 2}, {70282, 1}, {70286, 2}, {70287, 1},
2108 	{70302, 2}, {70303, 1}, {70314, 2}, {70320, 1},
2109 	{70379, 2}, {70384, 1}, {70394, 2}, {70400, 1},
2110 	{70404, 2}, {70405, 1}, {70413, 2}, {70415, 1},
2111 	{70417, 2}, {70419, 1}, {70441, 2}, {70442, 1},
2112 	{70449, 2}, {70450, 1}, {70452, 2}, {70453, 1},
2113 	{70458, 2}, {70459, 1}, {70469, 2}, {70471, 1},
2114 	{70473, 2}, {70475, 1}, {70478, 2}, {70480, 1},
2115 	{70481, 2}, {70487, 1}, {70488, 2}, {70493, 1},
2116 	{70500, 2}, {70502, 1}, {70509, 2}, {70512, 1},
2117 	{70517, 2}, {70656, 1}, {70748, 2}, {70749, 1},
2118 	{70754, 2}, {70784, 1}, {70856, 2}, {70864, 1},
2119 	{70874, 2}, {71040, 1}, {71094, 2}, {71096, 1},
2120 	{71134, 2}, {71168, 1}, {71237, 2}, {71248, 1},
2121 	{71258, 2}, {71264, 1}, {71277, 2}, {71296, 1},
2122 	{71354, 2}, {71360, 1}, {71370, 2}, {71424, 1},
2123 	{71451, 2}, {71453, 1}, {71468, 2}, {71472, 1},
2124 	{71495, 2}, {71680, 1}, {71740, 2}, {71840, 17919491},
2125 	{71841, 17919747}, {71842, 17920003}, {71843, 17920259}, {71844, 17920515},
2126 	{71845, 17920771}, {71846, 17921027}, {71847, 17921283}, {71848, 17921539},
2127 	{71849, 17921795}, {71850, 17922051}, {71851, 17922307}, {71852, 17922563},
2128 	{71853, 17922819}, {71854, 17923075}, {71855, 17923331}, {71856, 17923587},
2129 	{71857, 17923843}, {71858, 17924099}, {71859, 17924355}, {71860, 17924611},
2130 	{71861, 17924867}, {71862, 17925123}, {71863, 17925379}, {71864, 17925635},
2131 	{71865, 17925891}, {71866, 17926147}, {71867, 17926403}, {71868, 17926659},
2132 	{71869, 17926915}, {71870, 17927171}, {71871, 17927427}, {71872, 1},
2133 	{71923, 2}, {71935, 1}, {71943, 2}, {71945, 1},
2134 	{71946, 2}, {71948, 1}, {71956, 2}, {71957, 1},
2135 	{71959, 2}, {71960, 1}, {71990, 2}, {71991, 1},
2136 	{71993, 2}, {71995, 1}, {72007, 2}, {72016, 1},
2137 	{72026, 2}, {72096, 1}, {72104, 2}, {72106, 1},
2138 	{72152, 2}, {72154, 1}, {72165, 2}, {72192, 1},
2139 	{72264, 2}, {72272, 1}, {72355, 2}, {72368, 1},
2140 	{72441, 2}, {72448, 1}, {72458, 2}, {72704, 1},
2141 	{72713, 2}, {72714, 1}, {72759, 2}, {72760, 1},
2142 	{72774, 2}, {72784, 1}, {72813, 2}, {72816, 1},
2143 	{72848, 2}, {72850, 1}, {72872, 2}, {72873, 1},
2144 	{72887, 2}, {72960, 1}, {72967, 2}, {72968, 1},
2145 	{72970, 2}, {72971, 1}, {73015, 2}, {73018, 1},
2146 	{73019, 2}, {73020, 1}, {73022, 2}, {73023, 1},
2147 	{73032, 2}, {73040, 1}, {73050, 2}, {73056, 1},
2148 	{73062, 2}, {73063, 1}, {73065, 2}, {73066, 1},
2149 	{73103, 2}, {73104, 1}, {73106, 2}, {73107, 1},
2150 	{73113, 2}, {73120, 1}, {73130, 2}, {73440, 1},
2151 	{73465, 2}, {73472, 1}, {73489, 2}, {73490, 1},
2152 	{73531, 2}, {73534, 1}, {73562, 2}, {73648, 1},
2153 	{73649, 2}, {73664, 1}, {73714, 2}, {73727, 1},
2154 	{74650, 2}, {74752, 1}, {74863, 2}, {74864, 1},
2155 	{74869, 2}, {74880, 1}, {75076, 2}, {77712, 1},
2156 	{77811, 2}, {77824, 1}, {78896, 2}, {78912, 1},
2157 	{78934, 2}, {82944, 1}, {83527, 2}, {92160, 1},
2158 	{92729, 2}, {92736, 1}, {92767, 2}, {92768, 1},
2159 	{92778, 2}, {92782, 1}, {92863, 2}, {92864, 1},
2160 	{92874, 2}, {92880, 1}, {92910, 2}, {92912, 1},
2161 	{92918, 2}, {92928, 1}, {92998, 2}, {93008, 1},
2162 	{93018, 2}, {93019, 1}, {93026, 2}, {93027, 1},
2163 	{93048, 2}, {93053, 1}, {93072, 2}, {93760, 17927683},
2164 	{93761, 17927939}, {93762, 17928195}, {93763, 17928451}, {93764, 17928707},
2165 	{93765, 17928963}, {93766, 17929219}, {93767, 17929475}, {93768, 17929731},
2166 	{93769, 17929987}, {93770, 17930243}, {93771, 17930499}, {93772, 17930755},
2167 	{93773, 17931011}, {93774, 17931267}, {93775, 17931523}, {93776, 17931779},
2168 	{93777, 17932035}, {93778, 17932291}, {93779, 17932547}, {93780, 17932803},
2169 	{93781, 17933059}, {93782, 17933315}, {93783, 17933571}, {93784, 17933827},
2170 	{93785, 17934083}, {93786, 17934339}, {93787, 17934595}, {93788, 17934851},
2171 	{93789, 17935107}, {93790, 17935363}, {93791, 17935619}, {93792, 1},
2172 	{93851, 2}, {93952, 1}, {94027, 2}, {94031, 1},
2173 	{94088, 2}, {94095, 1}, {94112, 2}, {94176, 1},
2174 	{94181, 2}, {94192, 1}, {94194, 2}, {94208, 1},
2175 	{100344, 2}, {100352, 1}, {101590, 2}, {101632, 1},
2176 	{101641, 2}, {110576, 1}, {110580, 2}, {110581, 1},
2177 	{110588, 2}, {110589, 1}, {110591, 2}, {110592, 1},
2178 	{110883, 2}, {110898, 1}, {110899, 2}, {110928, 1},
2179 	{110931, 2}, {110933, 1}, {110934, 2}, {110948, 1},
2180 	{110952, 2}, {110960, 1}, {111356, 2}, {113664, 1},
2181 	{113771, 2}, {113776, 1}, {113789, 2}, {113792, 1},
2182 	{113801, 2}, {113808, 1}, {113818, 2}, {113820, 1},
2183 	{113824, 0}, {113828, 2}, {118528, 1}, {118574, 2},
2184 	{118576, 1}, {118599, 2}, {118608, 1}, {118724, 2},
2185 	{118784, 1}, {119030, 2}, {119040, 1}, {119079, 2},
2186 	{119081, 1}, {119134, 34713091}, {119135, 34713603}, {119136, 51491331},
2187 	{119137, 51492099}, {119138, 51492867}, {119139, 51493635}, {119140, 51494403},
2188 	{119141, 1}, {119155, 2}, {119163, 1}, {119227, 34717955},
2189 	{119228, 34718467}, {119229, 51496195}, {119230, 51496963}, {119231, 51497731},
2190 	{119232, 51498499}, {119233, 1}, {119275, 2}, {119296, 1},
2191 	{119366, 2}, {119488, 1}, {119508, 2}, {119520, 1},
2192 	{119540, 2}, {119552, 1}, {119639, 2}, {119648, 1},
2193 	{119673, 2}, {119808, 16777219}, {119809, 16777475}, {119810, 16777731},
2194 	{119811, 16777987}, {119812, 16778243}, {119813, 16778499}, {119814, 16778755},
2195 	{119815, 16779011}, {119816, 16779267}, {119817, 16779523}, {119818, 16779779},
2196 	{119819, 16780035}, {119820, 16780291}, {119821, 16780547}, {119822, 16780803},
2197 	{119823, 16781059}, {119824, 16781315}, {119825, 16781571}, {119826, 16781827},
2198 	{119827, 16782083}, {119828, 16782339}, {119829, 16782595}, {119830, 16782851},
2199 	{119831, 16783107}, {119832, 16783363}, {119833, 16783619}, {119834, 16777219},
2200 	{119835, 16777475}, {119836, 16777731}, {119837, 16777987}, {119838, 16778243},
2201 	{119839, 16778499}, {119840, 16778755}, {119841, 16779011}, {119842, 16779267},
2202 	{119843, 16779523}, {119844, 16779779}, {119845, 16780035}, {119846, 16780291},
2203 	{119847, 16780547}, {119848, 16780803}, {119849, 16781059}, {119850, 16781315},
2204 	{119851, 16781571}, {119852, 16781827}, {119853, 16782083}, {119854, 16782339},
2205 	{119855, 16782595}, {119856, 16782851}, {119857, 16783107}, {119858, 16783363},
2206 	{119859, 16783619}, {119860, 16777219}, {119861, 16777475}, {119862, 16777731},
2207 	{119863, 16777987}, {119864, 16778243}, {119865, 16778499}, {119866, 16778755},
2208 	{119867, 16779011}, {119868, 16779267}, {119869, 16779523}, {119870, 16779779},
2209 	{119871, 16780035}, {119872, 16780291}, {119873, 16780547}, {119874, 16780803},
2210 	{119875, 16781059}, {119876, 16781315}, {119877, 16781571}, {119878, 16781827},
2211 	{119879, 16782083}, {119880, 16782339}, {119881, 16782595}, {119882, 16782851},
2212 	{119883, 16783107}, {119884, 16783363}, {119885, 16783619}, {119886, 16777219},
2213 	{119887, 16777475}, {119888, 16777731}, {119889, 16777987}, {119890, 16778243},
2214 	{119891, 16778499}, {119892, 16778755}, {119893, 2}, {119894, 16779267},
2215 	{119895, 16779523}, {119896, 16779779}, {119897, 16780035}, {119898, 16780291},
2216 	{119899, 16780547}, {119900, 16780803}, {119901, 16781059}, {119902, 16781315},
2217 	{119903, 16781571}, {119904, 16781827}, {119905, 16782083}, {119906, 16782339},
2218 	{119907, 16782595}, {119908, 16782851}, {119909, 16783107}, {119910, 16783363},
2219 	{119911, 16783619}, {119912, 16777219}, {119913, 16777475}, {119914, 16777731},
2220 	{119915, 16777987}, {119916, 16778243}, {119917, 16778499}, {119918, 16778755},
2221 	{119919, 16779011}, {119920, 16779267}, {119921, 16779523}, {119922, 16779779},
2222 	{119923, 16780035}, {119924, 16780291}, {119925, 16780547}, {119926, 16780803},
2223 	{119927, 16781059}, {119928, 16781315}, {119929, 16781571}, {119930, 16781827},
2224 	{119931, 16782083}, {119932, 16782339}, {119933, 16782595}, {119934, 16782851},
2225 	{119935, 16783107}, {119936, 16783363}, {119937, 16783619}, {119938, 16777219},
2226 	{119939, 16777475}, {119940, 16777731}, {119941, 16777987}, {119942, 16778243},
2227 	{119943, 16778499}, {119944, 16778755}, {119945, 16779011}, {119946, 16779267},
2228 	{119947, 16779523}, {119948, 16779779}, {119949, 16780035}, {119950, 16780291},
2229 	{119951, 16780547}, {119952, 16780803}, {119953, 16781059}, {119954, 16781315},
2230 	{119955, 16781571}, {119956, 16781827}, {119957, 16782083}, {119958, 16782339},
2231 	{119959, 16782595}, {119960, 16782851}, {119961, 16783107}, {119962, 16783363},
2232 	{119963, 16783619}, {119964, 16777219}, {119965, 2}, {119966, 16777731},
2233 	{119967, 16777987}, {119968, 2}, {119970, 16778755}, {119971, 2},
2234 	{119973, 16779523}, {119974, 16779779}, {119975, 2}, {119977, 16780547},
2235 	{119978, 16780803}, {119979, 16781059}, {119980, 16781315}, {119981, 2},
2236 	{119982, 16781827}, {119983, 16782083}, {119984, 16782339}, {119985, 16782595},
2237 	{119986, 16782851}, {119987, 16783107}, {119988, 16783363}, {119989, 16783619},
2238 	{119990, 16777219}, {119991, 16777475}, {119992, 16777731}, {119993, 16777987},
2239 	{119994, 2}, {119995, 16778499}, {119996, 2}, {119997, 16779011},
2240 	{119998, 16779267}, {119999, 16779523}, {120000, 16779779}, {120001, 16780035},
2241 	{120002, 16780291}, {120003, 16780547}, {120004, 2}, {120005, 16781059},
2242 	{120006, 16781315}, {120007, 16781571}, {120008, 16781827}, {120009, 16782083},
2243 	{120010, 16782339}, {120011, 16782595}, {120012, 16782851}, {120013, 16783107},
2244 	{120014, 16783363}, {120015, 16783619}, {120016, 16777219}, {120017, 16777475},
2245 	{120018, 16777731}, {120019, 16777987}, {120020, 16778243}, {120021, 16778499},
2246 	{120022, 16778755}, {120023, 16779011}, {120024, 16779267}, {120025, 16779523},
2247 	{120026, 16779779}, {120027, 16780035}, {120028, 16780291}, {120029, 16780547},
2248 	{120030, 16780803}, {120031, 16781059}, {120032, 16781315}, {120033, 16781571},
2249 	{120034, 16781827}, {120035, 16782083}, {120036, 16782339}, {120037, 16782595},
2250 	{120038, 16782851}, {120039, 16783107}, {120040, 16783363}, {120041, 16783619},
2251 	{120042, 16777219}, {120043, 16777475}, {120044, 16777731}, {120045, 16777987},
2252 	{120046, 16778243}, {120047, 16778499}, {120048, 16778755}, {120049, 16779011},
2253 	{120050, 16779267}, {120051, 16779523}, {120052, 16779779}, {120053, 16780035},
2254 	{120054, 16780291}, {120055, 16780547}, {120056, 16780803}, {120057, 16781059},
2255 	{120058, 16781315}, {120059, 16781571}, {120060, 16781827}, {120061, 16782083},
2256 	{120062, 16782339}, {120063, 16782595}, {120064, 16782851}, {120065, 16783107},
2257 	{120066, 16783363}, {120067, 16783619}, {120068, 16777219}, {120069, 16777475},
2258 	{120070, 2}, {120071, 16777987}, {120072, 16778243}, {120073, 16778499},
2259 	{120074, 16778755}, {120075, 2}, {120077, 16779523}, {120078, 16779779},
2260 	{120079, 16780035}, {120080, 16780291}, {120081, 16780547}, {120082, 16780803},
2261 	{120083, 16781059}, {120084, 16781315}, {120085, 2}, {120086, 16781827},
2262 	{120087, 16782083}, {120088, 16782339}, {120089, 16782595}, {120090, 16782851},
2263 	{120091, 16783107}, {120092, 16783363}, {120093, 2}, {120094, 16777219},
2264 	{120095, 16777475}, {120096, 16777731}, {120097, 16777987}, {120098, 16778243},
2265 	{120099, 16778499}, {120100, 16778755}, {120101, 16779011}, {120102, 16779267},
2266 	{120103, 16779523}, {120104, 16779779}, {120105, 16780035}, {120106, 16780291},
2267 	{120107, 16780547}, {120108, 16780803}, {120109, 16781059}, {120110, 16781315},
2268 	{120111, 16781571}, {120112, 16781827}, {120113, 16782083}, {120114, 16782339},
2269 	{120115, 16782595}, {120116, 16782851}, {120117, 16783107}, {120118, 16783363},
2270 	{120119, 16783619}, {120120, 16777219}, {120121, 16777475}, {120122, 2},
2271 	{120123, 16777987}, {120124, 16778243}, {120125, 16778499}, {120126, 16778755},
2272 	{120127, 2}, {120128, 16779267}, {120129, 16779523}, {120130, 16779779},
2273 	{120131, 16780035}, {120132, 16780291}, {120133, 2}, {120134, 16780803},
2274 	{120135, 2}, {120138, 16781827}, {120139, 16782083}, {120140, 16782339},
2275 	{120141, 16782595}, {120142, 16782851}, {120143, 16783107}, {120144, 16783363},
2276 	{120145, 2}, {120146, 16777219}, {120147, 16777475}, {120148, 16777731},
2277 	{120149, 16777987}, {120150, 16778243}, {120151, 16778499}, {120152, 16778755},
2278 	{120153, 16779011}, {120154, 16779267}, {120155, 16779523}, {120156, 16779779},
2279 	{120157, 16780035}, {120158, 16780291}, {120159, 16780547}, {120160, 16780803},
2280 	{120161, 16781059}, {120162, 16781315}, {120163, 16781571}, {120164, 16781827},
2281 	{120165, 16782083}, {120166, 16782339}, {120167, 16782595}, {120168, 16782851},
2282 	{120169, 16783107}, {120170, 16783363}, {120171, 16783619}, {120172, 16777219},
2283 	{120173, 16777475}, {120174, 16777731}, {120175, 16777987}, {120176, 16778243},
2284 	{120177, 16778499}, {120178, 16778755}, {120179, 16779011}, {120180, 16779267},
2285 	{120181, 16779523}, {120182, 16779779}, {120183, 16780035}, {120184, 16780291},
2286 	{120185, 16780547}, {120186, 16780803}, {120187, 16781059}, {120188, 16781315},
2287 	{120189, 16781571}, {120190, 16781827}, {120191, 16782083}, {120192, 16782339},
2288 	{120193, 16782595}, {120194, 16782851}, {120195, 16783107}, {120196, 16783363},
2289 	{120197, 16783619}, {120198, 16777219}, {120199, 16777475}, {120200, 16777731},
2290 	{120201, 16777987}, {120202, 16778243}, {120203, 16778499}, {120204, 16778755},
2291 	{120205, 16779011}, {120206, 16779267}, {120207, 16779523}, {120208, 16779779},
2292 	{120209, 16780035}, {120210, 16780291}, {120211, 16780547}, {120212, 16780803},
2293 	{120213, 16781059}, {120214, 16781315}, {120215, 16781571}, {120216, 16781827},
2294 	{120217, 16782083}, {120218, 16782339}, {120219, 16782595}, {120220, 16782851},
2295 	{120221, 16783107}, {120222, 16783363}, {120223, 16783619}, {120224, 16777219},
2296 	{120225, 16777475}, {120226, 16777731}, {120227, 16777987}, {120228, 16778243},
2297 	{120229, 16778499}, {120230, 16778755}, {120231, 16779011}, {120232, 16779267},
2298 	{120233, 16779523}, {120234, 16779779}, {120235, 16780035}, {120236, 16780291},
2299 	{120237, 16780547}, {120238, 16780803}, {120239, 16781059}, {120240, 16781315},
2300 	{120241, 16781571}, {120242, 16781827}, {120243, 16782083}, {120244, 16782339},
2301 	{120245, 16782595}, {120246, 16782851}, {120247, 16783107}, {120248, 16783363},
2302 	{120249, 16783619}, {120250, 16777219}, {120251, 16777475}, {120252, 16777731},
2303 	{120253, 16777987}, {120254, 16778243}, {120255, 16778499}, {120256, 16778755},
2304 	{120257, 16779011}, {120258, 16779267}, {120259, 16779523}, {120260, 16779779},
2305 	{120261, 16780035}, {120262, 16780291}, {120263, 16780547}, {120264, 16780803},
2306 	{120265, 16781059}, {120266, 16781315}, {120267, 16781571}, {120268, 16781827},
2307 	{120269, 16782083}, {120270, 16782339}, {120271, 16782595}, {120272, 16782851},
2308 	{120273, 16783107}, {120274, 16783363}, {120275, 16783619}, {120276, 16777219},
2309 	{120277, 16777475}, {120278, 16777731}, {120279, 16777987}, {120280, 16778243},
2310 	{120281, 16778499}, {120282, 16778755}, {120283, 16779011}, {120284, 16779267},
2311 	{120285, 16779523}, {120286, 16779779}, {120287, 16780035}, {120288, 16780291},
2312 	{120289, 16780547}, {120290, 16780803}, {120291, 16781059}, {120292, 16781315},
2313 	{120293, 16781571}, {120294, 16781827}, {120295, 16782083}, {120296, 16782339},
2314 	{120297, 16782595}, {120298, 16782851}, {120299, 16783107}, {120300, 16783363},
2315 	{120301, 16783619}, {120302, 16777219}, {120303, 16777475}, {120304, 16777731},
2316 	{120305, 16777987}, {120306, 16778243}, {120307, 16778499}, {120308, 16778755},
2317 	{120309, 16779011}, {120310, 16779267}, {120311, 16779523}, {120312, 16779779},
2318 	{120313, 16780035}, {120314, 16780291}, {120315, 16780547}, {120316, 16780803},
2319 	{120317, 16781059}, {120318, 16781315}, {120319, 16781571}, {120320, 16781827},
2320 	{120321, 16782083}, {120322, 16782339}, {120323, 16782595}, {120324, 16782851},
2321 	{120325, 16783107}, {120326, 16783363}, {120327, 16783619}, {120328, 16777219},
2322 	{120329, 16777475}, {120330, 16777731}, {120331, 16777987}, {120332, 16778243},
2323 	{120333, 16778499}, {120334, 16778755}, {120335, 16779011}, {120336, 16779267},
2324 	{120337, 16779523}, {120338, 16779779}, {120339, 16780035}, {120340, 16780291},
2325 	{120341, 16780547}, {120342, 16780803}, {120343, 16781059}, {120344, 16781315},
2326 	{120345, 16781571}, {120346, 16781827}, {120347, 16782083}, {120348, 16782339},
2327 	{120349, 16782595}, {120350, 16782851}, {120351, 16783107}, {120352, 16783363},
2328 	{120353, 16783619}, {120354, 16777219}, {120355, 16777475}, {120356, 16777731},
2329 	{120357, 16777987}, {120358, 16778243}, {120359, 16778499}, {120360, 16778755},
2330 	{120361, 16779011}, {120362, 16779267}, {120363, 16779523}, {120364, 16779779},
2331 	{120365, 16780035}, {120366, 16780291}, {120367, 16780547}, {120368, 16780803},
2332 	{120369, 16781059}, {120370, 16781315}, {120371, 16781571}, {120372, 16781827},
2333 	{120373, 16782083}, {120374, 16782339}, {120375, 16782595}, {120376, 16782851},
2334 	{120377, 16783107}, {120378, 16783363}, {120379, 16783619}, {120380, 16777219},
2335 	{120381, 16777475}, {120382, 16777731}, {120383, 16777987}, {120384, 16778243},
2336 	{120385, 16778499}, {120386, 16778755}, {120387, 16779011}, {120388, 16779267},
2337 	{120389, 16779523}, {120390, 16779779}, {120391, 16780035}, {120392, 16780291},
2338 	{120393, 16780547}, {120394, 16780803}, {120395, 16781059}, {120396, 16781315},
2339 	{120397, 16781571}, {120398, 16781827}, {120399, 16782083}, {120400, 16782339},
2340 	{120401, 16782595}, {120402, 16782851}, {120403, 16783107}, {120404, 16783363},
2341 	{120405, 16783619}, {120406, 16777219}, {120407, 16777475}, {120408, 16777731},
2342 	{120409, 16777987}, {120410, 16778243}, {120411, 16778499}, {120412, 16778755},
2343 	{120413, 16779011}, {120414, 16779267}, {120415, 16779523}, {120416, 16779779},
2344 	{120417, 16780035}, {120418, 16780291}, {120419, 16780547}, {120420, 16780803},
2345 	{120421, 16781059}, {120422, 16781315}, {120423, 16781571}, {120424, 16781827},
2346 	{120425, 16782083}, {120426, 16782339}, {120427, 16782595}, {120428, 16782851},
2347 	{120429, 16783107}, {120430, 16783363}, {120431, 16783619}, {120432, 16777219},
2348 	{120433, 16777475}, {120434, 16777731}, {120435, 16777987}, {120436, 16778243},
2349 	{120437, 16778499}, {120438, 16778755}, {120439, 16779011}, {120440, 16779267},
2350 	{120441, 16779523}, {120442, 16779779}, {120443, 16780035}, {120444, 16780291},
2351 	{120445, 16780547}, {120446, 16780803}, {120447, 16781059}, {120448, 16781315},
2352 	{120449, 16781571}, {120450, 16781827}, {120451, 16782083}, {120452, 16782339},
2353 	{120453, 16782595}, {120454, 16782851}, {120455, 16783107}, {120456, 16783363},
2354 	{120457, 16783619}, {120458, 16777219}, {120459, 16777475}, {120460, 16777731},
2355 	{120461, 16777987}, {120462, 16778243}, {120463, 16778499}, {120464, 16778755},
2356 	{120465, 16779011}, {120466, 16779267}, {120467, 16779523}, {120468, 16779779},
2357 	{120469, 16780035}, {120470, 16780291}, {120471, 16780547}, {120472, 16780803},
2358 	{120473, 16781059}, {120474, 16781315}, {120475, 16781571}, {120476, 16781827},
2359 	{120477, 16782083}, {120478, 16782339}, {120479, 16782595}, {120480, 16782851},
2360 	{120481, 16783107}, {120482, 16783363}, {120483, 16783619}, {120484, 17944835},
2361 	{120485, 17945091}, {120486, 2}, {120488, 16851715}, {120489, 16851971},
2362 	{120490, 16852227}, {120491, 16852483}, {120492, 16852739}, {120493, 16852995},
2363 	{120494, 16853251}, {120495, 16853507}, {120496, 16846851}, {120497, 16853763},
2364 	{120498, 16854019}, {120499, 16786179}, {120500, 16854275}, {120501, 16854531},
2365 	{120502, 16854787}, {120503, 16855043}, {120504, 16855299}, {120505, 16853507},
2366 	{120506, 16855555}, {120507, 16855811}, {120508, 16856067}, {120509, 16856323},
2367 	{120510, 16856579}, {120511, 16856835}, {120512, 16857091}, {120513, 17945347},
2368 	{120514, 16851715}, {120515, 16851971}, {120516, 16852227}, {120517, 16852483},
2369 	{120518, 16852739}, {120519, 16852995}, {120520, 16853251}, {120521, 16853507},
2370 	{120522, 16846851}, {120523, 16853763}, {120524, 16854019}, {120525, 16786179},
2371 	{120526, 16854275}, {120527, 16854531}, {120528, 16854787}, {120529, 16855043},
2372 	{120530, 16855299}, {120531, 16855555}, {120533, 16855811}, {120534, 16856067},
2373 	{120535, 16856323}, {120536, 16856579}, {120537, 16856835}, {120538, 16857091},
2374 	{120539, 17945603}, {120540, 16852739}, {120541, 16853507}, {120542, 16853763},
2375 	{120543, 16856323}, {120544, 16855299}, {120545, 16855043}, {120546, 16851715},
2376 	{120547, 16851971}, {120548, 16852227}, {120549, 16852483}, {120550, 16852739},
2377 	{120551, 16852995}, {120552, 16853251}, {120553, 16853507}, {120554, 16846851},
2378 	{120555, 16853763}, {120556, 16854019}, {120557, 16786179}, {120558, 16854275},
2379 	{120559, 16854531}, {120560, 16854787}, {120561, 16855043}, {120562, 16855299},
2380 	{120563, 16853507}, {120564, 16855555}, {120565, 16855811}, {120566, 16856067},
2381 	{120567, 16856323}, {120568, 16856579}, {120569, 16856835}, {120570, 16857091},
2382 	{120571, 17945347}, {120572, 16851715}, {120573, 16851971}, {120574, 16852227},
2383 	{120575, 16852483}, {120576, 16852739}, {120577, 16852995}, {120578, 16853251},
2384 	{120579, 16853507}, {120580, 16846851}, {120581, 16853763}, {120582, 16854019},
2385 	{120583, 16786179}, {120584, 16854275}, {120585, 16854531}, {120586, 16854787},
2386 	{120587, 16855043}, {120588, 16855299}, {120589, 16855555}, {120591, 16855811},
2387 	{120592, 16856067}, {120593, 16856323}, {120594, 16856579}, {120595, 16856835},
2388 	{120596, 16857091}, {120597, 17945603}, {120598, 16852739}, {120599, 16853507},
2389 	{120600, 16853763}, {120601, 16856323}, {120602, 16855299}, {120603, 16855043},
2390 	{120604, 16851715}, {120605, 16851971}, {120606, 16852227}, {120607, 16852483},
2391 	{120608, 16852739}, {120609, 16852995}, {120610, 16853251}, {120611, 16853507},
2392 	{120612, 16846851}, {120613, 16853763}, {120614, 16854019}, {120615, 16786179},
2393 	{120616, 16854275}, {120617, 16854531}, {120618, 16854787}, {120619, 16855043},
2394 	{120620, 16855299}, {120621, 16853507}, {120622, 16855555}, {120623, 16855811},
2395 	{120624, 16856067}, {120625, 16856323}, {120626, 16856579}, {120627, 16856835},
2396 	{120628, 16857091}, {120629, 17945347}, {120630, 16851715}, {120631, 16851971},
2397 	{120632, 16852227}, {120633, 16852483}, {120634, 16852739}, {120635, 16852995},
2398 	{120636, 16853251}, {120637, 16853507}, {120638, 16846851}, {120639, 16853763},
2399 	{120640, 16854019}, {120641, 16786179}, {120642, 16854275}, {120643, 16854531},
2400 	{120644, 16854787}, {120645, 16855043}, {120646, 16855299}, {120647, 16855555},
2401 	{120649, 16855811}, {120650, 16856067}, {120651, 16856323}, {120652, 16856579},
2402 	{120653, 16856835}, {120654, 16857091}, {120655, 17945603}, {120656, 16852739},
2403 	{120657, 16853507}, {120658, 16853763}, {120659, 16856323}, {120660, 16855299},
2404 	{120661, 16855043}, {120662, 16851715}, {120663, 16851971}, {120664, 16852227},
2405 	{120665, 16852483}, {120666, 16852739}, {120667, 16852995}, {120668, 16853251},
2406 	{120669, 16853507}, {120670, 16846851}, {120671, 16853763}, {120672, 16854019},
2407 	{120673, 16786179}, {120674, 16854275}, {120675, 16854531}, {120676, 16854787},
2408 	{120677, 16855043}, {120678, 16855299}, {120679, 16853507}, {120680, 16855555},
2409 	{120681, 16855811}, {120682, 16856067}, {120683, 16856323}, {120684, 16856579},
2410 	{120685, 16856835}, {120686, 16857091}, {120687, 17945347}, {120688, 16851715},
2411 	{120689, 16851971}, {120690, 16852227}, {120691, 16852483}, {120692, 16852739},
2412 	{120693, 16852995}, {120694, 16853251}, {120695, 16853507}, {120696, 16846851},
2413 	{120697, 16853763}, {120698, 16854019}, {120699, 16786179}, {120700, 16854275},
2414 	{120701, 16854531}, {120702, 16854787}, {120703, 16855043}, {120704, 16855299},
2415 	{120705, 16855555}, {120707, 16855811}, {120708, 16856067}, {120709, 16856323},
2416 	{120710, 16856579}, {120711, 16856835}, {120712, 16857091}, {120713, 17945603},
2417 	{120714, 16852739}, {120715, 16853507}, {120716, 16853763}, {120717, 16856323},
2418 	{120718, 16855299}, {120719, 16855043}, {120720, 16851715}, {120721, 16851971},
2419 	{120722, 16852227}, {120723, 16852483}, {120724, 16852739}, {120725, 16852995},
2420 	{120726, 16853251}, {120727, 16853507}, {120728, 16846851}, {120729, 16853763},
2421 	{120730, 16854019}, {120731, 16786179}, {120732, 16854275}, {120733, 16854531},
2422 	{120734, 16854787}, {120735, 16855043}, {120736, 16855299}, {120737, 16853507},
2423 	{120738, 16855555}, {120739, 16855811}, {120740, 16856067}, {120741, 16856323},
2424 	{120742, 16856579}, {120743, 16856835}, {120744, 16857091}, {120745, 17945347},
2425 	{120746, 16851715}, {120747, 16851971}, {120748, 16852227}, {120749, 16852483},
2426 	{120750, 16852739}, {120751, 16852995}, {120752, 16853251}, {120753, 16853507},
2427 	{120754, 16846851}, {120755, 16853763}, {120756, 16854019}, {120757, 16786179},
2428 	{120758, 16854275}, {120759, 16854531}, {120760, 16854787}, {120761, 16855043},
2429 	{120762, 16855299}, {120763, 16855555}, {120765, 16855811}, {120766, 16856067},
2430 	{120767, 16856323}, {120768, 16856579}, {120769, 16856835}, {120770, 16857091},
2431 	{120771, 17945603}, {120772, 16852739}, {120773, 16853507}, {120774, 16853763},
2432 	{120775, 16856323}, {120776, 16855299}, {120777, 16855043}, {120778, 16858627},
2433 	{120780, 2}, {120782, 17035523}, {120783, 16786947}, {120784, 16785155},
2434 	{120785, 16785411}, {120786, 16787715}, {120787, 17035779}, {120788, 17036035},
2435 	{120789, 17036291}, {120790, 17036547}, {120791, 17036803}, {120792, 17035523},
2436 	{120793, 16786947}, {120794, 16785155}, {120795, 16785411}, {120796, 16787715},
2437 	{120797, 17035779}, {120798, 17036035}, {120799, 17036291}, {120800, 17036547},
2438 	{120801, 17036803}, {120802, 17035523}, {120803, 16786947}, {120804, 16785155},
2439 	{120805, 16785411}, {120806, 16787715}, {120807, 17035779}, {120808, 17036035},
2440 	{120809, 17036291}, {120810, 17036547}, {120811, 17036803}, {120812, 17035523},
2441 	{120813, 16786947}, {120814, 16785155}, {120815, 16785411}, {120816, 16787715},
2442 	{120817, 17035779}, {120818, 17036035}, {120819, 17036291}, {120820, 17036547},
2443 	{120821, 17036803}, {120822, 17035523}, {120823, 16786947}, {120824, 16785155},
2444 	{120825, 16785411}, {120826, 16787715}, {120827, 17035779}, {120828, 17036035},
2445 	{120829, 17036291}, {120830, 17036547}, {120831, 17036803}, {120832, 1},
2446 	{121484, 2}, {121499, 1}, {121504, 2}, {121505, 1},
2447 	{121520, 2}, {122624, 1}, {122655, 2}, {122661, 1},
2448 	{122667, 2}, {122880, 1}, {122887, 2}, {122888, 1},
2449 	{122905, 2}, {122907, 1}, {122914, 2}, {122915, 1},
2450 	{122917, 2}, {122918, 1}, {122923, 2}, {122928, 16866563},
2451 	{122929, 16866819}, {122930, 16867075}, {122931, 16867331}, {122932, 16867587},
2452 	{122933, 16867843}, {122934, 16868099}, {122935, 16868355}, {122936, 16868611},
2453 	{122937, 16869123}, {122938, 16869379}, {122939, 16869635}, {122940, 16870147},
2454 	{122941, 16870403}, {122942, 16870659}, {122943, 16870915}, {122944, 16871171},
2455 	{122945, 16871427}, {122946, 16871683}, {122947, 16871939}, {122948, 16872195},
2456 	{122949, 16872451}, {122950, 16872707}, {122951, 16873475}, {122952, 16873987},
2457 	{122953, 16874243}, {122954, 17495299}, {122955, 16888835}, {122956, 16864003},
2458 	{122957, 16864515}, {122958, 16890883}, {122959, 16883715}, {122960, 17945859},
2459 	{122961, 16866563}, {122962, 16866819}, {122963, 16867075}, {122964, 16867331},
2460 	{122965, 16867587}, {122966, 16867843}, {122967, 16868099}, {122968, 16868355},
2461 	{122969, 16868611}, {122970, 16869123}, {122971, 16869379}, {122972, 16870147},
2462 	{122973, 16870403}, {122974, 16870915}, {122975, 16871427}, {122976, 16871683},
2463 	{122977, 16871939}, {122978, 16872195}, {122979, 16872451}, {122980, 16872707},
2464 	{122981, 16873219}, {122982, 16873475}, {122983, 16879875}, {122984, 16864003},
2465 	{122985, 16863747}, {122986, 16866307}, {122987, 16883203}, {122988, 17490435},
2466 	{122989, 16883971}, {122990, 2}, {123023, 1}, {123024, 2},
2467 	{123136, 1}, {123181, 2}, {123184, 1}, {123198, 2},
2468 	{123200, 1}, {123210, 2}, {123214, 1}, {123216, 2},
2469 	{123536, 1}, {123567, 2}, {123584, 1}, {123642, 2},
2470 	{123647, 1}, {123648, 2}, {124112, 1}, {124154, 2},
2471 	{124896, 1}, {124903, 2}, {124904, 1}, {124908, 2},
2472 	{124909, 1}, {124911, 2}, {124912, 1}, {124927, 2},
2473 	{124928, 1}, {125125, 2}, {125127, 1}, {125143, 2},
2474 	{125184, 17946115}, {125185, 17946371}, {125186, 17946627}, {125187, 17946883},
2475 	{125188, 17947139}, {125189, 17947395}, {125190, 17947651}, {125191, 17947907},
2476 	{125192, 17948163}, {125193, 17948419}, {125194, 17948675}, {125195, 17948931},
2477 	{125196, 17949187}, {125197, 17949443}, {125198, 17949699}, {125199, 17949955},
2478 	{125200, 17950211}, {125201, 17950467}, {125202, 17950723}, {125203, 17950979},
2479 	{125204, 17951235}, {125205, 17951491}, {125206, 17951747}, {125207, 17952003},
2480 	{125208, 17952259}, {125209, 17952515}, {125210, 17952771}, {125211, 17953027},
2481 	{125212, 17953283}, {125213, 17953539}, {125214, 17953795}, {125215, 17954051},
2482 	{125216, 17954307}, {125217, 17954563}, {125218, 1}, {125260, 2},
2483 	{125264, 1}, {125274, 2}, {125278, 1}, {125280, 2},
2484 	{126065, 1}, {126133, 2}, {126209, 1}, {126270, 2},
2485 	{126464, 16910339}, {126465, 17683715}, {126466, 17681923}, {126467, 17834499},
2486 	{126468, 2}, {126469, 16910851}, {126470, 17731587}, {126471, 17682435},
2487 	{126472, 17700099}, {126473, 16911875}, {126474, 17708803}, {126475, 17711107},
2488 	{126476, 17682947}, {126477, 17718019}, {126478, 17694979}, {126479, 17701635},
2489 	{126480, 17703683}, {126481, 17697027}, {126482, 17706755}, {126483, 17725187},
2490 	{126484, 17745155}, {126485, 17686787}, {126486, 17689859}, {126487, 17684995},
2491 	{126488, 17724675}, {126489, 17698051}, {126490, 17701123}, {126491, 17702659},
2492 	{126492, 17954819}, {126493, 17673475}, {126494, 17955075}, {126495, 17955331},
2493 	{126496, 2}, {126497, 17683715}, {126498, 17681923}, {126499, 2},
2494 	{126500, 17721091}, {126501, 2}, {126503, 17682435}, {126504, 2},
2495 	{126505, 16911875}, {126506, 17708803}, {126507, 17711107}, {126508, 17682947},
2496 	{126509, 17718019}, {126510, 17694979}, {126511, 17701635}, {126512, 17703683},
2497 	{126513, 17697027}, {126514, 17706755}, {126515, 2}, {126516, 17745155},
2498 	{126517, 17686787}, {126518, 17689859}, {126519, 17684995}, {126520, 2},
2499 	{126521, 17698051}, {126522, 2}, {126523, 17702659}, {126524, 2},
2500 	{126530, 17681923}, {126531, 2}, {126535, 17682435}, {126536, 2},
2501 	{126537, 16911875}, {126538, 2}, {126539, 17711107}, {126540, 2},
2502 	{126541, 17718019}, {126542, 17694979}, {126543, 17701635}, {126544, 2},
2503 	{126545, 17697027}, {126546, 17706755}, {126547, 2}, {126548, 17745155},
2504 	{126549, 2}, {126551, 17684995}, {126552, 2}, {126553, 17698051},
2505 	{126554, 2}, {126555, 17702659}, {126556, 2}, {126557, 17673475},
2506 	{126558, 2}, {126559, 17955331}, {126560, 2}, {126561, 17683715},
2507 	{126562, 17681923}, {126563, 2}, {126564, 17721091}, {126565, 2},
2508 	{126567, 17682435}, {126568, 17700099}, {126569, 16911875}, {126570, 17708803},
2509 	{126571, 2}, {126572, 17682947}, {126573, 17718019}, {126574, 17694979},
2510 	{126575, 17701635}, {126576, 17703683}, {126577, 17697027}, {126578, 17706755},
2511 	{126579, 2}, {126580, 17745155}, {126581, 17686787}, {126582, 17689859},
2512 	{126583, 17684995}, {126584, 2}, {126585, 17698051}, {126586, 17701123},
2513 	{126587, 17702659}, {126588, 17954819}, {126589, 2}, {126590, 17955075},
2514 	{126591, 2}, {126592, 16910339}, {126593, 17683715}, {126594, 17681923},
2515 	{126595, 17834499}, {126596, 17721091}, {126597, 16910851}, {126598, 17731587},
2516 	{126599, 17682435}, {126600, 17700099}, {126601, 16911875}, {126602, 2},
2517 	{126603, 17711107}, {126604, 17682947}, {126605, 17718019}, {126606, 17694979},
2518 	{126607, 17701635}, {126608, 17703683}, {126609, 17697027}, {126610, 17706755},
2519 	{126611, 17725187}, {126612, 17745155}, {126613, 17686787}, {126614, 17689859},
2520 	{126615, 17684995}, {126616, 17724675}, {126617, 17698051}, {126618, 17701123},
2521 	{126619, 17702659}, {126620, 2}, {126625, 17683715}, {126626, 17681923},
2522 	{126627, 17834499}, {126628, 2}, {126629, 16910851}, {126630, 17731587},
2523 	{126631, 17682435}, {126632, 17700099}, {126633, 16911875}, {126634, 2},
2524 	{126635, 17711107}, {126636, 17682947}, {126637, 17718019}, {126638, 17694979},
2525 	{126639, 17701635}, {126640, 17703683}, {126641, 17697027}, {126642, 17706755},
2526 	{126643, 17725187}, {126644, 17745155}, {126645, 17686787}, {126646, 17689859},
2527 	{126647, 17684995}, {126648, 17724675}, {126649, 17698051}, {126650, 17701123},
2528 	{126651, 17702659}, {126652, 2}, {126704, 1}, {126706, 2},
2529 	{126976, 1}, {127020, 2}, {127024, 1}, {127124, 2},
2530 	{127136, 1}, {127151, 2}, {127153, 1}, {127168, 2},
2531 	{127169, 1}, {127184, 2}, {127185, 1}, {127222, 2},
2532 	{127233, 34732803}, {127234, 34733315}, {127235, 34733827}, {127236, 34734339},
2533 	{127237, 34734851}, {127238, 34735363}, {127239, 34735875}, {127240, 34736387},
2534 	{127241, 34736899}, {127242, 34737411}, {127243, 1}, {127248, 50644995},
2535 	{127249, 50645763}, {127250, 50646531}, {127251, 50647299}, {127252, 50648067},
2536 	{127253, 50648835}, {127254, 50649603}, {127255, 50650371}, {127256, 50651139},
2537 	{127257, 50651907}, {127258, 50652675}, {127259, 50653443}, {127260, 50654211},
2538 	{127261, 50654979}, {127262, 50655747}, {127263, 50656515}, {127264, 50657283},
2539 	{127265, 50658051}, {127266, 50658819}, {127267, 50659587}, {127268, 50660355},
2540 	{127269, 50661123}, {127270, 50661891}, {127271, 50662659}, {127272, 50663427},
2541 	{127273, 50664195}, {127274, 51515139}, {127275, 16777731}, {127276, 16781571},
2542 	{127277, 33554947}, {127278, 34738691}, {127279, 1}, {127280, 16777219},
2543 	{127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243},
2544 	{127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267},
2545 	{127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291},
2546 	{127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315},
2547 	{127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339},
2548 	{127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363},
2549 	{127305, 16783619}, {127306, 34739203}, {127307, 34226691}, {127308, 34739715},
2550 	{127309, 33752579}, {127310, 51517443}, {127311, 34740995}, {127312, 1},
2551 	{127338, 34209539}, {127339, 34189571}, {127340, 34741507}, {127341, 1},
2552 	{127376, 34742019}, {127377, 1}, {127406, 2}, {127462, 1},
2553 	{127488, 34742531}, {127489, 34743043}, {127490, 17307907}, {127491, 2},
2554 	{127504, 17157891}, {127505, 17966339}, {127506, 17966595}, {127507, 17351683},
2555 	{127508, 17143299}, {127509, 17966851}, {127510, 17967107}, {127511, 17225475},
2556 	{127512, 17967363}, {127513, 17967619}, {127514, 17967875}, {127515, 17584643},
2557 	{127516, 17968131}, {127517, 17968387}, {127518, 17968643}, {127519, 17968899},
2558 	{127520, 17969155}, {127521, 17969411}, {127522, 17167107}, {127523, 17969667},
2559 	{127524, 17969923}, {127525, 17970179}, {127526, 17970435}, {127527, 17970691},
2560 	{127528, 17970947}, {127529, 17141763}, {127530, 17223427}, {127531, 17971203},
2561 	{127532, 17288707}, {127533, 17224195}, {127534, 17288963}, {127535, 17971459},
2562 	{127536, 17181443}, {127537, 17971715}, {127538, 17971971}, {127539, 17972227},
2563 	{127540, 17972483}, {127541, 17972739}, {127542, 17264387}, {127543, 17160451},
2564 	{127544, 17972995}, {127545, 17973251}, {127546, 17973507}, {127547, 17973763},
2565 	{127548, 2}, {127552, 51528451}, {127553, 51529219}, {127554, 51529987},
2566 	{127555, 51530755}, {127556, 51531523}, {127557, 51532291}, {127558, 51533059},
2567 	{127559, 51533827}, {127560, 51534595}, {127561, 2}, {127568, 17980931},
2568 	{127569, 17981187}, {127570, 2}, {127584, 1}, {127590, 2},
2569 	{127744, 1}, {128728, 2}, {128732, 1}, {128749, 2},
2570 	{128752, 1}, {128765, 2}, {128768, 1}, {128887, 2},
2571 	{128891, 1}, {128986, 2}, {128992, 1}, {129004, 2},
2572 	{129008, 1}, {129009, 2}, {129024, 1}, {129036, 2},
2573 	{129040, 1}, {129096, 2}, {129104, 1}, {129114, 2},
2574 	{129120, 1}, {129160, 2}, {129168, 1}, {129198, 2},
2575 	{129200, 1}, {129202, 2}, {129280, 1}, {129620, 2},
2576 	{129632, 1}, {129646, 2}, {129648, 1}, {129661, 2},
2577 	{129664, 1}, {129673, 2}, {129680, 1}, {129726, 2},
2578 	{129727, 1}, {129734, 2}, {129742, 1}, {129756, 2},
2579 	{129760, 1}, {129769, 2}, {129776, 1}, {129785, 2},
2580 	{129792, 1}, {129939, 2}, {129940, 1}, {129995, 2},
2581 	{130032, 17035523}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2582 	{130036, 16787715}, {130037, 17035779}, {130038, 17036035}, {130039, 17036291},
2583 	{130040, 17036547}, {130041, 17036803}, {130042, 2}, {131072, 1},
2584 	{173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2585 	{178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2586 	{191457, 2}, {194560, 17981443}, {194561, 17981699}, {194562, 17981955},
2587 	{194563, 17982211}, {194564, 17982467}, {194565, 17608451}, {194566, 17982723},
2588 	{194567, 17982979}, {194568, 17983235}, {194569, 17983491}, {194570, 17608707},
2589 	{194571, 17983747}, {194572, 17984003}, {194573, 17984259}, {194574, 17608963},
2590 	{194575, 17984515}, {194576, 17984771}, {194577, 17985027}, {194578, 17985283},
2591 	{194579, 17985539}, {194580, 17985795}, {194581, 17968643}, {194582, 17986051},
2592 	{194583, 17986307}, {194584, 17986563}, {194585, 17986819}, {194586, 17987075},
2593 	{194587, 17623043}, {194588, 17987331}, {194589, 17145859}, {194590, 17987587},
2594 	{194591, 17987843}, {194592, 17988099}, {194593, 17988355}, {194594, 17973251},
2595 	{194595, 17988611}, {194596, 17988867}, {194597, 17624323}, {194598, 17609219},
2596 	{194599, 17609475}, {194600, 17624579}, {194601, 17989123}, {194602, 17989379},
2597 	{194603, 17562883}, {194604, 17989635}, {194605, 17609731}, {194606, 17989891},
2598 	{194607, 17990147}, {194608, 17990403}, {194609, 17990659}, {194612, 17990915},
2599 	{194613, 17991171}, {194614, 17991427}, {194615, 17991683}, {194616, 17991939},
2600 	{194617, 17992195}, {194618, 17992451}, {194619, 17992707}, {194620, 17992963},
2601 	{194621, 17993219}, {194622, 17993475}, {194623, 17993731}, {194624, 17993987},
2602 	{194625, 17994243}, {194626, 17994499}, {194627, 17994755}, {194628, 17995011},
2603 	{194629, 17995267}, {194631, 17625091}, {194632, 17995523}, {194633, 17995779},
2604 	{194634, 17996035}, {194635, 17996291}, {194636, 17610243}, {194637, 17996547},
2605 	{194638, 17996803}, {194639, 17997059}, {194640, 17600003}, {194641, 17997315},
2606 	{194642, 17997571}, {194643, 17997827}, {194644, 17998083}, {194645, 17998339},
2607 	{194646, 17998595}, {194647, 17998851}, {194648, 17999107}, {194649, 17999363},
2608 	{194650, 17999619}, {194651, 17999875}, {194652, 18000131}, {194653, 17966851},
2609 	{194654, 18000387}, {194655, 18000643}, {194656, 18000899}, {194657, 18001155},
2610 	{194658, 18001411}, {194659, 18001667}, {194660, 18001923}, {194661, 18002179},
2611 	{194662, 18002435}, {194663, 18002691}, {194664, 2}, {194665, 18002947},
2612 	{194666, 18003203}, {194668, 18003459}, {194669, 18003715}, {194670, 18003971},
2613 	{194671, 17561859}, {194672, 18004227}, {194673, 18004483}, {194674, 18004739},
2614 	{194675, 18004995}, {194676, 2}, {194677, 17152515}, {194678, 18005251},
2615 	{194679, 18005507}, {194680, 17153027}, {194681, 18005763}, {194682, 18006019},
2616 	{194683, 18006275}, {194684, 18006531}, {194685, 18006787}, {194686, 18007043},
2617 	{194687, 18007299}, {194688, 18007555}, {194689, 18007811}, {194690, 18008067},
2618 	{194691, 18008323}, {194692, 18008579}, {194693, 18008835}, {194694, 18009091},
2619 	{194695, 18009347}, {194696, 18009603}, {194697, 18009859}, {194698, 18010115},
2620 	{194699, 18010371}, {194700, 18010627}, {194701, 18010883}, {194702, 17548547},
2621 	{194703, 18011139}, {194704, 17155587}, {194705, 18011395}, {194707, 18011651},
2622 	{194708, 18011907}, {194710, 18012163}, {194711, 18012419}, {194712, 18012675},
2623 	{194713, 18012931}, {194714, 18013187}, {194715, 18013443}, {194716, 18013699},
2624 	{194717, 18013955}, {194718, 18014211}, {194719, 18014467}, {194720, 18014723},
2625 	{194721, 18014979}, {194722, 18015235}, {194723, 17611523}, {194724, 18015491},
2626 	{194725, 18015747}, {194726, 18016003}, {194727, 18016259}, {194728, 17628163},
2627 	{194729, 18016259}, {194730, 18016515}, {194731, 17612035}, {194732, 18016771},
2628 	{194733, 18017027}, {194734, 18017283}, {194735, 18017539}, {194736, 17612291},
2629 	{194737, 17541635}, {194738, 17414915}, {194739, 18017795}, {194740, 18018051},
2630 	{194741, 18018307}, {194742, 18018563}, {194743, 18018819}, {194744, 18019075},
2631 	{194745, 18019331}, {194746, 18019587}, {194747, 18019843}, {194748, 18020099},
2632 	{194749, 18020355}, {194750, 18020611}, {194751, 18020867}, {194752, 18021123},
2633 	{194753, 18021379}, {194754, 18021635}, {194755, 18021891}, {194756, 18022147},
2634 	{194757, 18022403}, {194758, 18022659}, {194759, 18022915}, {194760, 17612547},
2635 	{194761, 18023171}, {194762, 18023427}, {194763, 18023683}, {194764, 18023939},
2636 	{194765, 18024195}, {194766, 18024451}, {194767, 17613059}, {194768, 18024707},
2637 	{194769, 18024963}, {194770, 18025219}, {194771, 18025475}, {194772, 18025731},
2638 	{194773, 18025987}, {194774, 18026243}, {194775, 18026499}, {194776, 17548803},
2639 	{194777, 17630211}, {194778, 18026755}, {194779, 18027011}, {194780, 18027267},
2640 	{194781, 18027523}, {194782, 18027779}, {194783, 18028035}, {194784, 18028291},
2641 	{194785, 18028547}, {194786, 17613315}, {194787, 18028803}, {194788, 18029059},
2642 	{194789, 18029315}, {194790, 18029571}, {194791, 17640963}, {194792, 18029827},
2643 	{194793, 18030083}, {194794, 18030339}, {194795, 18030595}, {194796, 18030851},
2644 	{194797, 18031107}, {194798, 18031363}, {194799, 18031619}, {194800, 18031875},
2645 	{194801, 18032131}, {194802, 18032387}, {194803, 18032643}, {194804, 18032899},
2646 	{194805, 17566211}, {194806, 18033155}, {194807, 18033411}, {194808, 18033667},
2647 	{194809, 18033923}, {194810, 18034179}, {194811, 18034435}, {194812, 18034691},
2648 	{194813, 18034947}, {194814, 18035203}, {194815, 18035459}, {194816, 18035715},
2649 	{194817, 17613571}, {194818, 17587203}, {194819, 18035971}, {194820, 18036227},
2650 	{194821, 18036483}, {194822, 18036739}, {194823, 18036995}, {194824, 18037251},
2651 	{194825, 18037507}, {194826, 18037763}, {194827, 17630979}, {194828, 18038019},
2652 	{194829, 18038275}, {194830, 18038531}, {194831, 18038787}, {194832, 18039043},
2653 	{194833, 18039299}, {194834, 18039555}, {194835, 18039811}, {194836, 17631235},
2654 	{194837, 18040067}, {194838, 18040323}, {194839, 18040579}, {194840, 18040835},
2655 	{194841, 18041091}, {194842, 18041347}, {194843, 18041603}, {194844, 18041859},
2656 	{194845, 18042115}, {194846, 18042371}, {194847, 2}, {194848, 18042627},
2657 	{194849, 17631747}, {194850, 18042883}, {194851, 18043139}, {194852, 18043395},
2658 	{194853, 18043651}, {194854, 18043907}, {194855, 18044163}, {194856, 18044419},
2659 	{194857, 18044675}, {194858, 18044931}, {194859, 18045187}, {194860, 18045443},
2660 	{194862, 18045699}, {194863, 18045955}, {194864, 17632259}, {194865, 18046211},
2661 	{194866, 18046467}, {194867, 18046723}, {194868, 18046979}, {194869, 18047235},
2662 	{194870, 18047491}, {194871, 18047747}, {194872, 17562627}, {194873, 18048003},
2663 	{194874, 18048259}, {194875, 18048515}, {194876, 18048771}, {194877, 18049027},
2664 	{194878, 18049283}, {194879, 18049539}, {194880, 17633795}, {194881, 18049795},
2665 	{194882, 18050051}, {194883, 18050307}, {194884, 18050563}, {194885, 18050819},
2666 	{194886, 18051075}, {194888, 17634051}, {194889, 17641475}, {194890, 18051331},
2667 	{194891, 18051587}, {194892, 18051843}, {194893, 18052099}, {194894, 18052355},
2668 	{194895, 17553155}, {194896, 17634563}, {194897, 18052611}, {194898, 18052867},
2669 	{194899, 17616131}, {194900, 18053123}, {194901, 18053379}, {194902, 17605123},
2670 	{194903, 18053635}, {194904, 18053891}, {194905, 17616899}, {194906, 18054147},
2671 	{194907, 18054403}, {194908, 18054659}, {194909, 18054915}, {194911, 2},
2672 	{194912, 18055171}, {194913, 18055427}, {194914, 18055683}, {194915, 18055939},
2673 	{194916, 18056195}, {194917, 18056451}, {194918, 18056707}, {194919, 18056963},
2674 	{194920, 18057219}, {194921, 18057475}, {194922, 18057731}, {194923, 18057987},
2675 	{194924, 18058243}, {194925, 18058499}, {194926, 18058755}, {194927, 18059011},
2676 	{194928, 18059267}, {194929, 18059523}, {194930, 18059779}, {194931, 18060035},
2677 	{194932, 18060291}, {194933, 18060547}, {194934, 18060803}, {194935, 18061059},
2678 	{194936, 18061315}, {194937, 18061571}, {194938, 17618435}, {194939, 18061827},
2679 	{194940, 18062083}, {194941, 18062339}, {194942, 18062595}, {194943, 18062851},
2680 	{194944, 18063107}, {194945, 18063363}, {194946, 18063619}, {194947, 18063875},
2681 	{194948, 18064131}, {194949, 18064387}, {194950, 18064643}, {194951, 18064899},
2682 	{194952, 18065155}, {194953, 18065411}, {194954, 18065667}, {194955, 18011651},
2683 	{194956, 18065923}, {194957, 18066179}, {194958, 18066435}, {194959, 18066691},
2684 	{194960, 18066947}, {194961, 18067203}, {194962, 18067459}, {194963, 18067715},
2685 	{194964, 18067971}, {194965, 18068227}, {194966, 18068483}, {194967, 18068739},
2686 	{194968, 17566979}, {194969, 18068995}, {194970, 18069251}, {194971, 18069507},
2687 	{194972, 18069763}, {194973, 18070019}, {194974, 18070275}, {194975, 17619203},
2688 	{194976, 18070531}, {194977, 18070787}, {194978, 18071043}, {194979, 18071299},
2689 	{194980, 18071555}, {194981, 18071811}, {194982, 18072067}, {194983, 18072323},
2690 	{194984, 18072579}, {194985, 18072835}, {194986, 18073091}, {194987, 18073347},
2691 	{194988, 18073603}, {194989, 18073859}, {194990, 18074115}, {194991, 18074371},
2692 	{194992, 18074627}, {194993, 18074883}, {194994, 18075139}, {194995, 18075395},
2693 	{194996, 17551875}, {194997, 18075651}, {194998, 18075907}, {194999, 18076163},
2694 	{195000, 18076419}, {195001, 18076675}, {195002, 18076931}, {195003, 17636355},
2695 	{195004, 18077187}, {195005, 18077443}, {195006, 18077699}, {195007, 2},
2696 	{195008, 18077955}, {195009, 18078211}, {195010, 18078467}, {195011, 18078723},
2697 	{195012, 17178627}, {195013, 18078979}, {195014, 18079235}, {195015, 18079491},
2698 	{195016, 18079747}, {195017, 18080003}, {195018, 18080259}, {195019, 18080515},
2699 	{195020, 18080771}, {195021, 18081027}, {195022, 18081283}, {195023, 18081539},
2700 	{195024, 17637635}, {195025, 17637891}, {195026, 17180419}, {195027, 18081795},
2701 	{195028, 18082051}, {195029, 18082307}, {195030, 18082563}, {195031, 18082819},
2702 	{195032, 18083075}, {195033, 18083331}, {195034, 18083587}, {195035, 18083843},
2703 	{195036, 18084099}, {195037, 18084355}, {195038, 18084611}, {195039, 17638147},
2704 	{195040, 18084867}, {195041, 18085123}, {195042, 18085379}, {195043, 18085635},
2705 	{195044, 18085891}, {195045, 18086147}, {195046, 18086403}, {195047, 18086659},
2706 	{195048, 18086915}, {195049, 18087171}, {195050, 18087427}, {195051, 18087683},
2707 	{195052, 18087939}, {195053, 18088195}, {195054, 18088451}, {195055, 18088707},
2708 	{195056, 18088963}, {195057, 18089219}, {195058, 18089475}, {195059, 18089731},
2709 	{195060, 18089987}, {195061, 18090243}, {195062, 18090499}, {195063, 18090755},
2710 	{195064, 18091011}, {195065, 18091267}, {195066, 18091523}, {195067, 18091779},
2711 	{195068, 18092035}, {195069, 18092291}, {195070, 17639683}, {195072, 18092547},
2712 	{195073, 18092803}, {195074, 18093059}, {195075, 18093315}, {195076, 18093571},
2713 	{195077, 18093827}, {195078, 18094083}, {195079, 18094339}, {195080, 18094595},
2714 	{195081, 18094851}, {195082, 17639939}, {195083, 18095107}, {195084, 18095363},
2715 	{195085, 18095619}, {195086, 18095875}, {195087, 18096131}, {195088, 18096387},
2716 	{195089, 18096643}, {195090, 18096899}, {195091, 18097155}, {195092, 18097411},
2717 	{195093, 17192707}, {195094, 18097667}, {195095, 17193731}, {195096, 18097923},
2718 	{195097, 18098179}, {195098, 18098435}, {195099, 18098691}, {195100, 17195011},
2719 	{195101, 18098947}, {195102, 2}, {196608, 1}, {201547, 2},
2720 	{201552, 1}, {205744, 2}, {917760, 0}, {918000, 2}
2721 };
2722 
2723 
2724 } // namespace ada::idna
2725 #endif // ADA_IDNA_TABLES_H
2726 
2727 /* end file src/mapping_tables.cpp */
2728 
2729 namespace ada::idna {
2730 
2731 // This can be greatly accelerated. For now we just use a simply
2732 // binary search. In practice, you should *not* do that.
find_range_index(uint32_t key)2733 uint32_t find_range_index(uint32_t key) {
2734   ////////////////
2735   // This could be implemented with std::lower_bound, but we roll our own
2736   // because we want to allow further optimizations in the future.
2737   ////////////////
2738   uint32_t len = std::size(table);
2739   uint32_t low = 0;
2740   uint32_t high = len - 1;
2741   while (low <= high) {
2742     uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2743     uint32_t middle_value = table[middle_index][0];
2744     if (middle_value < key) {
2745       low = middle_index + 1;
2746     } else if (middle_value > key) {
2747       high = middle_index - 1;
2748     } else {
2749       return middle_index;  // perfect match
2750     }
2751   }
2752   return low == 0 ? 0 : low - 1;
2753 }
2754 
ascii_has_upper_case(char * input,size_t length)2755 bool ascii_has_upper_case(char* input, size_t length) {
2756   auto broadcast = [](uint8_t v) -> uint64_t {
2757     return 0x101010101010101ull * v;
2758   };
2759   uint64_t broadcast_80 = broadcast(0x80);
2760   uint64_t broadcast_Ap = broadcast(128 - 'A');
2761   uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2762   size_t i = 0;
2763 
2764   uint64_t runner{0};
2765 
2766   for (; i + 7 < length; i += 8) {
2767     uint64_t word{};
2768     memcpy(&word, input + i, sizeof(word));
2769     runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2770   }
2771   if (i < length) {
2772     uint64_t word{};
2773     memcpy(&word, input + i, length - i);
2774     runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2775   }
2776   return runner != 0;
2777 }
2778 
ascii_map(char * input,size_t length)2779 void ascii_map(char* input, size_t length) {
2780   auto broadcast = [](uint8_t v) -> uint64_t {
2781     return 0x101010101010101ull * v;
2782   };
2783   uint64_t broadcast_80 = broadcast(0x80);
2784   uint64_t broadcast_Ap = broadcast(128 - 'A');
2785   uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2786   size_t i = 0;
2787 
2788   for (; i + 7 < length; i += 8) {
2789     uint64_t word{};
2790     memcpy(&word, input + i, sizeof(word));
2791     word ^=
2792         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2793     memcpy(input + i, &word, sizeof(word));
2794   }
2795   if (i < length) {
2796     uint64_t word{};
2797     memcpy(&word, input + i, length - i);
2798     word ^=
2799         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2800     memcpy(input + i, &word, length - i);
2801   }
2802 }
2803 
2804 // Map the characters according to IDNA, returning the empty string on error.
map(std::u32string_view input)2805 std::u32string map(std::u32string_view input) {
2806   //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2807   //  For each code point in the domain_name string, look up the status
2808   //  value in Section 5, [IDNA Mapping
2809   //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2810   //  and take the following actions:
2811   //    * disallowed: Leave the code point unchanged in the string, and
2812   //    record that there was an error.
2813   //    * ignored: Remove the code point from the string. This is
2814   //    equivalent to mapping the code point to an empty string.
2815   //    * mapped: Replace the code point in the string by the value for
2816   //    the mapping in Section 5, [IDNA Mapping
2817   //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2818   //    * valid: Leave the code point unchanged in the string.
2819   static std::u32string error = U"";
2820   std::u32string answer;
2821   answer.reserve(input.size());
2822   for (char32_t x : input) {
2823     size_t index = find_range_index(x);
2824     uint32_t descriptor = table[index][1];
2825     uint8_t code = uint8_t(descriptor);
2826     switch (code) {
2827       case 0:
2828         break;  // nothing to do, ignored
2829       case 1:
2830         answer.push_back(x);  // valid, we just copy it to output
2831         break;
2832       case 2:
2833         return error;  // disallowed
2834       // case 3 :
2835       default:
2836         // We have a mapping
2837         {
2838           size_t char_count = (descriptor >> 24);
2839           uint16_t char_index = uint16_t(descriptor >> 8);
2840           for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2841             answer.push_back(mappings[idx]);
2842           }
2843         }
2844     }
2845   }
2846   return answer;
2847 }
2848 }  // namespace ada::idna
2849 /* end file src/mapping.cpp */
2850 /* begin file src/normalization.cpp */
2851 /* begin file src/normalization_tables.cpp */
2852 // IDNA  15.0.0
2853 
2854 // clang-format off
2855 #ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2856 #define ADA_IDNA_NORMALIZATION_TABLES_H
2857 #include <cstdint>
2858 
2859 /**
2860  * Unicode Standard Annex #15
2861  *
2862  * UNICODE NORMALIZATION FORMS
2863  * https://www.unicode.org/reports/tr15/
2864  *
2865  * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2866  */
2867 
2868 namespace ada::idna {
2869 
2870 const uint8_t decomposition_index[4352] = {
2871     0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2872     7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2873     7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2874     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2875     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2876     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2877     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2878     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2879     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  34, 35, 7,  7,  7,
2880     36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2881     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2882     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2883     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2884     7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2885     7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2886     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2887     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2888     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2889     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2890     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2891     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2892     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2893     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2894     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2895     7,  7,  7,  7,  7,  7,  7,  7,  7,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2896     7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2897     59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2898     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2899     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2900     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2901     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2902     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2903     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2904     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2905     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2906     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2907     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2908     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2909     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2910     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2911     64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2912     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2913     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2914     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2915     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2916     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2917     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2918     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2919     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2920     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2922     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2923     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2924     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2925     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2926     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2927     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2928     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2929     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2930     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2931     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2932     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2933     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2934     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2935     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2936     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2937     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2938     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2939     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2940     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2941     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2942     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2943     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2944     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2945     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2946     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2947     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2948     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100     7};
3101 
3102 const uint16_t decomposition_block[67][257] = {
3103     {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3104      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3105      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3106      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3107      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3108      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3109      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3110      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3111      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3112      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3113      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3114      8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3115      37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3116      124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3117      228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3118      316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3119      428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3120      516, 524},
3121     {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3122      620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3123      700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3124      796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3125      876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3126      956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3127      1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3128      1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3129      1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3130      1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3131      1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3132      1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3133      1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3134      1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3135      1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3136      1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3137      1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3138      1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3139      1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3140      1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3141      1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3142      1948, 1956, 1964, 1972, 1980},
3143     {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3144      2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3145      2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3146      2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3147      2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3148      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3149      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3150      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3151      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3152      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3153      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3154      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3155      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3156      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3157      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3158      2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3159      2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3160      2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3161      2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3162      2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3163      2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3164      2460, 2460, 2460, 2460, 2460},
3165     {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3166      2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3167      2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3168      2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3169      2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3170      2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3171      2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3172      2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3173      2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3174      2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3175      2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3176      2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3177      2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3178      2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3179      2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3180      2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3181      2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3182      2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3183      2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3184      2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3185      2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3186      2744, 2744, 2744, 2744, 2744},
3187     {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3188      2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3189      2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3190      2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3191      2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3192      2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3193      2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3194      2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3195      2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3196      2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3197      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3198      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3199      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3200      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3201      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3202      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3203      2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3204      2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3205      2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3206      3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3207      3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3208      3160, 3160, 3160, 3160, 3160},
3209     {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3210      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3211      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3212      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3213      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3214      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3215      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3216      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3217      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3218      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3219      3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3220      3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3221      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3222      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3223      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3224      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3225      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3226      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3227      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3228      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3229      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3230      3168, 3168, 3168, 3168, 3168},
3231     {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3232      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3233      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3234      3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3235      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3236      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3237      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3238      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3239      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3240      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3241      3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3242      3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3243      3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3244      3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3245      3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3246      3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3247      3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3248      3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3249      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3250      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3251      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3252      3264, 3264, 3264, 3264, 3264},
3253     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3254      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3255      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3256      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3257      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3258      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3259      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3260      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3261      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3262      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3263      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3264     {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3265      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3266      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3267      3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3268      3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3269      3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3270      3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3271      3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3272      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3273      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3274      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3275      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3276      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3277      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3278      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3279      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3280      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3281      3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3282      3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3283      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3284      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3285      3392, 3392, 3392, 3392, 3392},
3286     {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3287      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3288      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3289      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3290      3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3291      3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3292      3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3293      3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3294      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3295      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3296      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3297      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3298      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3299      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3300      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3301      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3302      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3303      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3304      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3305      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3306      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3307      3440, 3440, 3440, 3440, 3440},
3308     {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3309      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3310      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3311      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3312      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3313      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3314      3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3315      3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3316      3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3317      3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3318      3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3319      3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3320      3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3321      3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3322      3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3323      3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3324      3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3325      3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3326      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3327      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3328      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3329      3512, 3512, 3512, 3512, 3512},
3330     {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3331      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3332      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3333      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3334      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3335      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3336      3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3337      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3338      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3339      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3340      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3341      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3342      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3343      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3344      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3345      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3346      3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3347      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3348      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3349      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3350      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3351      3564, 3564, 3564, 3564, 3564},
3352     {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3353      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3354      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3355      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3356      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3357      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3358      3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3359      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3360      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3361      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3362      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3363      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3364      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3365      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3366      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3367      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3368      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3369      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3370      3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3371      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3372      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3373      3624, 3624, 3624, 3624, 3624},
3374     {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3375      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3376      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3377      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3378      3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3379      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3380      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3381      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3382      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3383      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3384      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3385      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3386      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3387      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3388      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3389      3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3390      3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3391      3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3392      3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3393      3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3394      3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3395      3656, 3656, 3656, 3656, 3656},
3396     {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3397      3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3398      3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3399      3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3400      3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3401      3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3402      3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3403      3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3404      3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3405      3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3406      3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3407      3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3408      3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3409      3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3410      3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3411      3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3412      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3413      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3414      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3415      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3416      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3417      3820, 3820, 3820, 3820, 3820},
3418     {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3419      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3420      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3421      3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3422      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3423      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3424      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3425      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3426      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3427      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3428      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3429      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3430      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3431      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3432      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3433      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3434      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3435      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3436      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3437      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3438      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3439      3829, 3832, 3832, 3832, 3832},
3440     {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3441      3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3442      3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3443      3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3444      3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3445      3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3446      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3447      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3448      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3449      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3450      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3451      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3452      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3453      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3454      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3455      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3456      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3457      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3458      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3459      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3460      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3461      3920, 3920, 3920, 3920, 3920},
3462     {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3463      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3464      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3465      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3466      3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3467      3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3468      4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3469      4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3470      4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3471      4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3472      4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3473      4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3474      4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3475      4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3476      4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3477      4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3478      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3479      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3480      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3481      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3482      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3483      4312, 4312, 4312, 4312, 4312},
3484     {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3485      4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3486      4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3487      4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3488      4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3489      4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3490      4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3491      5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3492      5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3493      5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3494      5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3495      5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3496      5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3497      5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3498      5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3499      5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3500      6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3501      6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3502      6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3503      6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3504      6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3505      6648, 6648, 6648, 6648, 6648},
3506     {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3507      6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3508      6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3509      6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3510      7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3511      7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3512      7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3513      7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3514      7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3515      7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3516      7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3517      7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3518      8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3519      8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3520      8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3521      8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3522      8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3523      8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3524      8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3525      8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3526      9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3527      9168, 9178, 9181, 9188, 9190},
3528     {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3529      9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3530      9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3531      9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3532      9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3533      9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3534      9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3535      9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3536      9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3537      9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3538      9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3539      9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3540      9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3541      9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3542      9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3543      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3544      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3545      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3546      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3547      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3548      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3549      9548, 9548, 9548, 9548, 9549},
3550     {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3551      9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3552      9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3553      9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3554      9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3555      9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3556      9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3557      9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3558      9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3559      9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3560      10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3561      10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3562      10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3563      10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3564      10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3565      10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3566      10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3567      10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3568      10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3569      10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3570      10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3571      10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3572      10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3573      10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3574      10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3575      10336, 10336, 10336, 10336, 10336, 10336, 10336},
3576     {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3577      10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3578      10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3579      10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3580      10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3581      10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3582      10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3583      10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3584      10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3585      10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3586      10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3587      10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3588      10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3589      10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3590      10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3591      10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3592      10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3593      10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3594      10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3595      10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3596      10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3597      10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3598      10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3599      10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3600      10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3601      10680, 10680, 10680, 10680, 10680, 10680, 10680},
3602     {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3603      10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3604      10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3605      10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3606      10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3607      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3608      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3609      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3610      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3611      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3612      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3613      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3614      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3615      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3616      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3617      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3618      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3619      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3620      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3621      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3622      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3623      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3624      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3625      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3626      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3627      10688, 10688, 10688, 10688, 10688, 10688, 10688},
3628     {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3629      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3630      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3631      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3632      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3633      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3634      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3635      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3636      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3637      10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3638      10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3639      10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3640      10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3641      11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3642      11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3643      11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3644      11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3645      11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3646      11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3647      11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3648      11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3649      11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3650      11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3651      11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3652      11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3653      11824, 11824, 11824, 11824, 11824, 11824, 11824},
3654     {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3655      11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3656      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3657      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3658      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3659      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3660      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3661      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3662      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3663      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3664      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3665      11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3666      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3667      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3668      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3669      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3670      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3671      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3672      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3673      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3674      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3675      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3676      11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3677      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3678      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3679      11880, 11880, 11880, 11880, 11880, 11880, 11880},
3680     {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3681      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3682      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3683      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3684      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3685      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3686      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3687      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3688      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3689      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3690      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3691      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3692      11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3693      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3694      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3695      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3696      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3697      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3698      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3699      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3700      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3701      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3702      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3703      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3704      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3705      11888, 11888, 11888, 11888, 11888, 11888, 11888},
3706     {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3707      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3708      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3709      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3710      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3711      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3712      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3713      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3714      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3715      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3716      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3717      11888, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3718      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3719      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3720      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3721      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3722      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3723      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3724      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3725      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3726      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3727      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3728      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3729      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3730      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3731      11892, 11892, 11892, 11892, 11892, 11892, 11892},
3732     {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3733      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3734      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3735      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3736      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3737      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3738      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3739      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3740      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3741      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3742      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3743      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3744      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3745      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3746      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3747      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3748      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3749      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3750      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3751      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3752      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3753      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3754      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3755      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3756      11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3757      11900, 11900, 11900, 11900, 11900, 11900, 11901},
3758     {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3759      11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3760      11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3761      12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3762      12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3763      12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3764      12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3765      12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3766      12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3767      12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3768      12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3769      12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3770      12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3771      12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3772      12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3773      12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3774      12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3775      12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3776      12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3777      12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3778      12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3779      12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3780      12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3781      12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3782      12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3783      12756, 12756, 12756, 12756, 12756, 12756, 12757},
3784     {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3785      12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3786      12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3787      12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3788      12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3789      12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3790      12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3791      12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3792      12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3793      12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3794      12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3795      12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3796      12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3797      12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3798      12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3799      12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3800      13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3801      13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3802      13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3803      13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3804      13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3805      13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3806      13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3807      13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3808      13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3809      13248, 13256, 13256, 13256, 13256, 13265, 13272},
3810     {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3811      13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3812      13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3813      13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3814      13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3815      13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3816      13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3817      13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3818      13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3819      13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3820      13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3821      13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3822      13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3823      13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3824      13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3825      13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3826      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3827      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3828      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3829      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3830      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3831      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3832      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3833      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3834      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3835      13704, 13704, 13704, 13704, 13704, 13704, 13705},
3836     {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3837      13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3838      13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3839      14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3840      14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3841      14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3842      14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3843      14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3844      14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3845      14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3846      14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3847      14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3848      14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3849      14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3850      15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3851      15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3852      15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3853      15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3854      15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3855      15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3856      15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3857      15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3858      15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3859      15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3860      15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3861      15589, 15593, 15597, 15601, 15605, 15609, 15617},
3862     {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3863      15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3864      15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3865      16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3866      16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3867      16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3868      16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3869      16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3870      16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3871      17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3872      17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3873      17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3874      17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3875      17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3876      17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3877      17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3878      17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3879      17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3880      17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3881      18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3882      18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3883      18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3884      18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3885      18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3886      18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3887      18617, 18629, 18641, 18653, 18665, 18677, 18688},
3888     {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3889      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3890      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3891      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3892      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3893      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3894      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3895      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3896      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3897      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3898      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3899      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3900      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3901      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3902      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3903      18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3904      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3905      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3906      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3907      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3908      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3909      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3910      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3911      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3912      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3913      18696, 18696, 18696, 18696, 18696, 18696, 18696},
3914     {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3915      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3916      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3917      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3918      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3919      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3920      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3921      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3922      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3923      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3924      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3925      18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3926      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3927      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3928      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3929      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3930      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3931      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3932      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3933      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3934      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3935      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3936      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3937      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3938      18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3939      18720, 18720, 18720, 18720, 18720, 18720, 18720},
3940     {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3941      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3942      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3943      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3944      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3945      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3946      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3947      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3948      18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3949      18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3950      18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3951      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3952      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3953      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3954      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3955      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3956      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3957      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3958      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3959      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3960      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3961      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3962      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3963      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3964      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3965      18740, 18740, 18740, 18740, 18740, 18740, 18740},
3966     {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3967      18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3968      18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3969      18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3970      18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3971      18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3972      18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3973      19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3974      19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3975      19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3976      19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3977      19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
3978      19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
3979      19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
3980      19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
3981      19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
3982      19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
3983      19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
3984      19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
3985      19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
3986      19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
3987      19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
3988      19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
3989      19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
3990      19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
3991      19740, 19744, 19748, 19752, 19756, 19760, 19764},
3992     {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
3993      19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
3994      19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
3995      19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
3996      19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
3997      19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
3998      19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
3999      19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4000      20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4001      20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4002      20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4003      20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4004      20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4005      20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4006      20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4007      20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4008      20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4009      20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4010      20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4011      20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4012      20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4013      20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4014      20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4015      20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4016      20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4017      20580, 20580, 20580, 20580, 20580, 20580, 20581},
4018     {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4019      20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4020      20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4021      20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4022      20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4023      20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4024      20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4025      20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4026      21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4027      21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4028      21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4029      21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4030      21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4031      21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4032      21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4033      21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4034      21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4035      21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4036      21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4037      21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4038      21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4039      21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4040      21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4041      21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4042      21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4043      21709, 21721, 21733, 21737, 21741, 21745, 21749},
4044     {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4045      21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4046      21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4047      22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4048      22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4049      22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4050      22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4051      22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4052      22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4053      22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4054      22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4055      22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4056      22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4057      22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4058      22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4059      23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4060      23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4061      23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4062      23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4063      23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4064      23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4065      23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4066      23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4067      23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4068      23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4069      23857, 23865, 23873, 23881, 23889, 23897, 23905},
4070     {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4071      23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4072      24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4073      24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4074      24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4075      24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4076      24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4077      24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4078      24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4079      24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4080      24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4081      24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4082      24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4083      25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4084      25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4085      25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4086      25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4087      25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4088      25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4089      25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4090      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4091      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4092      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4093      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4094      25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4095      25965, 26037, 26069, 26084, 26084, 26084, 26084},
4096     {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4097      26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4098      26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4099      26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4100      26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4101      26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4102      26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4103      26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4104      26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4105      26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4106      26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4107      26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4108      26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4109      26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4110      26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4111      26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4112      26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4113      26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4114      26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4115      26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4116      26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4117      26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4118      26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4119      26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4120      26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4121      27065, 27077, 27085, 27092, 27092, 27092, 27092},
4122     {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4123      27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4124      27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4125      27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4126      27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4127      27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4128      27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4129      27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4130      27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4131      27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4132      27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4133      27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4134      27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4135      27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4136      27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4137      27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4138      27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4139      27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4140      27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4141      27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4142      27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4143      27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4144      27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4145      27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4146      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4147      27996, 27996, 27996, 27996, 27996, 27996, 27996},
4148     {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4149      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4150      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4151      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4152      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4153      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4154      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4155      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4156      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4157      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4158      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4159      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4160      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4161      28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4162      28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4163      28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4164      28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4165      28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4166      28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4167      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4168      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4169      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4170      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4171      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4172      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4173      28220, 28220, 28220, 28220, 28220, 28220, 28220},
4174     {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4175      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4176      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4177      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4178      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4179      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4180      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4181      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4182      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4183      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4184      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4185      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4186      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4187      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4188      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4189      28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4190      28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4191      28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4192      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4193      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4194      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4195      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4196      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4197      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4198      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4199      28244, 28244, 28244, 28244, 28244, 28244, 28244},
4200     {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4201      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4202      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4203      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4204      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4205      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4206      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4207      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4208      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4209      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4210      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4211      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4212      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4213      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4214      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4215      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4216      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4217      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4218      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4219      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4220      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4221      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4222      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4223      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4224      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4225      28260, 28260, 28260, 28260, 28260, 28260, 28260},
4226     {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4227      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4228      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4229      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4230      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4231      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4232      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4233      28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4234      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4235      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4236      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4237      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4238      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4239      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4240      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4241      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4242      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4243      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4244      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4245      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4246      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4247      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4248      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4249      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4250      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4251      28276, 28276, 28276, 28276, 28276, 28276, 28276},
4252     {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4253      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4254      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4255      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4256      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4257      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4258      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4259      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4260      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4261      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4262      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4263      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4264      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4265      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4266      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4267      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4268      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4269      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4270      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4271      28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4272      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4273      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4274      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4275      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4276      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4277      28300, 28300, 28300, 28300, 28300, 28300, 28300},
4278     {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4279      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4280      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4281      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4282      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4283      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4284      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4285      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4286      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4287      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4288      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4289      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4290      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4291      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4292      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4293      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4294      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4295      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4296      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4297      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4298      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4299      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4300      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4301      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4302      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4303      28316, 28316, 28316, 28316, 28316, 28316, 28316},
4304     {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4305      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4306      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4307      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4308      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4309      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4310      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4311      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4312      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4313      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4314      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4315      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4316      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4317      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4318      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4319      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4320      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4321      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4322      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4323      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4324      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4325      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4326      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4327      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4328      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4329      28324, 28324, 28324, 28324, 28324, 28324, 28324},
4330     {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4331      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4332      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4333      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4334      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4335      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4336      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4337      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4338      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4339      28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4340      28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4341      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4342      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4343      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4344      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4345      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4346      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4347      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4348      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4349      28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4350      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4351      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4352      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4353      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4354      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4355      28464, 28464, 28464, 28464, 28464, 28464, 28464},
4356     {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4357      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4358      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4359      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4360      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4361      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4362      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4363      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4364      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4365      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4366      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4367      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4368      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4369      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4370      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4371      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4372      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4373      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4374      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4375      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4376      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4377      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4378      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4379      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4380      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4381      28464, 28464, 28464, 28464, 28464, 28464, 28465},
4382     {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4383      28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4384      28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4385      28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4386      28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4387      28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4388      28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4389      28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4390      28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4391      28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4392      28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4393      28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4394      28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4395      28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4396      29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4397      29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4398      29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4399      29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4400      29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4401      29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4402      29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4403      29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4404      29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4405      29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4406      29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4407      29417, 29421, 29425, 29429, 29433, 29437, 29441},
4408     {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4409      29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4410      29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4411      29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4412      29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4413      29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4414      29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4415      29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4416      29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4417      29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4418      29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4419      29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4420      29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4421      29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4422      29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4423      29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4424      30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4425      30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4426      30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4427      30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4428      30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4429      30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4430      30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4431      30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4432      30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4433      30393, 30397, 30401, 30405, 30409, 30413, 30417},
4434     {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4435      30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4436      30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4437      30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4438      30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4439      30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4440      30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4441      30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4442      30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4443      30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4444      30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4445      30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4446      30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4447      30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4448      30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4449      31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4450      31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4451      31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4452      31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4453      31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4454      31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4455      31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4456      31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4457      31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4458      31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4459      31409, 31413, 31417, 31421, 31425, 31429, 31433},
4460     {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4461      31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4462      31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4463      31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4464      31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4465      31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4466      31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4467      31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4468      31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4469      31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4470      31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4471      31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4472      31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4473      31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4474      31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4475      32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4476      32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4477      32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4478      32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4479      32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4480      32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4481      32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4482      32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4483      32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4484      32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4485      32425, 32429, 32433, 32437, 32441, 32445, 32448},
4486     {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4487      32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4488      32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4489      32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4490      32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4491      32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4492      32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4493      32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4494      32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4495      32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4496      32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4497      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4498      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4499      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4500      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4501      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4502      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4503      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4504      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4505      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4506      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4507      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4508      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4509      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4510      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4511      32696, 32696, 32696, 32696, 32696, 32696, 32696},
4512     {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4513      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4514      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4515      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4516      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4517      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4518      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4519      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4520      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4521      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4522      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4523      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4524      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4525      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4526      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4527      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4528      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4529      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4530      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4531      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4532      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4533      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4534      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4535      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4536      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4537      32696, 32696, 32696, 32696, 32696, 32696, 32697},
4538     {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4539      32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4540      32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4541      32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4542      32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4543      32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4544      32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4545      32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4546      32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4547      32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4548      32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4549      32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4550      33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4551      33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4552      33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4553      33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4554      33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4555      33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4556      33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4557      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4558      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4559      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4560      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4561      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4562      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4563      33260, 33260, 33260, 33260, 33260, 33260, 33260},
4564     {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4565      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4566      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4567      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4568      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4569      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4570      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4571      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4572      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4573      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4574      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4575      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4576      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4577      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4578      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4579      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4580      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4581      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4582      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4583      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4584      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4585      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4586      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4587      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4588      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4589      33260, 33260, 33260, 33260, 33260, 33260, 33261},
4590     {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4591      33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4592      33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4593      33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4594      33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4595      33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4596      33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4597      33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4598      33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4599      33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4600      33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4601      33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4602      33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4603      33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4604      33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4605      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4606      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4607      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4608      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4609      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4610      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4611      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4612      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4613      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4614      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4615      33884, 33884, 33884, 33884, 33884, 33884, 33885},
4616     {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4617      33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4618      33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4619      33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4620      34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4621      34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4622      34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4623      34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4624      34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4625      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4626      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4627      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4628      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4629      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4630      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4631      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4632      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4633      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4634      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4635      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4636      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4637      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4638      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4639      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4640      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4641      34200, 34200, 34200, 34200, 34200, 34200, 34200},
4642     {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4643      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4644      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4645      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4646      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4647      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4648      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4649      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4650      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4651      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4652      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4653      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4654      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4655      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4656      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4657      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4658      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4659      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4660      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4661      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4663      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4664      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4665      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4666      34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4667      34240, 34240, 34240, 34240, 34240, 34240, 34240},
4668     {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4669      34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4670      34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4671      34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4672      34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4673      34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4674      34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4675      34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4676      34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4677      34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4678      34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4679      34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4680      34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4681      34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4682      34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4683      34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4684      34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4685      34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4686      34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4687      35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4688      35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4689      35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4690      35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4691      35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4692      35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4693      35240, 35244, 35248, 35252, 35256, 35260, 35264},
4694     {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4695      35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4696      35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4697      35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4698      35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4699      35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4700      35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4701      35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4702      35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4703      35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4704      35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4705      35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4706      35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4707      35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4708      35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4709      35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4710      35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4711      35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4712      35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4713      36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4714      36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4715      36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4716      36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4717      36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4718      36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4719      36264, 36268, 36272, 36276, 36280, 36284, 36288},
4720     {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4721      36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4722      36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4723      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4724      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4725      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4726      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4727      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4728      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4729      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4730      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4731      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4732      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4733      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4734      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4735      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4736      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4737      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4738      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4739      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4740      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4741      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4742      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4743      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4744      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4745      36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4746 const char32_t decomposition_data[9102] = {
4747     0,      32,     32,     776,    97,     32,     772,    50,     51,
4748     32,     769,    956,    32,     807,    49,     111,    49,     8260,
4749     52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4750     65,     769,    65,     770,    65,     771,    65,     776,    65,
4751     778,    67,     807,    69,     768,    69,     769,    69,     770,
4752     69,     776,    73,     768,    73,     769,    73,     770,    73,
4753     776,    78,     771,    79,     768,    79,     769,    79,     770,
4754     79,     771,    79,     776,    85,     768,    85,     769,    85,
4755     770,    85,     776,    89,     769,    97,     768,    97,     769,
4756     97,     770,    97,     771,    97,     776,    97,     778,    99,
4757     807,    101,    768,    101,    769,    101,    770,    101,    776,
4758     105,    768,    105,    769,    105,    770,    105,    776,    110,
4759     771,    111,    768,    111,    769,    111,    770,    111,    771,
4760     111,    776,    117,    768,    117,    769,    117,    770,    117,
4761     776,    121,    769,    121,    776,    65,     772,    97,     772,
4762     65,     774,    97,     774,    65,     808,    97,     808,    67,
4763     769,    99,     769,    67,     770,    99,     770,    67,     775,
4764     99,     775,    67,     780,    99,     780,    68,     780,    100,
4765     780,    69,     772,    101,    772,    69,     774,    101,    774,
4766     69,     775,    101,    775,    69,     808,    101,    808,    69,
4767     780,    101,    780,    71,     770,    103,    770,    71,     774,
4768     103,    774,    71,     775,    103,    775,    71,     807,    103,
4769     807,    72,     770,    104,    770,    73,     771,    105,    771,
4770     73,     772,    105,    772,    73,     774,    105,    774,    73,
4771     808,    105,    808,    73,     775,    73,     74,     105,    106,
4772     74,     770,    106,    770,    75,     807,    107,    807,    76,
4773     769,    108,    769,    76,     807,    108,    807,    76,     780,
4774     108,    780,    76,     183,    108,    183,    78,     769,    110,
4775     769,    78,     807,    110,    807,    78,     780,    110,    780,
4776     700,    110,    79,     772,    111,    772,    79,     774,    111,
4777     774,    79,     779,    111,    779,    82,     769,    114,    769,
4778     82,     807,    114,    807,    82,     780,    114,    780,    83,
4779     769,    115,    769,    83,     770,    115,    770,    83,     807,
4780     115,    807,    83,     780,    115,    780,    84,     807,    116,
4781     807,    84,     780,    116,    780,    85,     771,    117,    771,
4782     85,     772,    117,    772,    85,     774,    117,    774,    85,
4783     778,    117,    778,    85,     779,    117,    779,    85,     808,
4784     117,    808,    87,     770,    119,    770,    89,     770,    121,
4785     770,    89,     776,    90,     769,    122,    769,    90,     775,
4786     122,    775,    90,     780,    122,    780,    115,    79,     795,
4787     111,    795,    85,     795,    117,    795,    68,     90,     780,
4788     68,     122,    780,    100,    122,    780,    76,     74,     76,
4789     106,    108,    106,    78,     74,     78,     106,    110,    106,
4790     65,     780,    97,     780,    73,     780,    105,    780,    79,
4791     780,    111,    780,    85,     780,    117,    780,    85,     776,
4792     772,    117,    776,    772,    85,     776,    769,    117,    776,
4793     769,    85,     776,    780,    117,    776,    780,    85,     776,
4794     768,    117,    776,    768,    65,     776,    772,    97,     776,
4795     772,    65,     775,    772,    97,     775,    772,    198,    772,
4796     230,    772,    71,     780,    103,    780,    75,     780,    107,
4797     780,    79,     808,    111,    808,    79,     808,    772,    111,
4798     808,    772,    439,    780,    658,    780,    106,    780,    68,
4799     90,     68,     122,    100,    122,    71,     769,    103,    769,
4800     78,     768,    110,    768,    65,     778,    769,    97,     778,
4801     769,    198,    769,    230,    769,    216,    769,    248,    769,
4802     65,     783,    97,     783,    65,     785,    97,     785,    69,
4803     783,    101,    783,    69,     785,    101,    785,    73,     783,
4804     105,    783,    73,     785,    105,    785,    79,     783,    111,
4805     783,    79,     785,    111,    785,    82,     783,    114,    783,
4806     82,     785,    114,    785,    85,     783,    117,    783,    85,
4807     785,    117,    785,    83,     806,    115,    806,    84,     806,
4808     116,    806,    72,     780,    104,    780,    65,     775,    97,
4809     775,    69,     807,    101,    807,    79,     776,    772,    111,
4810     776,    772,    79,     771,    772,    111,    771,    772,    79,
4811     775,    111,    775,    79,     775,    772,    111,    775,    772,
4812     89,     772,    121,    772,    104,    614,    106,    114,    633,
4813     635,    641,    119,    121,    32,     774,    32,     775,    32,
4814     778,    32,     808,    32,     771,    32,     779,    611,    108,
4815     115,    120,    661,    768,    769,    787,    776,    769,    697,
4816     32,     837,    59,     32,     769,    168,    769,    913,    769,
4817     183,    917,    769,    919,    769,    921,    769,    927,    769,
4818     933,    769,    937,    769,    953,    776,    769,    921,    776,
4819     933,    776,    945,    769,    949,    769,    951,    769,    953,
4820     769,    965,    776,    769,    953,    776,    965,    776,    959,
4821     769,    965,    769,    969,    769,    946,    952,    933,    978,
4822     769,    978,    776,    966,    960,    954,    961,    962,    920,
4823     949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4824     776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4825     1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4826     776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4827     1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4828     774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4829     1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4830     776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4831     1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4832     776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4833     1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4834     776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4835     1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4836     1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4837     1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4838     2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4839     2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4840     2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4841     2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4842     2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4843     2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4844     3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4845     3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4846     3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4847     3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4848     3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4849     4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4850     3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4851     4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4852     3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4853     4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4854     6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4855     6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4856     198,    66,     68,     69,     398,    71,     72,     73,     74,
4857     75,     76,     77,     78,     79,     546,    80,     82,     84,
4858     85,     87,     97,     592,    593,    7426,   98,     100,    101,
4859     601,    603,    604,    103,    107,    109,    331,    111,    596,
4860     7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4861     946,    947,    948,    966,    967,    105,    114,    117,    118,
4862     946,    947,    961,    966,    967,    1085,   594,    99,     597,
4863     240,    604,    102,    607,    609,    613,    616,    617,    618,
4864     7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4865     628,    629,    632,    642,    643,    427,    649,    650,    7452,
4866     651,    652,    122,    656,    657,    658,    952,    65,     805,
4867     97,     805,    66,     775,    98,     775,    66,     803,    98,
4868     803,    66,     817,    98,     817,    67,     807,    769,    99,
4869     807,    769,    68,     775,    100,    775,    68,     803,    100,
4870     803,    68,     817,    100,    817,    68,     807,    100,    807,
4871     68,     813,    100,    813,    69,     772,    768,    101,    772,
4872     768,    69,     772,    769,    101,    772,    769,    69,     813,
4873     101,    813,    69,     816,    101,    816,    69,     807,    774,
4874     101,    807,    774,    70,     775,    102,    775,    71,     772,
4875     103,    772,    72,     775,    104,    775,    72,     803,    104,
4876     803,    72,     776,    104,    776,    72,     807,    104,    807,
4877     72,     814,    104,    814,    73,     816,    105,    816,    73,
4878     776,    769,    105,    776,    769,    75,     769,    107,    769,
4879     75,     803,    107,    803,    75,     817,    107,    817,    76,
4880     803,    108,    803,    76,     803,    772,    108,    803,    772,
4881     76,     817,    108,    817,    76,     813,    108,    813,    77,
4882     769,    109,    769,    77,     775,    109,    775,    77,     803,
4883     109,    803,    78,     775,    110,    775,    78,     803,    110,
4884     803,    78,     817,    110,    817,    78,     813,    110,    813,
4885     79,     771,    769,    111,    771,    769,    79,     771,    776,
4886     111,    771,    776,    79,     772,    768,    111,    772,    768,
4887     79,     772,    769,    111,    772,    769,    80,     769,    112,
4888     769,    80,     775,    112,    775,    82,     775,    114,    775,
4889     82,     803,    114,    803,    82,     803,    772,    114,    803,
4890     772,    82,     817,    114,    817,    83,     775,    115,    775,
4891     83,     803,    115,    803,    83,     769,    775,    115,    769,
4892     775,    83,     780,    775,    115,    780,    775,    83,     803,
4893     775,    115,    803,    775,    84,     775,    116,    775,    84,
4894     803,    116,    803,    84,     817,    116,    817,    84,     813,
4895     116,    813,    85,     804,    117,    804,    85,     816,    117,
4896     816,    85,     813,    117,    813,    85,     771,    769,    117,
4897     771,    769,    85,     772,    776,    117,    772,    776,    86,
4898     771,    118,    771,    86,     803,    118,    803,    87,     768,
4899     119,    768,    87,     769,    119,    769,    87,     776,    119,
4900     776,    87,     775,    119,    775,    87,     803,    119,    803,
4901     88,     775,    120,    775,    88,     776,    120,    776,    89,
4902     775,    121,    775,    90,     770,    122,    770,    90,     803,
4903     122,    803,    90,     817,    122,    817,    104,    817,    116,
4904     776,    119,    778,    121,    778,    97,     702,    383,    775,
4905     65,     803,    97,     803,    65,     777,    97,     777,    65,
4906     770,    769,    97,     770,    769,    65,     770,    768,    97,
4907     770,    768,    65,     770,    777,    97,     770,    777,    65,
4908     770,    771,    97,     770,    771,    65,     803,    770,    97,
4909     803,    770,    65,     774,    769,    97,     774,    769,    65,
4910     774,    768,    97,     774,    768,    65,     774,    777,    97,
4911     774,    777,    65,     774,    771,    97,     774,    771,    65,
4912     803,    774,    97,     803,    774,    69,     803,    101,    803,
4913     69,     777,    101,    777,    69,     771,    101,    771,    69,
4914     770,    769,    101,    770,    769,    69,     770,    768,    101,
4915     770,    768,    69,     770,    777,    101,    770,    777,    69,
4916     770,    771,    101,    770,    771,    69,     803,    770,    101,
4917     803,    770,    73,     777,    105,    777,    73,     803,    105,
4918     803,    79,     803,    111,    803,    79,     777,    111,    777,
4919     79,     770,    769,    111,    770,    769,    79,     770,    768,
4920     111,    770,    768,    79,     770,    777,    111,    770,    777,
4921     79,     770,    771,    111,    770,    771,    79,     803,    770,
4922     111,    803,    770,    79,     795,    769,    111,    795,    769,
4923     79,     795,    768,    111,    795,    768,    79,     795,    777,
4924     111,    795,    777,    79,     795,    771,    111,    795,    771,
4925     79,     795,    803,    111,    795,    803,    85,     803,    117,
4926     803,    85,     777,    117,    777,    85,     795,    769,    117,
4927     795,    769,    85,     795,    768,    117,    795,    768,    85,
4928     795,    777,    117,    795,    777,    85,     795,    771,    117,
4929     795,    771,    85,     795,    803,    117,    795,    803,    89,
4930     768,    121,    768,    89,     803,    121,    803,    89,     777,
4931     121,    777,    89,     771,    121,    771,    945,    787,    945,
4932     788,    945,    787,    768,    945,    788,    768,    945,    787,
4933     769,    945,    788,    769,    945,    787,    834,    945,    788,
4934     834,    913,    787,    913,    788,    913,    787,    768,    913,
4935     788,    768,    913,    787,    769,    913,    788,    769,    913,
4936     787,    834,    913,    788,    834,    949,    787,    949,    788,
4937     949,    787,    768,    949,    788,    768,    949,    787,    769,
4938     949,    788,    769,    917,    787,    917,    788,    917,    787,
4939     768,    917,    788,    768,    917,    787,    769,    917,    788,
4940     769,    951,    787,    951,    788,    951,    787,    768,    951,
4941     788,    768,    951,    787,    769,    951,    788,    769,    951,
4942     787,    834,    951,    788,    834,    919,    787,    919,    788,
4943     919,    787,    768,    919,    788,    768,    919,    787,    769,
4944     919,    788,    769,    919,    787,    834,    919,    788,    834,
4945     953,    787,    953,    788,    953,    787,    768,    953,    788,
4946     768,    953,    787,    769,    953,    788,    769,    953,    787,
4947     834,    953,    788,    834,    921,    787,    921,    788,    921,
4948     787,    768,    921,    788,    768,    921,    787,    769,    921,
4949     788,    769,    921,    787,    834,    921,    788,    834,    959,
4950     787,    959,    788,    959,    787,    768,    959,    788,    768,
4951     959,    787,    769,    959,    788,    769,    927,    787,    927,
4952     788,    927,    787,    768,    927,    788,    768,    927,    787,
4953     769,    927,    788,    769,    965,    787,    965,    788,    965,
4954     787,    768,    965,    788,    768,    965,    787,    769,    965,
4955     788,    769,    965,    787,    834,    965,    788,    834,    933,
4956     788,    933,    788,    768,    933,    788,    769,    933,    788,
4957     834,    969,    787,    969,    788,    969,    787,    768,    969,
4958     788,    768,    969,    787,    769,    969,    788,    769,    969,
4959     787,    834,    969,    788,    834,    937,    787,    937,    788,
4960     937,    787,    768,    937,    788,    768,    937,    787,    769,
4961     937,    788,    769,    937,    787,    834,    937,    788,    834,
4962     945,    768,    945,    769,    949,    768,    949,    769,    951,
4963     768,    951,    769,    953,    768,    953,    769,    959,    768,
4964     959,    769,    965,    768,    965,    769,    969,    768,    969,
4965     769,    945,    787,    837,    945,    788,    837,    945,    787,
4966     768,    837,    945,    788,    768,    837,    945,    787,    769,
4967     837,    945,    788,    769,    837,    945,    787,    834,    837,
4968     945,    788,    834,    837,    913,    787,    837,    913,    788,
4969     837,    913,    787,    768,    837,    913,    788,    768,    837,
4970     913,    787,    769,    837,    913,    788,    769,    837,    913,
4971     787,    834,    837,    913,    788,    834,    837,    951,    787,
4972     837,    951,    788,    837,    951,    787,    768,    837,    951,
4973     788,    768,    837,    951,    787,    769,    837,    951,    788,
4974     769,    837,    951,    787,    834,    837,    951,    788,    834,
4975     837,    919,    787,    837,    919,    788,    837,    919,    787,
4976     768,    837,    919,    788,    768,    837,    919,    787,    769,
4977     837,    919,    788,    769,    837,    919,    787,    834,    837,
4978     919,    788,    834,    837,    969,    787,    837,    969,    788,
4979     837,    969,    787,    768,    837,    969,    788,    768,    837,
4980     969,    787,    769,    837,    969,    788,    769,    837,    969,
4981     787,    834,    837,    969,    788,    834,    837,    937,    787,
4982     837,    937,    788,    837,    937,    787,    768,    837,    937,
4983     788,    768,    837,    937,    787,    769,    837,    937,    788,
4984     769,    837,    937,    787,    834,    837,    937,    788,    834,
4985     837,    945,    774,    945,    772,    945,    768,    837,    945,
4986     837,    945,    769,    837,    945,    834,    945,    834,    837,
4987     913,    774,    913,    772,    913,    768,    913,    769,    913,
4988     837,    32,     787,    953,    32,     787,    32,     834,    168,
4989     834,    951,    768,    837,    951,    837,    951,    769,    837,
4990     951,    834,    951,    834,    837,    917,    768,    917,    769,
4991     919,    768,    919,    769,    919,    837,    8127,   768,    8127,
4992     769,    8127,   834,    953,    774,    953,    772,    953,    776,
4993     768,    953,    776,    769,    953,    834,    953,    776,    834,
4994     921,    774,    921,    772,    921,    768,    921,    769,    8190,
4995     768,    8190,   769,    8190,   834,    965,    774,    965,    772,
4996     965,    776,    768,    965,    776,    769,    961,    787,    961,
4997     788,    965,    834,    965,    776,    834,    933,    774,    933,
4998     772,    933,    768,    933,    769,    929,    788,    168,    768,
4999     168,    769,    96,     969,    768,    837,    969,    837,    969,
5000     769,    837,    969,    834,    969,    834,    837,    927,    768,
5001     927,    769,    937,    768,    937,    769,    937,    837,    180,
5002     32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5003     32,     32,     32,     32,     8208,   32,     819,    46,     46,
5004     46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5005     8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5006     773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5007     8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5008     56,     57,     43,     8722,   61,     40,     41,     110,    48,
5009     49,     50,     51,     52,     53,     54,     55,     56,     57,
5010     43,     8722,   61,     40,     41,     97,     101,    111,    120,
5011     601,    104,    107,    108,    109,    110,    112,    115,    116,
5012     82,     115,    97,     47,     99,     97,     47,     115,    67,
5013     176,    67,     99,     47,     111,    99,     47,     117,    400,
5014     176,    70,     103,    72,     72,     72,     104,    295,    73,
5015     73,     76,     108,    78,     78,     111,    80,     81,     82,
5016     82,     82,     83,     77,     84,     69,     76,     84,     77,
5017     90,     937,    90,     75,     65,     778,    66,     67,     101,
5018     69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5019     70,     65,     88,     960,    947,    915,    928,    8721,   68,
5020     100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5021     57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5022     8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5023     8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5024     8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5025     8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5026     73,     73,     73,     73,     73,     86,     86,     86,     73,
5027     86,     73,     73,     86,     73,     73,     73,     73,     88,
5028     88,     88,     73,     88,     73,     73,     76,     67,     68,
5029     77,     105,    105,    105,    105,    105,    105,    105,    118,
5030     118,    118,    105,    118,    105,    105,    118,    105,    105,
5031     105,    105,    120,    120,    120,    105,    120,    105,    105,
5032     108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5033     8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5034     824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5035     8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5036     8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5037     8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5038     824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5039     8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5040     824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5041     8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5042     824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5043     8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5044     50,     51,     52,     53,     54,     55,     56,     57,     49,
5045     48,     49,     49,     49,     50,     49,     51,     49,     52,
5046     49,     53,     49,     54,     49,     55,     49,     56,     49,
5047     57,     50,     48,     40,     49,     41,     40,     50,     41,
5048     40,     51,     41,     40,     52,     41,     40,     53,     41,
5049     40,     54,     41,     40,     55,     41,     40,     56,     41,
5050     40,     57,     41,     40,     49,     48,     41,     40,     49,
5051     49,     41,     40,     49,     50,     41,     40,     49,     51,
5052     41,     40,     49,     52,     41,     40,     49,     53,     41,
5053     40,     49,     54,     41,     40,     49,     55,     41,     40,
5054     49,     56,     41,     40,     49,     57,     41,     40,     50,
5055     48,     41,     49,     46,     50,     46,     51,     46,     52,
5056     46,     53,     46,     54,     46,     55,     46,     56,     46,
5057     57,     46,     49,     48,     46,     49,     49,     46,     49,
5058     50,     46,     49,     51,     46,     49,     52,     46,     49,
5059     53,     46,     49,     54,     46,     49,     55,     46,     49,
5060     56,     46,     49,     57,     46,     50,     48,     46,     40,
5061     97,     41,     40,     98,     41,     40,     99,     41,     40,
5062     100,    41,     40,     101,    41,     40,     102,    41,     40,
5063     103,    41,     40,     104,    41,     40,     105,    41,     40,
5064     106,    41,     40,     107,    41,     40,     108,    41,     40,
5065     109,    41,     40,     110,    41,     40,     111,    41,     40,
5066     112,    41,     40,     113,    41,     40,     114,    41,     40,
5067     115,    41,     40,     116,    41,     40,     117,    41,     40,
5068     118,    41,     40,     119,    41,     40,     120,    41,     40,
5069     121,    41,     40,     122,    41,     65,     66,     67,     68,
5070     69,     70,     71,     72,     73,     74,     75,     76,     77,
5071     78,     79,     80,     81,     82,     83,     84,     85,     86,
5072     87,     88,     89,     90,     97,     98,     99,     100,    101,
5073     102,    103,    104,    105,    106,    107,    108,    109,    110,
5074     111,    112,    113,    114,    115,    116,    117,    118,    119,
5075     120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5076     58,     61,     61,     61,     61,     61,     61,     10973,  824,
5077     106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5078     20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5079     20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5080     21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5081     22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5082     23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5083     24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5084     24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5085     26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5086     27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5087     28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5088     29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5089     30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5090     31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5091     32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5092     33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5093     33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5094     35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5095     36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5096     37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5097     38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5098     39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5099     39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5100     40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5101     40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5102     12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5103     12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5104     12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5105     12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5106     12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5107     12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5108     12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5109     12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5110     12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5111     12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5112     12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5113     12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5114     12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5115     12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5116     4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5117     4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5118     4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5119     4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5120     4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5121     4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5122     4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5123     4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5124     4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5125     4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5126     4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5127     20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5128     40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5129     40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5130     40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5131     40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5132     40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5133     4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5134     41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5135     40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5136     4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5137     4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5138     41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5139     40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5140     4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5141     41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5142     41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5143     41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5144     41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5145     41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5146     41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5147     41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5148     41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5149     41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5150     41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5151     41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5152     41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5153     84,     69,     50,     49,     50,     50,     50,     51,     50,
5154     52,     50,     53,     50,     54,     50,     55,     50,     56,
5155     50,     57,     51,     48,     51,     49,     51,     50,     51,
5156     51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5157     4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5158     4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5159     4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5160     4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5161     4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5162     4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5163     20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5164     37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5165     31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5166     38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5167     21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5168     54,     51,     55,     51,     56,     51,     57,     52,     48,
5169     52,     49,     52,     50,     52,     51,     52,     52,     52,
5170     53,     52,     54,     52,     55,     52,     56,     52,     57,
5171     53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5172     26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5173     57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5174     50,     26376,  72,     103,    101,    114,    103,    101,    86,
5175     76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5176     12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5177     12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5178     12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5179     12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5180     12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5181     12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5182     12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5183     12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5184     12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5185     12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5186     12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5187     12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5188     12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5189     12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5190     12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5191     12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5192     12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5193     12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5194     12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5195     12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5196     12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5197     12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5198     12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5199     12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5200     12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5201     12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5202     12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5203     12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5204     12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5205     12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5206     12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5207     12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5208     12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5209     12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5210     12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5211     12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5212     12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5213     12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5214     12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5215     12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5216     12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5217     12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5218     12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5219     12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5220     28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5221     55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5222     49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5223     49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5224     49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5225     50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5226     50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5227     100,    97,     65,     85,     98,     97,     114,    111,    86,
5228     112,    99,     100,    109,    100,    109,    50,     100,    109,
5229     51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5230     26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5231     65,     956,    65,     109,    65,     107,    65,     75,     66,
5232     77,     66,     71,     66,     99,     97,     108,    107,    99,
5233     97,     108,    112,    70,     110,    70,     956,    70,     956,
5234     103,    109,    103,    107,    103,    72,     122,    107,    72,
5235     122,    77,     72,     122,    71,     72,     122,    84,     72,
5236     122,    956,    108,    109,    108,    100,    108,    107,    108,
5237     102,    109,    110,    109,    956,    109,    109,    109,    99,
5238     109,    107,    109,    109,    109,    50,     99,     109,    50,
5239     109,    50,     107,    109,    50,     109,    109,    51,     99,
5240     109,    51,     109,    51,     107,    109,    51,     109,    8725,
5241     115,    109,    8725,   115,    50,     80,     97,     107,    80,
5242     97,     77,     80,     97,     71,     80,     97,     114,    97,
5243     100,    114,    97,     100,    8725,   115,    114,    97,     100,
5244     8725,   115,    50,     112,    115,    110,    115,    956,    115,
5245     109,    115,    112,    86,     110,    86,     956,    86,     109,
5246     86,     107,    86,     77,     86,     112,    87,     110,    87,
5247     956,    87,     109,    87,     107,    87,     77,     87,     107,
5248     937,    77,     937,    97,     46,     109,    46,     66,     113,
5249     99,     99,     99,     100,    67,     8725,   107,    103,    67,
5250     111,    46,     100,    66,     71,     121,    104,    97,     72,
5251     80,     105,    110,    75,     75,     75,     77,     107,    116,
5252     108,    109,    108,    110,    108,    111,    103,    108,    120,
5253     109,    98,     109,    105,    108,    109,    111,    108,    80,
5254     72,     112,    46,     109,    46,     80,     80,     77,     80,
5255     82,     115,    114,    83,     118,    87,     98,     86,     8725,
5256     109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5257     26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5258     56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5259     26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5260     26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5261     26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5262     26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5263     26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5264     26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5265     26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5266     108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5267     42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5268     28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5269     25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5270     28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5271     34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5272     24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5273     27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5274     40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5275     24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5276     27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5277     20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5278     20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5279     19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5280     27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5281     20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5282     24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5283     26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5284     29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5285     21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5286     31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5287     32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5288     38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5289     30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5290     27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5291     38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5292     38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5293     30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5294     29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5295     31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5296     20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5297     38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5298     30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5299     35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5300     20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5301     22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5302     26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5303     30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5304     31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5305     33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5306     36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5307     20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5308     21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5309     24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5310     25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5311     27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5312     29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5313     30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5314     32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5315     35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5316     36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5317     38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5318     16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5319     105,    102,    108,    102,    102,    105,    102,    102,    108,
5320     115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5321     1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5322     1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5323     43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5324     1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5325     1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5326     1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5327     1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5328     1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5329     1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5330     1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5331     1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5332     1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5333     1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5334     1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5335     1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5336     1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5337     1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5338     1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5339     1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5340     1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5341     1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5342     1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5343     1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5344     1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5345     1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5346     1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5347     1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5348     1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5349     1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5350     1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5351     1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5352     1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5353     1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5354     1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5355     1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5356     1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5357     1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5358     1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5359     1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5360     1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5361     1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5362     1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5363     1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5364     1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5365     1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5366     1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5367     1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5368     1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5369     1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5370     1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5371     1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5372     1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5373     1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5374     1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5375     1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5376     1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5377     1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5378     1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5379     1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5380     1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5381     1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5382     1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5383     1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5384     1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5385     1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5386     1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5387     1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5388     1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5389     1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5390     1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5391     1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5392     1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5393     1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5394     1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5395     1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5396     1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5397     1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5398     1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5399     1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5400     1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5401     1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5402     1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5403     1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5404     1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5405     1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5406     1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5407     1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5408     1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5409     1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5410     1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5411     1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5412     1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5413     1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5414     1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5415     1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5416     1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5417     1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5418     1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5419     1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5420     1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5421     1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5422     1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5423     1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5424     1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5425     1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5426     1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5427     1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5428     1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5429     1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5430     1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5431     1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5432     1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5433     1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5434     1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5435     1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5436     1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5437     1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5438     1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5439     1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5440     1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5441     1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5442     1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5443     1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5444     1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5445     1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5446     1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5447     1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5448     1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5449     1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5450     1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5451     1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5452     1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5453     1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5454     1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5455     1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5456     1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5457     1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5458     1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5459     1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5460     1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5461     1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5462     1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5463     1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5464     1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5465     1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5466     1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5467     1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5468     1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5469     1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5470     1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5471     1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5472     59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5473     46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5474     12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5475     12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5476     32,     773,    32,     773,    95,     95,     95,     44,     12289,
5477     46,     59,     58,     63,     33,     8212,   40,     41,     123,
5478     125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5479     62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5480     1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5481     32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5482     1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5483     1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5484     1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5485     1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5486     1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5487     1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5488     1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5489     1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5490     1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5491     1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5492     1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5493     1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5494     1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5495     1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5496     1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5497     1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5498     1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5499     1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5500     37,     38,     39,     40,     41,     42,     43,     44,     45,
5501     46,     47,     48,     49,     50,     51,     52,     53,     54,
5502     55,     56,     57,     58,     59,     60,     61,     62,     63,
5503     64,     65,     66,     67,     68,     69,     70,     71,     72,
5504     73,     74,     75,     76,     77,     78,     79,     80,     81,
5505     82,     83,     84,     85,     86,     87,     88,     89,     90,
5506     91,     92,     93,     94,     95,     96,     97,     98,     99,
5507     100,    101,    102,    103,    104,    105,    106,    107,    108,
5508     109,    110,    111,    112,    113,    114,    115,    116,    117,
5509     118,    119,    120,    121,    122,    123,    124,    125,    126,
5510     10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5511     12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5512     12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5513     12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5514     12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5515     12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5516     12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5517     12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5518     4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5519     4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5520     4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5521     4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5522     4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5523     162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5524     8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5525     665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5526     600,    606,    681,    612,    610,    608,    667,    295,    668,
5527     615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5528     654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5529     638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5530     673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5531     69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5532     70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5533     70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5534     119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5535     119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5536     119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5537     119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5538     68,     69,     70,     71,     72,     73,     74,     75,     76,
5539     77,     78,     79,     80,     81,     82,     83,     84,     85,
5540     86,     87,     88,     89,     90,     97,     98,     99,     100,
5541     101,    102,    103,    104,    105,    106,    107,    108,    109,
5542     110,    111,    112,    113,    114,    115,    116,    117,    118,
5543     119,    120,    121,    122,    65,     66,     67,     68,     69,
5544     70,     71,     72,     73,     74,     75,     76,     77,     78,
5545     79,     80,     81,     82,     83,     84,     85,     86,     87,
5546     88,     89,     90,     97,     98,     99,     100,    101,    102,
5547     103,    105,    106,    107,    108,    109,    110,    111,    112,
5548     113,    114,    115,    116,    117,    118,    119,    120,    121,
5549     122,    65,     66,     67,     68,     69,     70,     71,     72,
5550     73,     74,     75,     76,     77,     78,     79,     80,     81,
5551     82,     83,     84,     85,     86,     87,     88,     89,     90,
5552     97,     98,     99,     100,    101,    102,    103,    104,    105,
5553     106,    107,    108,    109,    110,    111,    112,    113,    114,
5554     115,    116,    117,    118,    119,    120,    121,    122,    65,
5555     67,     68,     71,     74,     75,     78,     79,     80,     81,
5556     83,     84,     85,     86,     87,     88,     89,     90,     97,
5557     98,     99,     100,    102,    104,    105,    106,    107,    108,
5558     109,    110,    112,    113,    114,    115,    116,    117,    118,
5559     119,    120,    121,    122,    65,     66,     67,     68,     69,
5560     70,     71,     72,     73,     74,     75,     76,     77,     78,
5561     79,     80,     81,     82,     83,     84,     85,     86,     87,
5562     88,     89,     90,     97,     98,     99,     100,    101,    102,
5563     103,    104,    105,    106,    107,    108,    109,    110,    111,
5564     112,    113,    114,    115,    116,    117,    118,    119,    120,
5565     121,    122,    65,     66,     68,     69,     70,     71,     74,
5566     75,     76,     77,     78,     79,     80,     81,     83,     84,
5567     85,     86,     87,     88,     89,     97,     98,     99,     100,
5568     101,    102,    103,    104,    105,    106,    107,    108,    109,
5569     110,    111,    112,    113,    114,    115,    116,    117,    118,
5570     119,    120,    121,    122,    65,     66,     68,     69,     70,
5571     71,     73,     74,     75,     76,     77,     79,     83,     84,
5572     85,     86,     87,     88,     89,     97,     98,     99,     100,
5573     101,    102,    103,    104,    105,    106,    107,    108,    109,
5574     110,    111,    112,    113,    114,    115,    116,    117,    118,
5575     119,    120,    121,    122,    65,     66,     67,     68,     69,
5576     70,     71,     72,     73,     74,     75,     76,     77,     78,
5577     79,     80,     81,     82,     83,     84,     85,     86,     87,
5578     88,     89,     90,     97,     98,     99,     100,    101,    102,
5579     103,    104,    105,    106,    107,    108,    109,    110,    111,
5580     112,    113,    114,    115,    116,    117,    118,    119,    120,
5581     121,    122,    65,     66,     67,     68,     69,     70,     71,
5582     72,     73,     74,     75,     76,     77,     78,     79,     80,
5583     81,     82,     83,     84,     85,     86,     87,     88,     89,
5584     90,     97,     98,     99,     100,    101,    102,    103,    104,
5585     105,    106,    107,    108,    109,    110,    111,    112,    113,
5586     114,    115,    116,    117,    118,    119,    120,    121,    122,
5587     65,     66,     67,     68,     69,     70,     71,     72,     73,
5588     74,     75,     76,     77,     78,     79,     80,     81,     82,
5589     83,     84,     85,     86,     87,     88,     89,     90,     97,
5590     98,     99,     100,    101,    102,    103,    104,    105,    106,
5591     107,    108,    109,    110,    111,    112,    113,    114,    115,
5592     116,    117,    118,    119,    120,    121,    122,    65,     66,
5593     67,     68,     69,     70,     71,     72,     73,     74,     75,
5594     76,     77,     78,     79,     80,     81,     82,     83,     84,
5595     85,     86,     87,     88,     89,     90,     97,     98,     99,
5596     100,    101,    102,    103,    104,    105,    106,    107,    108,
5597     109,    110,    111,    112,    113,    114,    115,    116,    117,
5598     118,    119,    120,    121,    122,    65,     66,     67,     68,
5599     69,     70,     71,     72,     73,     74,     75,     76,     77,
5600     78,     79,     80,     81,     82,     83,     84,     85,     86,
5601     87,     88,     89,     90,     97,     98,     99,     100,    101,
5602     102,    103,    104,    105,    106,    107,    108,    109,    110,
5603     111,    112,    113,    114,    115,    116,    117,    118,    119,
5604     120,    121,    122,    65,     66,     67,     68,     69,     70,
5605     71,     72,     73,     74,     75,     76,     77,     78,     79,
5606     80,     81,     82,     83,     84,     85,     86,     87,     88,
5607     89,     90,     97,     98,     99,     100,    101,    102,    103,
5608     104,    105,    106,    107,    108,    109,    110,    111,    112,
5609     113,    114,    115,    116,    117,    118,    119,    120,    121,
5610     122,    305,    567,    913,    914,    915,    916,    917,    918,
5611     919,    920,    921,    922,    923,    924,    925,    926,    927,
5612     928,    929,    920,    931,    932,    933,    934,    935,    936,
5613     937,    8711,   945,    946,    947,    948,    949,    950,    951,
5614     952,    953,    954,    955,    956,    957,    958,    959,    960,
5615     961,    962,    963,    964,    965,    966,    967,    968,    969,
5616     8706,   949,    952,    954,    966,    961,    960,    913,    914,
5617     915,    916,    917,    918,    919,    920,    921,    922,    923,
5618     924,    925,    926,    927,    928,    929,    920,    931,    932,
5619     933,    934,    935,    936,    937,    8711,   945,    946,    947,
5620     948,    949,    950,    951,    952,    953,    954,    955,    956,
5621     957,    958,    959,    960,    961,    962,    963,    964,    965,
5622     966,    967,    968,    969,    8706,   949,    952,    954,    966,
5623     961,    960,    913,    914,    915,    916,    917,    918,    919,
5624     920,    921,    922,    923,    924,    925,    926,    927,    928,
5625     929,    920,    931,    932,    933,    934,    935,    936,    937,
5626     8711,   945,    946,    947,    948,    949,    950,    951,    952,
5627     953,    954,    955,    956,    957,    958,    959,    960,    961,
5628     962,    963,    964,    965,    966,    967,    968,    969,    8706,
5629     949,    952,    954,    966,    961,    960,    913,    914,    915,
5630     916,    917,    918,    919,    920,    921,    922,    923,    924,
5631     925,    926,    927,    928,    929,    920,    931,    932,    933,
5632     934,    935,    936,    937,    8711,   945,    946,    947,    948,
5633     949,    950,    951,    952,    953,    954,    955,    956,    957,
5634     958,    959,    960,    961,    962,    963,    964,    965,    966,
5635     967,    968,    969,    8706,   949,    952,    954,    966,    961,
5636     960,    913,    914,    915,    916,    917,    918,    919,    920,
5637     921,    922,    923,    924,    925,    926,    927,    928,    929,
5638     920,    931,    932,    933,    934,    935,    936,    937,    8711,
5639     945,    946,    947,    948,    949,    950,    951,    952,    953,
5640     954,    955,    956,    957,    958,    959,    960,    961,    962,
5641     963,    964,    965,    966,    967,    968,    969,    8706,   949,
5642     952,    954,    966,    961,    960,    988,    989,    48,     49,
5643     50,     51,     52,     53,     54,     55,     56,     57,     48,
5644     49,     50,     51,     52,     53,     54,     55,     56,     57,
5645     48,     49,     50,     51,     52,     53,     54,     55,     56,
5646     57,     48,     49,     50,     51,     52,     53,     54,     55,
5647     56,     57,     48,     49,     50,     51,     52,     53,     54,
5648     55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5649     1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5650     1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5651     1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5652     1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5653     1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5654     1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5655     42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5656     1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5657     1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5658     1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5659     1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5660     1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5661     1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5662     1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5663     1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5664     1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5665     1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5666     1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5667     1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5668     1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5669     1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5670     1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5671     46,     48,     44,     49,     44,     50,     44,     51,     44,
5672     52,     44,     53,     44,     54,     44,     55,     44,     56,
5673     44,     57,     44,     40,     65,     41,     40,     66,     41,
5674     40,     67,     41,     40,     68,     41,     40,     69,     41,
5675     40,     70,     41,     40,     71,     41,     40,     72,     41,
5676     40,     73,     41,     40,     74,     41,     40,     75,     41,
5677     40,     76,     41,     40,     77,     41,     40,     78,     41,
5678     40,     79,     41,     40,     80,     41,     40,     81,     41,
5679     40,     82,     41,     40,     83,     41,     40,     84,     41,
5680     40,     85,     41,     40,     86,     41,     40,     87,     41,
5681     40,     88,     41,     40,     89,     41,     40,     90,     41,
5682     12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5683     65,     66,     67,     68,     69,     70,     71,     72,     73,
5684     74,     75,     76,     77,     78,     79,     80,     81,     82,
5685     83,     84,     85,     86,     87,     88,     89,     90,     72,
5686     86,     77,     86,     83,     68,     83,     83,     80,     80,
5687     86,     87,     67,     77,     67,     77,     68,     77,     82,
5688     68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5689     21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5690     28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5691     36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5692     24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5693     28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5694     12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5695     12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5696     12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5697     48,     49,     50,     51,     52,     53,     54,     55,     56,
5698     57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5699     20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5700     20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5701     20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5702     21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5703     21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5704     28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5705     21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5706     21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5707     20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5708     136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5709     23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5710     23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5711     24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5712     138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5713     24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5714     172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5715     156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5716     14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5717     24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5718     25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5719     25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5720     25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5721     15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5722     17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5723     26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5724     27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5725     15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5726     146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5727     28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5728     147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5729     15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5730     148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5731     29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5732     29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5733     30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5734     151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5735     16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5736     153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5737     154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5738     17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5739     32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5740     32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5741     32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5742     33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5743     33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5744     33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5745     158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5746     17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5747     34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5748     34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5749     13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5750     162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5751     36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5752     165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5753     38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5754     168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5755     38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5756     170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5757     172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5758     40726,  40763,  173568};
5759 
5760 const uint8_t canonical_combining_class_index[4352] = {
5761     0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5762     15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5763     0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5764     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5765     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5766     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5767     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5768     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5769     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5770     31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5771     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5772     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5773     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5774     0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5775     37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5776     53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5777     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5778     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5779     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5780     0,  55, 56, 0,  0,  0,  57, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5781     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5782     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5783     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5784     0,  0,  0,  0,  0,  0,  0,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5785     0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5786     0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5787     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5788     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5789     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5790     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5791     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5792     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5793     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5794     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5795     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5796     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5797     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5798     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5799     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5800     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5801     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5802     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5803     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5804     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5805     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5806     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5807     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5808     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5809     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5812     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5813     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5814     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5815     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5816     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5817     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5818     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5819     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5820     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5821     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5823     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5824     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990     0};
5991 const uint8_t canonical_combining_class_block[67][256] = {
5992     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5993      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5994      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5995      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5996      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5997      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5998      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5999      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6000      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6001      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6002      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6003     {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6004      230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6005      220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6006      220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6007      220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6008      230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6009      220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6010      230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6011      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6012      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6013      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6014      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6015      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6016      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6017      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6018      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6019      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6020      0},
6021     {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6022      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6023      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6024      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6025      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6026      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6027      230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6028      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6029      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6030      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6031      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6032      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6033     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6034      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6035      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6036      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6037      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6038      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6039      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6040      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6041      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6042      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6043      220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6044      220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6045      14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6046      0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6047      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6048      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6049      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6050      0},
6051     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6052      0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6053      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6054      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6055      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056      27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6057      230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6058      0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6059      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6060      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6061      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6062      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6063      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6064      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6065      0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6066      230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6067      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6068      0},
6069     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6070      0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6071      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6072      0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6073      220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6074      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6075      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6076      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6077      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6078      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6079      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6080      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6081      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6082      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6083      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6085      230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6086      0},
6087     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6088      0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6089      230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6090      230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6091      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6093      220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6094      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6095      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6096      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097      0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6098      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6099      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6100      0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6101      220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6102      230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6103      27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6104      230},
6105     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6106      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6107      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6108      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6109      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6110      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6111      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6112      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6113      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6114      0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6115      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6116      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6117     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6118      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6119      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6120      0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6121      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6122      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6123      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6124      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6125      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6126      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6127      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6128     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6129      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6130      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6131      0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6132      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6133      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6134      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6135      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6136      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6137      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6138      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6139     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6140      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6141      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6142      0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6143      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6144      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6145      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6146      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6147      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6148      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6149      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0},
6150     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6151      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6152      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6153      0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6154      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6158      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6161     {0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6162      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6163      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164      0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6165      107, 107, 107, 107, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6166      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6167      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6168      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6169      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6170      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6171      0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6172      0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6173      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175      0,   0,   0,   0},
6176     {0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6177      0,   0, 0,   0,   0,   0,   0, 0, 0,   220, 220, 0,   0,   0, 0,
6178      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6179      0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6180      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6181      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6182      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6183      0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6184      0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6185      230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6186      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6187      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6188      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6189      0,   0, 0,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6190      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6191      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6192      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6193      0},
6194     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6195      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6196      0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6197      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6198      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6199      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6200      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6201      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6202      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6203      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6204      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6205     {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6206      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6207      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6208      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6209      0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6210      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6211      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6212      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6213      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6214      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6215      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6216      0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0},
6217     {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6218      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6219      0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6220      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6221      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6222      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6223      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6224      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6225      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6226      0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6227      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6228     {0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6229      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6230      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6231      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6232      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6233      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6234      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6235      0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6236      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6237      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6238      0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6239     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6240      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6241      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6242      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6243      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6244      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6245      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6246      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6247      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6248      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6249      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6250      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6251     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6252      0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6253      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6254      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6255      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6256      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6257      0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6258      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6259      230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6260      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6261      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6262      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6263      230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6264      220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6265      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6266      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6267      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6268      0},
6269     {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6270      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6271      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6272      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6273      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6274      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6275      230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6276      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6277      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6278      9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6279      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6280      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6281      0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6282      0,   0,   0, 0, 0, 0, 0, 0, 0},
6283     {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6284      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6285      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6286      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6287      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6288      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6289      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6290      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6291      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6292      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6293      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6294      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6295      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6296      0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6297      230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6298      0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6299      0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6300      0},
6301     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6302      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6303      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6304      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6305      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6306      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6307      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6308      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6309      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6310      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6311      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6312      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6313      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 220,
6314      230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6315      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6316      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6317      230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6318      220},
6319     {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6320      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6321      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6322      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6323      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6324      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6325      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6326      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6327      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6328      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6329      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6330      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6331      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6332      230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6333      0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6334      230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6335     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6336      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6337      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6338      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6339      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6340      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6341      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6342      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6343      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6344      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6345      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6346      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6347     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6348      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6349      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6350      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6351      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6352      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6353      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6354      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6355      0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6356      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6357      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6358      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6359      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6360      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6361      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6362      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6363      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6364      230},
6365     {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6366      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6367      0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6368      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6369      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6370      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6371      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6372      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
6373      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6374      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6375      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6376      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6377      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6378     {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6379      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6380      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6381      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6382      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6383      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6384      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6385      0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6386      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6387      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6388      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6389      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6390      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6391      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6392      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6393      230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6394     {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6395      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6396      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6397      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6398      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6399      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6400      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6401      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6402      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6403      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6404      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6405      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6406      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6407      0,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6408      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6409      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6410      230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6411      0},
6412     {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6413      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6414      220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6415      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6416      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6417      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6418      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6419      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6420      0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6421      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6422      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6423      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6424     {0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6425      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6426      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6427      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6428      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6429      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6430      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6431      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6432      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6433      0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6434      230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6435      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6436      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6437      0,   0,   0, 0,   0, 0,   0, 0,   0},
6438     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6439      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6440      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6441      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6442      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6443      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6444      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6445      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6446      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6447      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
6448      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6449     {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6450      0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6451      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6452      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6453      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6454      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6455      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6456      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6457      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6458      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6459      0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0},
6460     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6461      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6462      0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6463      220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6464      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6465      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6466      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6467      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6468      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6469      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6470      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6471      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6472      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6473      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6474      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6475      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6476      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6477      0},
6478     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6479      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6480      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6481      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6482      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6483      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6484      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6485      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6486      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6487      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6488      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6489     {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6490      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6491      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6492      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6493      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6494      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6495      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6496      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6497      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6498      0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6499      0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0},
6500     {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6501      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6502      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6503      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6504      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6505      0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6506      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6507      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6508      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6509      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6510      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6511      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6512     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6513      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6514      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6515      0, 0, 0, 9, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6516      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6517      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6518      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6519      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6520      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6521      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6522      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6523      0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6524      0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6525     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6526      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
6527      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6528      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6529      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6530      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6531      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6532      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6533      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6534      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6535      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6536      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6537     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6538      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6539      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6540      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6541      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6542      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6543      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6544      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 230, 230, 0, 0, 0,
6545      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6546      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6547      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6548      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6549     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6550      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6551      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6552      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6553      230, 230, 230, 220, 230, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6554      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6555      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6556      0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6557      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6558      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6559      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6560      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6561      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6562      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6563      0,   0,   0,   0},
6564     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6565      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6566      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6567      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6568      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
6569      0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6570      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6571      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6572      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6573      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6574      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6575     {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6576      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6577      0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6578      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6579      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6580      0,   0,   0,   0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6581      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6582      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6583      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6584      0,   0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6585      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6586      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6587     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6588      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6589      0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6590      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6591      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6592      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6593      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6594      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6596      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0,
6597      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6598     {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6599      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6600      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6601      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6602      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6603      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6604      0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6605      230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6606      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6607      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6608      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6609      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6610      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6611      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6612      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6613      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0},
6614     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6615      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6616      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 7,   0,
6617      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6618      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6619      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6620      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6621      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6622      0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6623      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6624      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6625     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6626      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6627      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6628      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6629      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6630      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6631      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6632      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6633      7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6634      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6635      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6636     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6637      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6638      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6639      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6640      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6641      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6642      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6643      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6644      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6645      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6646      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6647     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6648      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6649      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6650      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6651      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6652      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6653      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6654      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6655      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6656      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6657      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6658     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6659      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6660      0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6661      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6662      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6666      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6669     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6670      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6671      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6672      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6673      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6674      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6675      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6676      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6677      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6678      0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6679      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6680     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6681      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682      0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6683      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6684      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6685      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6686      0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6687      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6688      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6689      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6690      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6691     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6692      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6693      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6694      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6695      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6696      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6697      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6702     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6705      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6706      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708      0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6709      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6711      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6712      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6713     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6715      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0,
6716      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6717      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6720      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6722      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6723      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6724     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6725      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6726      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6727      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6728      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6729      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6730      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6731      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6734      1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6735     {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6736      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6737      0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6738      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6739      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6740      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6741      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6742      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6743      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6744      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6745      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6746      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6747      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6748     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6749      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6750      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6751      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6752      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6753      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6754      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6755      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6756      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6757      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6758      6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6759     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6760      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6761      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6762      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6763      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6764      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6765      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6766      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6767      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6768      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6769      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6770     {0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6771      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6772      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6773      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6774      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6775      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6776      0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6777      216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6778      220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6779      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6780      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   0,
6781      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6782      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6783      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6784      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6785      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6786     {0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6788      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6789      230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6790      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6791      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6792      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6793      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6794      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6795      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6796      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6797      0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6798     {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6799      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6800      230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6801      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6802      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6803      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6804      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6805      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6806      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6807      0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6808      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6809      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6810      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6811      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6812      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6813      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6814      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6815      0},
6816     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6817      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6818      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6819      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6820      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6821      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6822      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6823      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6824      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6825      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6826      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6827      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6828     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6829      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6830      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6831      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6832      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6833      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6834      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6835      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6836      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6837      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6838      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6839      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6840     {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6841      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6842      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6843      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6844      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6845      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6846      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6847      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6848      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6849      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6850      0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6851      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6852      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6853     {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6854      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6855      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6856      0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6857      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6858      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6859      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6860      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6861      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6862      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6863      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6864      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6865      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6866 
6867 const uint8_t composition_index[4352] = {
6868     0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6869     5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6870     5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6871     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6872     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6873     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6874     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6875     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6876     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6877     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6878     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6879     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6880     5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6881     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6882     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6883     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6884     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6885     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6886     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6887     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6888     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6889     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6890     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6891     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6892     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6893     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6894     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6895     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6896     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6897     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6898     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6899     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6900     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6901     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6902     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6903     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6904     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6905     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6906     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6907     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6908     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6909     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6910     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6911     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6912     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6913     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6914     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6915     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6916     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6917     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6918     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7066 const uint16_t composition_block[67][257] = {
7067     {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7068      1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7069      1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7070      1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7071      1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7072      163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7073      365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7074      503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7075      719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7076      755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7077      755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7078      755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7079      761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7080      769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7081      789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7082      815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7083      843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7084      869, 869},
7085     {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7086      885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7087      893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7088      893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7089      893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7090      893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7091      901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7092      911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7093      917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7094      919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7095      919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7096      939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7097      959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7098      961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7099      961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7100      961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7101      965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7102      965, 965},
7103     {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7104      965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7105      965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7106      973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7107      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7108      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7109      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7110      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7111      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7112      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7113      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7114      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7115      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7116      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7117      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7118      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7119      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7120      979, 979},
7121     {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7122      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7123      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7124      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7125      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7126      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7127      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7128      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7129      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7130      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7131      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7132      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7133      979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7134      1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7135      1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7136      1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7137      1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7138      1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7139      1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7140      1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7141      1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7142      1171, 1171, 1171, 1171, 1171},
7143     {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7144      1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7145      1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7146      1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7147      1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7148      1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7149      1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7150      1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7151      1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7152      1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7153      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7154      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7155      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7156      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7157      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7158      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7159      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7160      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7161      1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7162      1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7163      1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7164      1275, 1275, 1275, 1275, 1275},
7165     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7166      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7167      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7168      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7169      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7170      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7171      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7172      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7173      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7174      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7175      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7176     {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7177      1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7178      1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7179      1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7180      1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7181      1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7182      1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7183      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7184      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7185      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7186      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7187      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7188      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7189      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7190      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7191      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7192      1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7193      1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7194      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7195      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7196      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7197      1291, 1291, 1291, 1291, 1291},
7198     {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7199      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7200      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7201      1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7202      1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7203      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7204      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7205      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7206      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7207      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7208      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7209      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7210      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7211      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7212      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7213      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7214      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7215      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7216      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7217      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7218      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7219      1301, 1301, 1301, 1301, 1301},
7220     {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7221      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7222      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7223      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7224      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7225      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7226      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7227      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7228      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7229      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7230      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7231      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7232      1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7233      1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7234      1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7235      1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7236      1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7237      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7238      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7239      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7240      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7241      1315, 1315, 1315, 1315, 1315},
7242     {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7243      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7244      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7245      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7246      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7247      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7248      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7249      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7250      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7251      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7252      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7253      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7254      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7255      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7256      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7257      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7258      1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7259      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7260      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7261      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7262      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7263      1327, 1327, 1327, 1327, 1327},
7264     {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7265      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7266      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7267      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7268      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7269      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7270      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7271      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7272      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7273      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7274      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7275      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7276      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7277      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7278      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7279      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7280      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7281      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7282      1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7283      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7284      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7285      1341, 1341, 1341, 1341, 1341},
7286     {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7287      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7288      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7289      1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7290      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7291      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7292      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7293      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7294      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7295      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7296      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7297      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7298      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7299      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7300      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7301      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7302      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7303      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7304      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7305      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7306      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7307      1343, 1343, 1343, 1343, 1343},
7308     {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7309      1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7310      1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7311      1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7312      1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7313      1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7314      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7315      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7316      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7317      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7318      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7319      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7320      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7321      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7322      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7323      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7324      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7325      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7326      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7327      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7328      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7329      1365, 1365, 1365, 1365, 1365},
7330     {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7331      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7332      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7333      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7334      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7335      1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7336      1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7337      1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7338      1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7339      1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7340      1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7341      1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7342      1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7343      1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7344      1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7345      1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7346      1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7347      1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7348      1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7349      1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7350      1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7351      1393, 1393, 1393, 1393, 1393},
7352     {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7353      1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7354      1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7355      1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7356      1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7357      1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7358      1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7359      1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7360      1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7361      1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7362      1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7363      1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7364      1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7365      1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7366      1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7367      1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7368      1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7369      1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7370      1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7371      1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7372      1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7373      1653, 1653, 1653, 1659, 1659},
7374     {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7375      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7376      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7377      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7378      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7379      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7380      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7381      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7382      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7383      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7384      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7385      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7386      1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7387      1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7388      1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7389      1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7390      1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7391      1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7392      1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7393      1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7394      1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7395      1671, 1671, 1671, 1671, 1671},
7396     {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7397      1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7398      1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7399      1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7400      1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7401      1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7402      1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7403      1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7404      1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7405      1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7406      1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7407      1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7408      1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7409      1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7410      1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7411      1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7412      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7413      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7414      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7415      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7416      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7417      1741, 1741, 1741, 1741, 1741},
7418     {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7419      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7420      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7421      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7422      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7423      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7424      1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7425      1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7426      1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7427      1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7428      1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7429      1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7430      1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7431      1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7432      1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7433      1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7434      1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7435      1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7436      1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7437      1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7438      1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7439      1855, 1855, 1857, 1857, 1857},
7440     {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7441      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7442      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7443      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7444      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7445      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7446      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7447      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7448      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7449      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7450      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7451      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7452      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7453      1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7454      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7455      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7456      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7457      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7458      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7459      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7460      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7461      1863, 1863, 1863, 1863, 1863},
7462     {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7463      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7464      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7465      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7466      1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7467      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7468      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7469      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7470      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7471      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7472      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7473      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7474      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7475      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7476      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7477      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7478      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7479      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7480      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7481      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7482      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7483      1867, 1867, 1867, 1867, 1867},
7484     {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7485      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7486      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7487      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7488      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7489      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7490      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7491      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7492      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7493      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7494      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7495      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7496      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7497      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7498      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7499      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7500      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7501      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7502      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7503      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7504      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7505      1871, 1871, 1871, 1871, 1871},
7506     {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7507      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7508      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7509      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7510      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7511      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7512      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7513      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7514      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7515      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7516      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7517      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7518      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7519      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7520      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7521      1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7522      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7523      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7524      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7525      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7526      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7527      1877, 1877, 1877, 1877, 1877},
7528     {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7529      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7530      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7531      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7532      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7533      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7534      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7535      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7536      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7537      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7538      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7539      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7540      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7541      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7542      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7543      1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7544      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7545      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7546      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7547      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7548      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7549      1881, 1881, 1881, 1881, 1881},
7550     {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7551      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7552      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7553      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7554      1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7555      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7556      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7557      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7558      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7559      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7560      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7561      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7562      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7563      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7564      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7565      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7566      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7567      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7568      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7569      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7570      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7571      1883, 1883, 1883, 1883, 1883}};
7572 const char32_t composition_data[1883] = {
7573     0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7574     770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7575     196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7576     803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7577     7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7578     775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7579     7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7580     774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7581     516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7582     816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7583     286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7584     776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7585     204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7586     775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7587     522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7588     780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7589     317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7590     775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7591     7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7592     768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7593     334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7594     783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7595     7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7596     785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7597     348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7598     775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7599     7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7600     772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7601     368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7602     804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7603     7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7604     803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7605     374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7606     803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7607     7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7608     772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7609     229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7610     808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7611     265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7612     803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7613     233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7614     776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7615     7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7616     769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7617     487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7618     803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7619     237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7620     777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7621     303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7622     803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7623     7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7624     803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7625     328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7626     769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7627     559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7628     785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7629     7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7630     803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7631     7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7632     776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7633     7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7634     772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7635     369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7636     804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7637     7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7638     778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7639     253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7640     777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7641     380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7642     834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7643     478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7644     769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7645     7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7646     772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7647     473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7648     769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7649     7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7650     771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7651     555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7652     768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7653     7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7654     769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7655     7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7656     776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7657     7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7658     777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7659     7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7660     803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7661     481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7662     768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7663     7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7664     768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7665     8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7666     788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7667     8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7668     788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7669     8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7670     774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7671     8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7672     787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7673     943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7674     834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7675     8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7676     776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7677     974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7678     769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7679     8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7680     769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7681     1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7682     769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7683     1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7684     769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7685     1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7686     769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7687     1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7688     783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7689     1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7690     1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7691     2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7692     3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7693     3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7694     3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7695     4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7696     6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7697     6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7698     775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7699     7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7700     834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7701     8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7702     837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7703     7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7704     837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7705     7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7706     769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7707     7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7708     837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7709     7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7710     837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7711     8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7712     769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7713     7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7714     769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7715     8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7716     768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7717     8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7718     837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7719     8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7720     769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7721     8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7722     837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7723     8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7724     824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7725     8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7726     824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7727     8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7728     824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7729     8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7730     824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7731     8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7732     12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7733     12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7734     12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7735     12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7736     12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7737     12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7738     12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7739     12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7740     12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7741     12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7742     69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7743     70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7744     71984, 71992};
7745 
7746 }  // namespace ada::idna
7747 #endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7748 /* end file src/normalization_tables.cpp */
7749 
7750 namespace ada::idna {
7751 
7752 // See
7753 // https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7754 constexpr char32_t hangul_sbase = 0xAC00;
7755 constexpr char32_t hangul_tbase = 0x11A7;
7756 constexpr char32_t hangul_vbase = 0x1161;
7757 constexpr char32_t hangul_lbase = 0x1100;
7758 constexpr char32_t hangul_lcount = 19;
7759 constexpr char32_t hangul_vcount = 21;
7760 constexpr char32_t hangul_tcount = 28;
7761 constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7762 constexpr char32_t hangul_scount =
7763     hangul_lcount * hangul_vcount * hangul_tcount;
7764 
compute_decomposition_length(const std::u32string_view input)7765 std::pair<bool, size_t> compute_decomposition_length(
7766     const std::u32string_view input) noexcept {
7767   bool decomposition_needed{false};
7768   size_t additional_elements{0};
7769   for (char32_t current_character : input) {
7770     size_t decomposition_length{0};
7771 
7772     if (current_character >= hangul_sbase &&
7773         current_character < hangul_sbase + hangul_scount) {
7774       decomposition_length = 2;
7775       if ((current_character - hangul_sbase) % hangul_tcount) {
7776         decomposition_length = 3;
7777       }
7778     } else if (current_character < 0x110000) {
7779       const uint8_t di = decomposition_index[current_character >> 8];
7780       const uint16_t* const decomposition =
7781           decomposition_block[di] + (current_character % 256);
7782       decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7783       if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7784         decomposition_length = 0;
7785       }
7786     }
7787     if (decomposition_length != 0) {
7788       decomposition_needed = true;
7789       additional_elements += decomposition_length - 1;
7790     }
7791   }
7792   return {decomposition_needed, additional_elements};
7793 }
7794 
decompose(std::u32string & input,size_t additional_elements)7795 void decompose(std::u32string& input, size_t additional_elements) {
7796   input.resize(input.size() + additional_elements);
7797   for (size_t descending_idx = input.size(),
7798               input_count = descending_idx - additional_elements;
7799        input_count--;) {
7800     if (input[input_count] >= hangul_sbase &&
7801         input[input_count] < hangul_sbase + hangul_scount) {
7802       // Hangul decomposition.
7803       char32_t s_index = input[input_count] - hangul_sbase;
7804       if (s_index % hangul_tcount != 0) {
7805         input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7806       }
7807       input[--descending_idx] =
7808           hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7809       input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7810     } else if (input[input_count] < 0x110000) {
7811       // Check decomposition_data.
7812       const uint16_t* decomposition =
7813           decomposition_block[decomposition_index[input[input_count] >> 8]] +
7814           (input[input_count] % 256);
7815       uint16_t decomposition_length =
7816           (decomposition[1] >> 2) - (decomposition[0] >> 2);
7817       if (decomposition_length > 0 && (decomposition[0] & 1)) {
7818         decomposition_length = 0;
7819       }
7820       if (decomposition_length > 0) {
7821         // Non-recursive decomposition.
7822         while (decomposition_length-- > 0) {
7823           input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7824                                                        decomposition_length];
7825         }
7826       } else {
7827         // No decomposition.
7828         input[--descending_idx] = input[input_count];
7829       }
7830     } else {
7831       // Non-Unicode character.
7832       input[--descending_idx] = input[input_count];
7833     }
7834   }
7835 }
7836 
get_ccc(char32_t c)7837 uint8_t get_ccc(char32_t c) noexcept {
7838   return c < 0x110000 ? canonical_combining_class_block
7839                             [canonical_combining_class_index[c >> 8]][c % 256]
7840                       : 0;
7841 }
7842 
sort_marks(std::u32string & input)7843 void sort_marks(std::u32string& input) {
7844   for (size_t idx = 1; idx < input.size(); idx++) {
7845     uint8_t ccc = get_ccc(input[idx]);
7846     if (ccc == 0) {
7847       continue;
7848     }  // Skip non-combining characters.
7849     auto current_character = input[idx];
7850     size_t back_idx = idx;
7851     while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7852       input[back_idx] = input[back_idx - 1];
7853       back_idx--;
7854     }
7855     input[back_idx] = current_character;
7856   }
7857 }
7858 
decompose_nfc(std::u32string & input)7859 void decompose_nfc(std::u32string& input) {
7860   /**
7861    * Decompose the domain_name string to Unicode Normalization Form C.
7862    * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7863    */
7864   auto [decomposition_needed, additional_elements] =
7865       compute_decomposition_length(input);
7866   if (decomposition_needed) {
7867     decompose(input, additional_elements);
7868   }
7869   sort_marks(input);
7870 }
7871 
compose(std::u32string & input)7872 void compose(std::u32string& input) {
7873   /**
7874    * Compose the domain_name string to Unicode Normalization Form C.
7875    * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7876    */
7877   size_t input_count{0};
7878   size_t composition_count{0};
7879   for (; input_count < input.size(); input_count++, composition_count++) {
7880     input[composition_count] = input[input_count];
7881     if (input[input_count] >= hangul_lbase &&
7882         input[input_count] < hangul_lbase + hangul_lcount) {
7883       if (input_count + 1 < input.size() &&
7884           input[input_count + 1] >= hangul_vbase &&
7885           input[input_count + 1] < hangul_vbase + hangul_vcount) {
7886         input[composition_count] =
7887             hangul_sbase +
7888             ((input[input_count] - hangul_lbase) * hangul_vcount +
7889              input[input_count + 1] - hangul_vbase) *
7890                 hangul_tcount;
7891         input_count++;
7892         if (input_count + 1 < input.size() &&
7893             input[input_count + 1] > hangul_tbase &&
7894             input[input_count + 1] < hangul_tbase + hangul_tcount) {
7895           input[composition_count] += input[++input_count] - hangul_tbase;
7896         }
7897       }
7898     } else if (input[input_count] >= hangul_sbase &&
7899                input[input_count] < hangul_sbase + hangul_scount) {
7900       if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7901           input_count + 1 < input.size() &&
7902           input[input_count + 1] > hangul_tbase &&
7903           input[input_count + 1] < hangul_tbase + hangul_tcount) {
7904         input[composition_count] += input[++input_count] - hangul_tbase;
7905       }
7906     } else if (input[input_count] < 0x110000) {
7907       const uint16_t* composition =
7908           &composition_block[composition_index[input[input_count] >> 8]]
7909                             [input[input_count] % 256];
7910       size_t initial_composition_count = composition_count;
7911       for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7912            input_count++) {
7913         uint8_t ccc = get_ccc(input[input_count + 1]);
7914 
7915         if (composition[1] != composition[0] && previous_ccc < ccc) {
7916           // Try finding a composition.
7917           uint16_t left = composition[0];
7918           uint16_t right = composition[1];
7919           while (left + 2 < right) {
7920             // mean without overflow
7921             uint16_t middle = left + (((right - left) >> 1) & ~1);
7922             if (composition_data[middle] <= input[input_count + 1]) {
7923               left = middle;
7924             }
7925             if (composition_data[middle] >= input[input_count + 1]) {
7926               right = middle;
7927             }
7928           }
7929           if (composition_data[left] == input[input_count + 1]) {
7930             input[initial_composition_count] = composition_data[left + 1];
7931             composition =
7932                 &composition_block
7933                     [composition_index[composition_data[left + 1] >> 8]]
7934                     [composition_data[left + 1] % 256];
7935             continue;
7936           }
7937         }
7938 
7939         if (ccc == 0) {
7940           break;
7941         }  // Not a combining character.
7942         previous_ccc = ccc;
7943         input[++composition_count] = input[input_count + 1];
7944       }
7945     }
7946   }
7947 
7948   if (composition_count < input_count) {
7949     input.resize(composition_count);
7950   }
7951 }
7952 
normalize(std::u32string & input)7953 void normalize(std::u32string& input) {
7954   /**
7955    * Normalize the domain_name string to Unicode Normalization Form C.
7956    * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7957    */
7958   decompose_nfc(input);
7959   compose(input);
7960 }
7961 
7962 }  // namespace ada::idna
7963 /* end file src/normalization.cpp */
7964 /* begin file src/punycode.cpp */
7965 
7966 #include <cstdint>
7967 
7968 namespace ada::idna {
7969 
7970 constexpr int32_t base = 36;
7971 constexpr int32_t tmin = 1;
7972 constexpr int32_t tmax = 26;
7973 constexpr int32_t skew = 38;
7974 constexpr int32_t damp = 700;
7975 constexpr int32_t initial_bias = 72;
7976 constexpr uint32_t initial_n = 128;
7977 
char_to_digit_value(char value)7978 static constexpr int32_t char_to_digit_value(char value) {
7979   if (value >= 'a' && value <= 'z') return value - 'a';
7980   if (value >= '0' && value <= '9') return value - '0' + 26;
7981   return -1;
7982 }
7983 
digit_to_char(int32_t digit)7984 static constexpr char digit_to_char(int32_t digit) {
7985   return digit < 26 ? char(digit + 97) : char(digit + 22);
7986 }
7987 
adapt(int32_t d,int32_t n,bool firsttime)7988 static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
7989   if (firsttime) {
7990     d = d / damp;
7991   } else {
7992     d = d / 2;
7993   }
7994   d += d / n;
7995   int32_t k = 0;
7996   while (d > ((base - tmin) * tmax) / 2) {
7997     d /= base - tmin;
7998     k += base;
7999   }
8000   return k + (((base - tmin + 1) * d) / (d + skew));
8001 }
8002 
punycode_to_utf32(std::string_view input,std::u32string & out)8003 bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8004   int32_t written_out{0};
8005   out.reserve(out.size() + input.size());
8006   uint32_t n = initial_n;
8007   int32_t i = 0;
8008   int32_t bias = initial_bias;
8009   // grab ascii content
8010   size_t end_of_ascii = input.find_last_of('-');
8011   if (end_of_ascii != std::string_view::npos) {
8012     for (uint8_t c : input.substr(0, end_of_ascii)) {
8013       if (c >= 0x80) {
8014         return false;
8015       }
8016       out.push_back(c);
8017       written_out++;
8018     }
8019     input.remove_prefix(end_of_ascii + 1);
8020   }
8021   while (!input.empty()) {
8022     int32_t oldi = i;
8023     int32_t w = 1;
8024     for (int32_t k = base;; k += base) {
8025       if (input.empty()) {
8026         return false;
8027       }
8028       uint8_t code_point = input.front();
8029       input.remove_prefix(1);
8030       int32_t digit = char_to_digit_value(code_point);
8031       if (digit < 0) {
8032         return false;
8033       }
8034       if (digit > (0x7fffffff - i) / w) {
8035         return false;
8036       }
8037       i = i + digit * w;
8038       int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8039       if (digit < t) {
8040         break;
8041       }
8042       if (w > 0x7fffffff / (base - t)) {
8043         return false;
8044       }
8045       w = w * (base - t);
8046     }
8047     bias = adapt(i - oldi, written_out + 1, oldi == 0);
8048     if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8049       return false;
8050     }
8051     n = n + i / (written_out + 1);
8052     i = i % (written_out + 1);
8053     if (n < 0x80) {
8054       return false;
8055     }
8056     out.insert(out.begin() + i, n);
8057     written_out++;
8058     ++i;
8059   }
8060 
8061   return true;
8062 }
8063 
verify_punycode(std::string_view input)8064 bool verify_punycode(std::string_view input) {
8065   size_t written_out{0};
8066   uint32_t n = initial_n;
8067   int32_t i = 0;
8068   int32_t bias = initial_bias;
8069   // grab ascii content
8070   size_t end_of_ascii = input.find_last_of('-');
8071   if (end_of_ascii != std::string_view::npos) {
8072     for (uint8_t c : input.substr(0, end_of_ascii)) {
8073       if (c >= 0x80) {
8074         return false;
8075       }
8076       written_out++;
8077     }
8078     input.remove_prefix(end_of_ascii + 1);
8079   }
8080   while (!input.empty()) {
8081     int32_t oldi = i;
8082     int32_t w = 1;
8083     for (int32_t k = base;; k += base) {
8084       if (input.empty()) {
8085         return false;
8086       }
8087       uint8_t code_point = input.front();
8088       input.remove_prefix(1);
8089       int32_t digit = char_to_digit_value(code_point);
8090       if (digit < 0) {
8091         return false;
8092       }
8093       if (digit > (0x7fffffff - i) / w) {
8094         return false;
8095       }
8096       i = i + digit * w;
8097       int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8098       if (digit < t) {
8099         break;
8100       }
8101       if (w > 0x7fffffff / (base - t)) {
8102         return false;
8103       }
8104       w = w * (base - t);
8105     }
8106     bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8107     if (i / (written_out + 1) > 0x7fffffff - n) {
8108       return false;
8109     }
8110     n = n + i / int32_t(written_out + 1);
8111     i = i % int32_t(written_out + 1);
8112     if (n < 0x80) {
8113       return false;
8114     }
8115     written_out++;
8116     ++i;
8117   }
8118 
8119   return true;
8120 }
8121 
utf32_to_punycode(std::u32string_view input,std::string & out)8122 bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8123   out.reserve(input.size() + out.size());
8124   uint32_t n = initial_n;
8125   int32_t d = 0;
8126   int32_t bias = initial_bias;
8127   size_t h = 0;
8128   // first push the ascii content
8129   for (uint32_t c : input) {
8130     if (c < 0x80) {
8131       ++h;
8132       out.push_back(char(c));
8133     }
8134     if (c > 0x10ffff || (c >= 0xd880 && c < 0xe000)) {
8135       return false;
8136     }
8137   }
8138   size_t b = h;
8139   if (b > 0) {
8140     out.push_back('-');
8141   }
8142   while (h < input.size()) {
8143     uint32_t m = 0x10FFFF;
8144     for (auto code_point : input) {
8145       if (code_point >= n && code_point < m) m = code_point;
8146     }
8147 
8148     if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8149       return false;
8150     }
8151     d = d + int32_t((m - n) * (h + 1));
8152     n = m;
8153     for (auto c : input) {
8154       if (c < n) {
8155         if (d == 0x7fffffff) {
8156           return false;
8157         }
8158         ++d;
8159       }
8160       if (c == n) {
8161         int32_t q = d;
8162         for (int32_t k = base;; k += base) {
8163           int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8164 
8165           if (q < t) {
8166             break;
8167           }
8168           out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8169           q = (q - t) / (base - t);
8170         }
8171         out.push_back(digit_to_char(q));
8172         bias = adapt(d, int32_t(h + 1), h == b);
8173         d = 0;
8174         ++h;
8175       }
8176     }
8177     ++d;
8178     ++n;
8179   }
8180   return true;
8181 }
8182 
8183 }  // namespace ada::idna
8184 /* end file src/punycode.cpp */
8185 /* begin file src/validity.cpp */
8186 #include <algorithm>
8187 #include <string_view>
8188 
8189 namespace ada::idna {
8190 
8191 enum direction : uint8_t {
8192   NONE,
8193   BN,
8194   CS,
8195   ES,
8196   ON,
8197   EN,
8198   L,
8199   R,
8200   NSM,
8201   AL,
8202   AN,
8203   ET,
8204   WS,
8205   RLO,
8206   LRO,
8207   PDF,
8208   RLE,
8209   RLI,
8210   FSI,
8211   PDI,
8212   LRI,
8213   B,
8214   S,
8215   LRE
8216 };
8217 
8218 struct directions {
8219   uint32_t start_code;
8220   uint32_t final_code;
8221   direction direct;
8222 };
8223 
8224 static directions dir_table[] = {
8225     {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8226     {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8227     {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8228     {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8229     {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8230     {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8231     {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8232     {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8233     {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8234     {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8235     {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8236     {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8237     {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8238     {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8239     {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8240     {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8241     {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8242     {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8243     {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8244     {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8245     {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8246     {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8247     {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8248     {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8249     {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8250     {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8251     {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8252     {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8253     {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8254     {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8255     {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8256     {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8257     {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8258     {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8259     {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8260     {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8261     {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8262     {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8263     {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8264     {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8265     {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8266     {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8267     {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8268     {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8269     {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8270     {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8271     {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8272     {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8273     {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8274     {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8275     {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8276     {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8277     {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8278     {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8279     {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8280     {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8281     {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8282     {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8283     {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8284     {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8285     {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8286     {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8287     {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8288     {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8289     {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8290     {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8291     {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8292     {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8293     {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8294     {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8295     {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8296     {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8297     {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8298     {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8299     {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8300     {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8301     {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8302     {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8303     {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8304     {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8305     {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8306     {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8307     {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8308     {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8309     {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8310     {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8311     {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8312     {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8313     {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8314     {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8315     {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8316     {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8317     {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8318     {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8319     {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8320     {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8321     {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8322     {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8323     {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8324     {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8325     {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8326     {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8327     {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8328     {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8329     {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8330     {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8331     {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8332     {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8333     {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8334     {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8335     {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8336     {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8337     {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8338     {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8339     {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8340     {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8341     {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8342     {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8343     {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8344     {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8345     {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8346     {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8347     {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8348     {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8349     {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8350     {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8351     {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8352     {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8353     {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8354     {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8355     {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8356     {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8357     {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8358     {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8359     {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8360     {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8361     {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8362     {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8363     {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8364     {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8365     {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8366     {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8367     {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8368     {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8369     {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8370     {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8371     {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8372     {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8373     {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8374     {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8375     {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8376     {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8377     {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8378     {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8379     {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8380     {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8381     {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8382     {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8383     {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8384     {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8385     {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8386     {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8387     {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8388     {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8389     {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8390     {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8391     {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8392     {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8393     {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8394     {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8395     {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8396     {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8397     {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8398     {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8399     {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8400     {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8401     {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8402     {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8403     {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8404     {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8405     {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8406     {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8407     {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8408     {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8409     {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8410     {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8411     {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8412     {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8413     {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8414     {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8415     {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8416     {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8417     {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8418     {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8419     {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8420     {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8421     {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8422     {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8423     {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8424     {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8425     {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8426     {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8427     {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8428     {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8429     {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8430     {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8431     {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8432     {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8433     {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8434     {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8435     {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8436     {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8437     {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8438     {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8439     {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8440     {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8441     {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8442     {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8443     {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8444     {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8445     {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8446     {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8447     {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8448     {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8449     {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8450     {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8451     {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8452     {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8453     {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8454     {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8455     {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8456     {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8457     {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8458     {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8459     {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8460     {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8461     {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8462     {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8463     {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8464     {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8465     {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8466     {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8467     {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8468     {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8469     {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8470     {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8471     {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8472     {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8473     {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8474     {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8475     {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8476     {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8477     {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8478     {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8479     {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8480     {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8481     {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8482     {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8483     {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8484     {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8485     {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8486     {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8487     {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8488     {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8489     {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8490     {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8491     {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8492     {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8493     {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8494     {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8495     {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8496     {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8497     {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8498     {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8499     {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8500     {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8501     {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8502     {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8503     {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8504     {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8505     {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8506     {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8507     {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8508     {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8509     {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8510     {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8511     {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8512     {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8513     {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8514     {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8515     {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8516     {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8517     {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8518     {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8519     {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8520     {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8521     {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8522     {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8523     {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8524     {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8525     {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8526     {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8527     {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8528     {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8529     {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8530     {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8531     {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8532     {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8533     {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8534     {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8535     {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8536     {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8537     {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8538     {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8539     {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8540     {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8541     {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8542     {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8543     {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8544     {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8545     {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8546     {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8547     {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8548     {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8549     {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8550     {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8551     {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8552     {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8553     {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8554     {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8555     {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8556     {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8557     {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8558     {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8559     {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8560     {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8561     {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8562     {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8563     {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8564     {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8565     {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8566     {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8567     {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8568     {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8569     {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8570     {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8571     {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8572     {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8573     {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8574     {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8575     {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8576     {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8577     {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8578     {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8579     {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8580     {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8581     {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8582     {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8583     {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8584     {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8585     {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8586     {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8587     {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8588     {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8589     {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8590     {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8591     {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8592     {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8593     {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8594     {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8595     {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8596     {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8597     {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8598     {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8599     {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8600     {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8601     {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8602     {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8603     {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8604     {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8605     {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8606     {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8607     {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8608     {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8609     {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8610     {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8611     {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8612     {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8613     {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8614     {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8615     {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8616     {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8617     {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8618     {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8619     {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8620     {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8621     {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8622     {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8623     {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8624     {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8625     {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8626     {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8627     {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8628     {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8629     {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8630     {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8631     {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8632     {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8633     {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8634     {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8635     {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8636     {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8637     {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8638     {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8639     {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8640     {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8641     {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8642     {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8643     {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8644     {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8645     {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8646     {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8647     {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8648     {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8649     {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8650     {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8651     {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8652     {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8653     {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8654     {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8655     {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8656     {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8657     {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8658     {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8659     {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8660     {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8661     {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8662     {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8663     {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8664     {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8665     {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8666     {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8667     {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8668     {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8669     {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8670     {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8671     {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8672     {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8673     {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8674     {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8675     {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8676     {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8677     {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8678     {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8679     {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8680     {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8681     {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8682     {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8683     {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8684     {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8685     {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8686     {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8687     {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8688     {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8689     {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8690     {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8691     {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8692     {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8693     {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8694     {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8695     {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8696     {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8697     {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8698     {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8699     {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8700     {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8701     {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8702     {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8703     {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8704     {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8705     {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8706     {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8707     {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8708     {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8709     {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8710     {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8711     {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8712     {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8713     {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8714     {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8715     {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8716     {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8717     {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8718     {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8719     {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8720     {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8721     {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8722     {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8723     {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8724     {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8725     {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8726     {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8727     {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8728     {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8729     {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8730     {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8731     {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8732     {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8733     {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8734     {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8735     {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8736     {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8737     {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8738     {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8739     {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8740     {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8741     {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8742     {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8743     {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8744     {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8745     {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8746     {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8747     {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8748     {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8749     {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8750     {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8751     {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8752     {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8753     {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8754     {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8755     {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8756     {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8757     {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8758     {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8759     {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8760     {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8761     {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8762     {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8763     {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8764     {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8765     {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8766     {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8767     {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8768     {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8769     {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8770     {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8771     {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8772     {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8773     {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8774     {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8775     {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8776     {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8777     {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8778     {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8779     {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8780     {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8781     {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8782     {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8783     {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8784     {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8785     {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8786     {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8787     {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8788     {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8789     {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8790     {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8791     {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8792     {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8793     {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8794     {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8795     {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8796     {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8797     {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8798     {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8799     {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8800     {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8801     {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8802     {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8803     {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8804     {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8805     {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8806     {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8807     {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8808     {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8809     {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8810     {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8811     {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8812     {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8813     {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8814     {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8815     {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8816     {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8817     {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8818     {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8819     {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8820     {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8821     {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8822     {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8823     {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8824     {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8825     {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8826     {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8827     {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8828     {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8829     {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8830     {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8831     {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8832     {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8833     {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8834     {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8835     {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8836     {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8837     {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8838     {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8839     {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8840     {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8841     {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8842     {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8843     {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8844     {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8845     {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8846     {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8847     {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8848     {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8849     {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8850     {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8851     {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8852     {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8853     {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8854     {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8855     {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8856     {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8857     {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8858     {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8859     {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8860     {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8861     {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8862     {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8863     {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8864     {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8865     {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8866     {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8867     {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8868     {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8869     {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8870     {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8871     {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8872     {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8873     {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8874     {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8875     {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8876     {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8877     {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8878     {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8879     {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8880     {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8881     {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8882     {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8883     {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8884     {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8885     {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8886     {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8887     {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8888     {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8889     {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8890     {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8891     {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8892     {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8893     {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8894     {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8895     {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8896     {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8897     {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8898     {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8899     {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8900     {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8901     {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8902     {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8903     {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8904     {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8905     {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8906     {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8907     {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8908     {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8909     {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8910     {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8911     {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8912     {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8913     {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8914     {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8915     {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8916     {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8917     {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8918     {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8919     {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8920     {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8921     {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8922     {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8923     {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8924     {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8925     {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8926     {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8927     {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8928     {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8929     {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8930     {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8931     {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8932     {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8933     {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8934     {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8935     {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8936     {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8937     {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8938     {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8939     {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8940     {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8941     {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8942     {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8943     {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8944     {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8945     {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8946     {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8947     {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8948     {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8949     {0x100000, 0x10fffd, direction::L}};
8950 
8951 // CheckJoiners and CheckBidi are true for URL specification.
8952 
find_direction(uint32_t code_point)8953 inline static direction find_direction(uint32_t code_point) noexcept {
8954   auto it = std::lower_bound(
8955       std::begin(dir_table), std::end(dir_table), code_point,
8956       [](const directions& d, uint32_t c) { return d.final_code < c; });
8957 
8958   // next check is almost surely in vain, but we use it for safety.
8959   if (it == std::end(dir_table)) {
8960     return direction::NONE;
8961   }
8962   // We have that d.final_code >= c.
8963   if (code_point >= it->start_code) {
8964     return it->direct;
8965   }
8966   return direction::NONE;
8967 }
8968 
find_last_not_of_nsm(const std::u32string_view label)8969 inline static size_t find_last_not_of_nsm(
8970     const std::u32string_view label) noexcept {
8971   for (int i = label.size() - 1; i >= 0; i--)
8972     if (find_direction(label[i]) != direction::NSM) return i;
8973 
8974   return std::u32string_view::npos;
8975 }
8976 
8977 // An RTL label is a label that contains at least one character of type R, AL,
8978 // or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
is_rtl_label(const std::u32string_view label)8979 inline static bool is_rtl_label(const std::u32string_view label) noexcept {
8980   const size_t mask =
8981       (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
8982 
8983   size_t directions = 0;
8984   for (size_t i = 0; i < label.size(); i++) {
8985     directions |= 1u << find_direction(label[i]);
8986   }
8987   return (directions & mask) != 0;
8988 }
8989 
is_label_valid(const std::u32string_view label)8990 bool is_label_valid(const std::u32string_view label) {
8991   if (label.empty()) {
8992     return true;
8993   }
8994 
8995   ///////////////
8996   // We have a normalization step which ensures that we are in NFC.
8997   // If we receive punycode, we normalize and check that the normalized
8998   // version matches the original.
8999   // --------------------------------------
9000   // The label must be in Unicode Normalization Form NFC.
9001 
9002   // Current URL standard indicatest that CheckHyphens is set to false.
9003   // ---------------------------------------
9004   // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9005   // in both the third and fourth positions. If CheckHyphens, the label must
9006   // neither begin nor end with a U+002D HYPHEN-MINUS character.
9007 
9008   // This is not necessary because we segment the
9009   // labels by '.'.
9010   // ---------------------------------------
9011   // The label must not contain a U+002E ( . ) FULL STOP.
9012   // if (label.find('.') != std::string_view::npos) return false;
9013 
9014   // The label must not begin with a combining mark, that is:
9015   // General_Category=Mark.
9016   constexpr static uint32_t combining[] = {
9017       0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9018       0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9019       0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9020       0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9021       0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9022       0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9023       0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9024       0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9025       0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9026       0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9027       0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9028       0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9029       0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9030       0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9031       0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9032       0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9033       0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9034       0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9035       0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9036       0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9037       0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9038       0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9039       0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9040       0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9041       0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9042       0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9043       0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9044       0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9045       0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9046       0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9047       0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9048       0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9049       0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9050       0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9051       0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9052       0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9053       0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9054       0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9055       0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9056       0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9057       0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9058       0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9059       0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9060       0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9061       0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9062       0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9063       0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9064       0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9065       0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9066       0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9067       0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9068       0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9069       0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9070       0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9071       0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9072       0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9073       0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9074       0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9075       0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9076       0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9077       0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9078       0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9079       0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9080       0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9081       0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9082       0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9083       0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9084       0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9085       0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9086       0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9087       0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9088       0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9089       0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9090       0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9091       0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9092       0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9093       0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9094       0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9095       0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9096       0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9097       0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9098       0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9099       0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9100       0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9101       0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9102       0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9103       0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9104       0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9105       0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9106       0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9107       0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9108       0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9109       0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9110       0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9111       0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9112       0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9113       0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9114       0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9115       0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9116       0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9117       0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9118       0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9119       0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9120       0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9121       0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9122       0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9123       0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9124       0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9125       0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9126       0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9127       0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9128       0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9129       0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9130       0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9131       0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9132       0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9133       0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9134       0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9135       0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9136       0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9137       0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9138       0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9139       0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9140       0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9141       0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9142       0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9143       0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9144       0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9145       0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9146       0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9147       0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9148       0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9149       0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9150       0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9151       0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9152       0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9153       0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9154       0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9155       0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9156       0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9157       0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9158       0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9159       0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9160       0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9161       0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9162       0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9163       0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9164       0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9165       0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9166       0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9167       0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9168       0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9169       0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9170       0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9171       0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9172       0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9173       0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9174       0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9175       0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9176       0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9177       0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9178       0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9179       0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9180       0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9181       0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9182       0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9183       0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9184       0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9185       0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9186       0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9187       0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9188       0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9189       0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9190       0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9191       0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9192       0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9193       0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9194       0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9195       0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9196       0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9197       0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9198       0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9199       0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9200       0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9201       0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9202       0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9203       0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9204       0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9205       0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9206       0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9207       0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9208       0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9209       0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9210       0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9211       0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9212       0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9213       0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9214       0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9215       0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9216       0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9217       0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9218       0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9219       0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9220       0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9221       0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9222       0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9223       0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9224       0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9225       0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9226       0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9227       0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9228       0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9229       0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9230       0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9231       0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9232       0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9233       0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9234       0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9235       0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9236       0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9237       0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9238       0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9239       0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9240       0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9241       0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9242       0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9243       0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9244       0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9245       0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9246       0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9247       0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9248       0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9249       0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9250       0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9251       0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9252       0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9253       0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9254       0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9255       0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9256       0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9257       0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9258       0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9259       0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9260       0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9261       0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9262       0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9263       0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9264       0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9265       0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9266       0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9267       0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9268       0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9269       0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9270       0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9271       0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9272       0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9273       0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9274       0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9275       0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9276       0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9277       0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9278       0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9279       0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9280       0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9281       0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9282       0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9283       0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9284       0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9285       0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9286       0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9287       0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9288       0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9289       0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9290       0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9291       0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9292       0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9293       0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9294       0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9295       0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9296       0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9297       0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9298       0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9299       0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9300       0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9301       0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9302       0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9303       0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9304   if (std::binary_search(std::begin(combining), std::end(combining),
9305                          label.front())) {
9306     return false;
9307   }
9308   // We verify this next step as part of the mapping:
9309   // ---------------------------------------------
9310   // Each code point in the label must only have certain status values
9311   // according to Section 5, IDNA Mapping Table:
9312   // - For Transitional Processing, each value must be valid.
9313   // - For Nontransitional Processing, each value must be either valid or
9314   // deviation.
9315 
9316   // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9317   // A, in The Unicode Code Points and Internationalized Domain Names for
9318   // Applications (IDNA) [IDNA2008].
9319   constexpr static uint32_t virama[] = {
9320       0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9321       0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9322       0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9323       0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9324       0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9325       0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9326       0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9327       0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9328   constexpr static uint32_t R[] = {
9329       0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9330       0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9331       0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9332       0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9333       0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9334       0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9335       0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9336       0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9337   constexpr static uint32_t L[] = {0xa872};
9338   constexpr static uint32_t D[] = {
9339       0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9340       0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9341       0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9342       0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9343       0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9344       0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9345       0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9346       0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9347       0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9348       0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9349       0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9350       0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9351       0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9352       0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9353       0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9354       0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9355       0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9356       0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9357       0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9358       0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9359       0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9360       0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9361       0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9362       0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9363       0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9364       0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9365       0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9366       0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9367       0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9368       0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9369       0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9370       0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9371       0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9372       0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9373       0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9374       0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9375       0xa870, 0xa871};
9376 
9377   for (size_t i = 0; i < label.size(); i++) {
9378     uint32_t c = label[i];
9379     if (c == 0x200c) {
9380       if (i > 0) {
9381         if (std::binary_search(std::begin(virama), std::end(virama),
9382                                label[i - 1])) {
9383           return true;
9384         }
9385       }
9386       if ((i == 0) || (i + 1 >= label.size())) {
9387         return false;
9388       }
9389       // we go backward looking for L or D
9390       auto is_l_or_d = [](uint32_t code) {
9391         return std::binary_search(std::begin(L), std::end(L), code) ||
9392                std::binary_search(std::begin(D), std::end(D), code);
9393       };
9394       auto is_r_or_d = [](uint32_t code) {
9395         return std::binary_search(std::begin(R), std::end(R), code) ||
9396                std::binary_search(std::begin(D), std::end(D), code);
9397       };
9398       std::u32string_view before = label.substr(0, i);
9399       std::u32string_view after = label.substr(i + 1);
9400       return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9401               before.end()) &&
9402              (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9403               after.end());
9404     } else if (c == 0x200d) {
9405       if (i > 0) {
9406         if (std::binary_search(std::begin(virama), std::end(virama),
9407                                label[i - 1])) {
9408           return true;
9409         }
9410       }
9411       return false;
9412     }
9413   }
9414 
9415   // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9416   // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9417   // Section 2.
9418 
9419   // The following rule, consisting of six conditions, applies to labels
9420   // in Bidi domain names.  The requirements that this rule satisfies are
9421   // described in Section 3.  All of the conditions must be satisfied for
9422   // the rule to be satisfied.
9423   //
9424   //  1.  The first character must be a character with Bidi property L, R,
9425   //     or AL.  If it has the R or AL property, it is an RTL label; if it
9426   //     has the L property, it is an LTR label.
9427   //
9428   //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9429   //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9430   //
9431   //   3.  In an RTL label, the end of the label must be a character with
9432   //       Bidi property R, AL, EN, or AN, followed by zero or more
9433   //       characters with Bidi property NSM.
9434   //
9435   //   4.  In an RTL label, if an EN is present, no AN may be present, and
9436   //       vice versa.
9437   //
9438   //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9439   //       ES, CS, ET, ON, BN, or NSM are allowed.
9440   //
9441   //   6.  In an LTR label, the end of the label must be a character with
9442   //       Bidi property L or EN, followed by zero or more characters with
9443   //       Bidi property NSM.
9444 
9445   size_t last_non_nsm_char = find_last_not_of_nsm(label);
9446   if (last_non_nsm_char == std::u32string_view::npos) {
9447     return false;
9448   }
9449 
9450   // A "Bidi domain name" is a domain name that contains at least one RTL label.
9451   // The following rule, consisting of six conditions, applies to labels in Bidi
9452   // domain names.
9453   if (is_rtl_label(label)) {
9454     // The first character must be a character with Bidi property L, R,
9455     // or AL. If it has the R or AL property, it is an RTL label; if it
9456     // has the L property, it is an LTR label.
9457 
9458     if (find_direction(label[0]) == direction::L) {
9459       // Eval as LTR
9460 
9461       // In an LTR label, only characters with the Bidi properties L, EN,
9462       // ES, CS, ET, ON, BN, or NSM are allowed.
9463       for (size_t i = 0; i < last_non_nsm_char; i++) {
9464         const direction d = find_direction(label[i]);
9465         if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9466               d == direction::CS || d == direction::ET || d == direction::ON ||
9467               d == direction::BN || d == direction::NSM)) {
9468           return false;
9469         }
9470 
9471         if ((i == last_non_nsm_char) &&
9472             !(d == direction::L || d == direction::EN)) {
9473           return false;
9474         }
9475       }
9476 
9477       return true;
9478 
9479     } else {
9480       // Eval as RTL
9481 
9482       bool has_an = false;
9483       bool has_en = false;
9484       for (size_t i = 0; i <= last_non_nsm_char; i++) {
9485         const direction d = find_direction(label[i]);
9486 
9487         // In an RTL label, if an EN is present, no AN may be present, and vice
9488         // versa.
9489         if ((d == direction::EN && ((has_en = true) && has_an)) ||
9490             (d == direction::AN && ((has_an = true) && has_en))) {
9491           return false;
9492         }
9493 
9494         if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9495               d == direction::EN || d == direction::ES || d == direction::CS ||
9496               d == direction::ET || d == direction::ON || d == direction::BN ||
9497               d == direction::NSM)) {
9498           return false;
9499         }
9500 
9501         if (i == last_non_nsm_char &&
9502             !(d == direction::R || d == direction::AL || d == direction::AN ||
9503               d == direction::EN)) {
9504           return false;
9505         }
9506       }
9507 
9508       return true;
9509     }
9510   }
9511 
9512   return true;
9513 }
9514 
9515 }  // namespace ada::idna
9516 /* end file src/validity.cpp */
9517 /* begin file src/to_ascii.cpp */
9518 
9519 #include <algorithm>
9520 #include <cstdint>
9521 
9522 
9523 namespace ada::idna {
9524 
begins_with(std::u32string_view view,std::u32string_view prefix)9525 bool begins_with(std::u32string_view view, std::u32string_view prefix) {
9526   if (view.size() < prefix.size()) {
9527     return false;
9528   }
9529   // constexpr as of C++20
9530   return std::equal(prefix.begin(), prefix.end(), view.begin());
9531 }
9532 
begins_with(std::string_view view,std::string_view prefix)9533 bool begins_with(std::string_view view, std::string_view prefix) {
9534   if (view.size() < prefix.size()) {
9535     return false;
9536   }
9537   // constexpr as of C++20
9538   return std::equal(prefix.begin(), prefix.end(), view.begin());
9539 }
9540 
is_ascii(std::u32string_view view)9541 bool constexpr is_ascii(std::u32string_view view) {
9542   for (uint32_t c : view) {
9543     if (c >= 0x80) {
9544       return false;
9545     }
9546   }
9547   return true;
9548 }
9549 
is_ascii(std::string_view view)9550 bool constexpr is_ascii(std::string_view view) {
9551   for (uint8_t c : view) {
9552     if (c >= 0x80) {
9553       return false;
9554     }
9555   }
9556   return true;
9557 }
9558 
9559 constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9560     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9561     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9562     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9563     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9564     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9565     0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9566     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9567     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9568     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9569     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9570     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9571 
9572 static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9573 
is_forbidden_domain_code_point(const char c)9574 inline bool is_forbidden_domain_code_point(const char c) noexcept {
9575   return is_forbidden_domain_code_point_table[uint8_t(c)];
9576 }
9577 
contains_forbidden_domain_code_point(std::string_view view)9578 bool contains_forbidden_domain_code_point(std::string_view view) {
9579   return (
9580       std::any_of(view.begin(), view.end(), is_forbidden_domain_code_point));
9581 }
9582 
9583 // We return "" on error.
from_ascii_to_ascii(std::string_view ut8_string)9584 static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9585   static const std::string error = "";
9586   // copy and map
9587   // we could be more efficient by avoiding the copy when unnecessary.
9588   std::string mapped_string = std::string(ut8_string);
9589   ascii_map(mapped_string.data(), mapped_string.size());
9590   std::string out;
9591   size_t label_start = 0;
9592 
9593   while (label_start != mapped_string.size()) {
9594     size_t loc_dot = mapped_string.find('.', label_start);
9595     bool is_last_label = (loc_dot == std::string_view::npos);
9596     size_t label_size = is_last_label ? mapped_string.size() - label_start
9597                                       : loc_dot - label_start;
9598     size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9599     std::string_view label_view(mapped_string.data() + label_start, label_size);
9600     label_start += label_size_with_dot;
9601     if (label_size == 0) {
9602       // empty label? Nothing to do.
9603     } else if (begins_with(label_view, "xn--")) {
9604       // The xn-- part is the expensive game.
9605       out.append(label_view);
9606       std::string_view puny_segment_ascii(
9607           out.data() + out.size() - label_view.size() + 4,
9608           label_view.size() - 4);
9609       std::u32string tmp_buffer;
9610       bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9611       if (!is_ok) {
9612         return error;
9613       }
9614       std::u32string post_map = ada::idna::map(tmp_buffer);
9615       if (tmp_buffer != post_map) {
9616         return error;
9617       }
9618       std::u32string pre_normal = post_map;
9619       normalize(post_map);
9620       if (post_map != pre_normal) {
9621         return error;
9622       }
9623       if (post_map.empty()) {
9624         return error;
9625       }
9626       if (!is_label_valid(post_map)) {
9627         return error;
9628       }
9629     } else {
9630       out.append(label_view);
9631     }
9632     if (!is_last_label) {
9633       out.push_back('.');
9634     }
9635   }
9636   return out;
9637 }
9638 
9639 // We return "" on error.
to_ascii(std::string_view ut8_string)9640 std::string to_ascii(std::string_view ut8_string) {
9641   if (is_ascii(ut8_string)) {
9642     return from_ascii_to_ascii(ut8_string);
9643   }
9644   static const std::string error = "";
9645   // We convert to UTF-32
9646   size_t utf32_length =
9647       ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9648   std::u32string utf32(utf32_length, '\0');
9649   size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9650       ut8_string.data(), ut8_string.size(), utf32.data());
9651   if (actual_utf32_length == 0) {
9652     return error;
9653   }
9654   // mapping
9655   utf32 = ada::idna::map(utf32);
9656   normalize(utf32);
9657   std::string out;
9658   size_t label_start = 0;
9659 
9660   while (label_start != utf32.size()) {
9661     size_t loc_dot = utf32.find('.', label_start);
9662     bool is_last_label = (loc_dot == std::string_view::npos);
9663     size_t label_size =
9664         is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9665     size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9666     std::u32string_view label_view(utf32.data() + label_start, label_size);
9667     label_start += label_size_with_dot;
9668     if (label_size == 0) {
9669       // empty label? Nothing to do.
9670     } else if (begins_with(label_view, U"xn--")) {
9671       // we do not need to check, e.g., Xn-- because mapping goes to lower case
9672       for (char32_t c : label_view) {
9673         if (c >= 0x80) {
9674           return error;
9675         }
9676         out += (unsigned char)(c);
9677       }
9678       std::string_view puny_segment_ascii(
9679           out.data() + out.size() - label_view.size() + 4,
9680           label_view.size() - 4);
9681       std::u32string tmp_buffer;
9682       bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9683       if (!is_ok) {
9684         return error;
9685       }
9686       std::u32string post_map = ada::idna::map(tmp_buffer);
9687       if (tmp_buffer != post_map) {
9688         return error;
9689       }
9690       std::u32string pre_normal = post_map;
9691       normalize(post_map);
9692       if (post_map != pre_normal) {
9693         return error;
9694       }
9695       if (post_map.empty()) {
9696         return error;
9697       }
9698       if (!is_label_valid(post_map)) {
9699         return error;
9700       }
9701     } else {
9702       // The fast path here is an ascii label.
9703       if (is_ascii(label_view)) {
9704         // no validation needed.
9705         for (char32_t c : label_view) {
9706           out += (unsigned char)(c);
9707         }
9708       } else {
9709         // slow path.
9710         // first check validity.
9711         if (!is_label_valid(label_view)) {
9712           return error;
9713         }
9714         // It is valid! So now we must encode it as punycode...
9715         out.append("xn--");
9716         bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9717         if (!is_ok) {
9718           return error;
9719         }
9720       }
9721     }
9722     if (!is_last_label) {
9723       out.push_back('.');
9724     }
9725   }
9726   return out;
9727 }
9728 }  // namespace ada::idna
9729 /* end file src/to_ascii.cpp */
9730 /* begin file src/to_unicode.cpp */
9731 
9732 #include <algorithm>
9733 #include <string>
9734 
9735 
9736 namespace ada::idna {
to_unicode(std::string_view input)9737 std::string to_unicode(std::string_view input) {
9738   std::string output;
9739   output.reserve(input.size());
9740 
9741   size_t label_start = 0;
9742   while (label_start < input.size()) {
9743     size_t loc_dot = input.find('.', label_start);
9744     bool is_last_label = (loc_dot == std::string_view::npos);
9745     size_t label_size =
9746         is_last_label ? input.size() - label_start : loc_dot - label_start;
9747     auto label_view = std::string_view(input.data() + label_start, label_size);
9748 
9749     if (ada::idna::begins_with(label_view, "xn--") &&
9750         ada::idna::is_ascii(label_view)) {
9751       label_view.remove_prefix(4);
9752       if (ada::idna::verify_punycode(label_view)) {
9753         std::u32string tmp_buffer;
9754         if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9755           auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9756                                                              tmp_buffer.size());
9757           std::string final_utf8(utf8_size, '\0');
9758           ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9759                                    final_utf8.data());
9760           output.append(final_utf8);
9761         } else {
9762           // ToUnicode never fails.  If any step fails, then the original input
9763           // sequence is returned immediately in that step.
9764           output.append(
9765               std::string_view(input.data() + label_start, label_size));
9766         }
9767       } else {
9768         output.append(std::string_view(input.data() + label_start, label_size));
9769       }
9770     } else {
9771       output.append(label_view);
9772     }
9773 
9774     if (!is_last_label) {
9775       output.push_back('.');
9776     }
9777 
9778     label_start += label_size + 1;
9779   }
9780 
9781   return output;
9782 }
9783 }  // namespace ada::idna
9784 /* end file src/to_unicode.cpp */
9785 /* end file src/idna.cpp */
9786 /* end file src/ada_idna.cpp */
9787 ADA_POP_DISABLE_WARNINGS
9788 
9789 #include <algorithm>
9790 #if ADA_NEON
9791 #include <arm_neon.h>
9792 #elif ADA_SSE2
9793 #include <emmintrin.h>
9794 #endif
9795 
9796 namespace ada::unicode {
9797 
broadcast(uint8_t v)9798 constexpr uint64_t broadcast(uint8_t v) noexcept {
9799   return 0x101010101010101ull * v;
9800 }
9801 
to_lower_ascii(char * input,size_t length)9802 constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
9803   uint64_t broadcast_80 = broadcast(0x80);
9804   uint64_t broadcast_Ap = broadcast(128 - 'A');
9805   uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
9806   uint64_t non_ascii = 0;
9807   size_t i = 0;
9808 
9809   for (; i + 7 < length; i += 8) {
9810     uint64_t word{};
9811     memcpy(&word, input + i, sizeof(word));
9812     non_ascii |= (word & broadcast_80);
9813     word ^=
9814         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9815     memcpy(input + i, &word, sizeof(word));
9816   }
9817   if (i < length) {
9818     uint64_t word{};
9819     memcpy(&word, input + i, length - i);
9820     non_ascii |= (word & broadcast_80);
9821     word ^=
9822         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9823     memcpy(input + i, &word, length - i);
9824   }
9825   return non_ascii == 0;
9826 }
9827 #if ADA_NEON
has_tabs_or_newline(std::string_view user_input)9828 ada_really_inline bool has_tabs_or_newline(
9829     std::string_view user_input) noexcept {
9830   // first check for short strings in which case we do it naively.
9831   if (user_input.size() < 16) {  // slow path
9832     for (size_t i = 0; i < user_input.size(); i++) {
9833       if (user_input[i] == '\r' || user_input[i] == '\n' ||
9834           user_input[i] == '\t') {
9835         return true;
9836       }
9837     }
9838     return false;
9839   }
9840   // fast path for long strings (expected to be common)
9841   size_t i = 0;
9842   const uint8x16_t mask1 = vmovq_n_u8('\r');
9843   const uint8x16_t mask2 = vmovq_n_u8('\n');
9844   const uint8x16_t mask3 = vmovq_n_u8('\t');
9845   uint8x16_t running{0};
9846   for (; i + 15 < user_input.size(); i += 16) {
9847     uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
9848     running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9849                                                   vceqq_u8(word, mask2))),
9850                        vceqq_u8(word, mask3));
9851   }
9852   if (i < user_input.size()) {
9853     uint8x16_t word =
9854         vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
9855     running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9856                                                   vceqq_u8(word, mask2))),
9857                        vceqq_u8(word, mask3));
9858   }
9859   return vmaxvq_u8(running) != 0;
9860 }
9861 #elif ADA_SSE2
has_tabs_or_newline(std::string_view user_input)9862 ada_really_inline bool has_tabs_or_newline(
9863     std::string_view user_input) noexcept {
9864   // first check for short strings in which case we do it naively.
9865   if (user_input.size() < 16) {  // slow path
9866     for (size_t i = 0; i < user_input.size(); i++) {
9867       if (user_input[i] == '\r' || user_input[i] == '\n' ||
9868           user_input[i] == '\t') {
9869         return true;
9870       }
9871     }
9872     return false;
9873   }
9874   // fast path for long strings (expected to be common)
9875   size_t i = 0;
9876   const __m128i mask1 = _mm_set1_epi8('\r');
9877   const __m128i mask2 = _mm_set1_epi8('\n');
9878   const __m128i mask3 = _mm_set1_epi8('\t');
9879   __m128i running{0};
9880   for (; i + 15 < user_input.size(); i += 16) {
9881     __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
9882     running = _mm_or_si128(
9883         _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9884                                            _mm_cmpeq_epi8(word, mask2))),
9885         _mm_cmpeq_epi8(word, mask3));
9886   }
9887   if (i < user_input.size()) {
9888     __m128i word = _mm_loadu_si128(
9889         (const __m128i*)(user_input.data() + user_input.length() - 16));
9890     running = _mm_or_si128(
9891         _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9892                                            _mm_cmpeq_epi8(word, mask2))),
9893         _mm_cmpeq_epi8(word, mask3));
9894   }
9895   return _mm_movemask_epi8(running) != 0;
9896 }
9897 #else
has_tabs_or_newline(std::string_view user_input)9898 ada_really_inline bool has_tabs_or_newline(
9899     std::string_view user_input) noexcept {
9900   auto has_zero_byte = [](uint64_t v) {
9901     return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
9902   };
9903   size_t i = 0;
9904   uint64_t mask1 = broadcast('\r');
9905   uint64_t mask2 = broadcast('\n');
9906   uint64_t mask3 = broadcast('\t');
9907   uint64_t running{0};
9908   for (; i + 7 < user_input.size(); i += 8) {
9909     uint64_t word{};
9910     memcpy(&word, user_input.data() + i, sizeof(word));
9911     uint64_t xor1 = word ^ mask1;
9912     uint64_t xor2 = word ^ mask2;
9913     uint64_t xor3 = word ^ mask3;
9914     running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9915   }
9916   if (i < user_input.size()) {
9917     uint64_t word{};
9918     memcpy(&word, user_input.data() + i, user_input.size() - i);
9919     uint64_t xor1 = word ^ mask1;
9920     uint64_t xor2 = word ^ mask2;
9921     uint64_t xor3 = word ^ mask3;
9922     running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9923   }
9924   return running;
9925 }
9926 #endif
9927 
9928 // A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
9929 // U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
9930 // U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
9931 // U+007C (|).
9932 constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
__anon4ddc785e0902() 9933     []() constexpr {
9934       std::array<uint8_t, 256> result{};
9935       for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
9936                         '>', '?', '@', '[', '\\', ']', '^', '|'}) {
9937         result[c] = true;
9938       }
9939       return result;
9940     }();
9941 
is_forbidden_host_code_point(const char c)9942 ada_really_inline constexpr bool is_forbidden_host_code_point(
9943     const char c) noexcept {
9944   return is_forbidden_host_code_point_table[uint8_t(c)];
9945 }
9946 
9947 constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
__anon4ddc785e0a02() 9948     []() constexpr {
9949       std::array<uint8_t, 256> result{};
9950       for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
9951                         '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
9952         result[c] = true;
9953       }
9954       for (uint8_t c = 0; c <= 32; c++) {
9955         result[c] = true;
9956       }
9957       for (size_t c = 127; c < 255; c++) {
9958         result[c] = true;
9959       }
9960       return result;
9961     }();
9962 
9963 static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9964 
is_forbidden_domain_code_point(const char c)9965 ada_really_inline constexpr bool is_forbidden_domain_code_point(
9966     const char c) noexcept {
9967   return is_forbidden_domain_code_point_table[uint8_t(c)];
9968 }
9969 
contains_forbidden_domain_code_point(const char * input,size_t length)9970 ada_really_inline constexpr bool contains_forbidden_domain_code_point(
9971     const char* input, size_t length) noexcept {
9972   size_t i = 0;
9973   uint8_t accumulator{};
9974   for (; i + 4 <= length; i += 4) {
9975     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9976     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
9977     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
9978     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
9979   }
9980   for (; i < length; i++) {
9981     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9982   }
9983   return accumulator;
9984 }
9985 
9986 constexpr static std::array<uint8_t, 256>
__anon4ddc785e0b02() 9987     is_forbidden_domain_code_point_table_or_upper = []() constexpr {
9988       std::array<uint8_t, 256> result{};
9989       for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
9990                         '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
9991         result[c] = 1;
9992       }
9993       for (uint8_t c = 'A'; c <= 'Z'; c++) {
9994         result[c] = 2;
9995       }
9996       for (uint8_t c = 0; c <= 32; c++) {
9997         result[c] = 1;
9998       }
9999       for (size_t c = 127; c < 255; c++) {
10000         result[c] = 1;
10001       }
10002       return result;
10003     }();
10004 
10005 ada_really_inline constexpr uint8_t
contains_forbidden_domain_code_point_or_upper(const char * input,size_t length)10006 contains_forbidden_domain_code_point_or_upper(const char* input,
10007                                               size_t length) noexcept {
10008   size_t i = 0;
10009   uint8_t accumulator{};
10010   for (; i + 4 <= length; i += 4) {
10011     accumulator |=
10012         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10013     accumulator |=
10014         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10015     accumulator |=
10016         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10017     accumulator |=
10018         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10019   }
10020   for (; i < length; i++) {
10021     accumulator |=
10022         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10023   }
10024   return accumulator;
10025 }
10026 
10027 // std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
__anon4ddc785e0c02() 10028 constexpr static std::array<bool, 256> is_alnum_plus_table = []() constexpr {
10029   std::array<bool, 256> result{};
10030   for (size_t c = 0; c < 256; c++) {
10031     if (c >= '0' && c <= '9') {
10032       result[c] = true;
10033     } else if (c >= 'a' && c <= 'z') {
10034       result[c] = true;
10035     } else if (c >= 'A' && c <= 'Z') {
10036       result[c] = true;
10037     } else if (c == '+' || c == '-' || c == '.') {
10038       result[c] = true;
10039     }
10040   }
10041   return result;
10042 }();
10043 
is_alnum_plus(const char c)10044 ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10045   return is_alnum_plus_table[uint8_t(c)];
10046   // A table is almost surely much faster than the
10047   // following under most compilers: return
10048   // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10049 }
10050 
is_ascii_hex_digit(const char c)10051 ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10052   return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10053          (c >= 'a' && c <= 'f');
10054 }
10055 
is_c0_control_or_space(const char c)10056 ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10057   return (unsigned char)c <= ' ';
10058 }
10059 
is_ascii_tab_or_newline(const char c)10060 ada_really_inline constexpr bool is_ascii_tab_or_newline(
10061     const char c) noexcept {
10062   return c == '\t' || c == '\n' || c == '\r';
10063 }
10064 
10065 constexpr std::string_view table_is_double_dot_path_segment[] = {
10066     "..", "%2e.", ".%2e", "%2e%2e"};
10067 
is_double_dot_path_segment(std::string_view input)10068 ada_really_inline ada_constexpr bool is_double_dot_path_segment(
10069     std::string_view input) noexcept {
10070   // This will catch most cases:
10071   // The length must be 2,4 or 6.
10072   // We divide by two and require
10073   // that the result be between 1 and 3 inclusively.
10074   uint64_t half_length = uint64_t(input.size()) / 2;
10075   if (half_length - 1 > 2) {
10076     return false;
10077   }
10078   // We have a string of length 2, 4 or 6.
10079   // We now check the first character:
10080   if ((input[0] != '.') && (input[0] != '%')) {
10081     return false;
10082   }
10083   // We are unlikely the get beyond this point.
10084   int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10085   const std::string_view target = table_is_double_dot_path_segment[hash_value];
10086   if (target.size() != input.size()) {
10087     return false;
10088   }
10089   // We almost never get here.
10090   // Optimizing the rest is relatively unimportant.
10091   auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10092     uint16_t A, B;
10093     memcpy(&A, a.data(), sizeof(A));
10094     memcpy(&B, b.data(), sizeof(B));
10095     return A == B;
10096   };
10097   if (!prefix_equal_unsafe(input, target)) {
10098     return false;
10099   }
10100   for (size_t i = 2; i < input.size(); i++) {
10101     char c = input[i];
10102     if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10103       return false;
10104     }
10105   }
10106   return true;
10107   // The above code might be a bit better than the code below. Compilers
10108   // are not stupid and may use the fact that these strings have length 2,4 and
10109   // 6 and other tricks.
10110   // return input == ".." ||
10111   //  input == ".%2e" || input == ".%2E" ||
10112   //  input == "%2e." || input == "%2E." ||
10113   //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10114   //  "%2e%2E";
10115 }
10116 
is_single_dot_path_segment(std::string_view input)10117 ada_really_inline constexpr bool is_single_dot_path_segment(
10118     std::string_view input) noexcept {
10119   return input == "." || input == "%2e" || input == "%2E";
10120 }
10121 
is_lowercase_hex(const char c)10122 ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10123   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10124 }
10125 
10126 constexpr static char hex_to_binary_table[] = {
10127     0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10128     12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10129     0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
convert_hex_to_binary(const char c)10130 unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10131   return hex_to_binary_table[c - '0'];
10132 }
10133 
percent_decode(const std::string_view input,size_t first_percent)10134 std::string percent_decode(const std::string_view input, size_t first_percent) {
10135   // next line is for safety only, we expect users to avoid calling
10136   // percent_decode when first_percent is outside the range.
10137   if (first_percent == std::string_view::npos) {
10138     return std::string(input);
10139   }
10140   std::string dest;
10141   dest.reserve(input.length());
10142   dest.append(input.substr(0, first_percent));
10143   const char* pointer = input.data() + first_percent;
10144   const char* end = input.data() + input.size();
10145   // Optimization opportunity: if the following code gets
10146   // called often, it can be optimized quite a bit.
10147   while (pointer < end) {
10148     const char ch = pointer[0];
10149     size_t remaining = end - pointer - 1;
10150     if (ch != '%' || remaining < 2 ||
10151         (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10152             (!is_ascii_hex_digit(pointer[1]) ||
10153              !is_ascii_hex_digit(pointer[2])))) {
10154       dest += ch;
10155       pointer++;
10156       continue;
10157     } else {
10158       unsigned a = convert_hex_to_binary(pointer[1]);
10159       unsigned b = convert_hex_to_binary(pointer[2]);
10160       char c = static_cast<char>(a * 16 + b);
10161       dest += c;
10162       pointer += 3;
10163     }
10164   }
10165   return dest;
10166 }
10167 
percent_encode(const std::string_view input,const uint8_t character_set[])10168 std::string percent_encode(const std::string_view input,
10169                            const uint8_t character_set[]) {
10170   auto pointer =
10171       std::find_if(input.begin(), input.end(), [character_set](const char c) {
10172         return character_sets::bit_at(character_set, c);
10173       });
10174   // Optimization: Don't iterate if percent encode is not required
10175   if (pointer == input.end()) {
10176     return std::string(input);
10177   }
10178 
10179   std::string result;
10180   result.reserve(input.length());  // in the worst case, percent encoding might
10181                                    // produce 3 characters.
10182   result.append(input.substr(0, std::distance(input.begin(), pointer)));
10183 
10184   for (; pointer != input.end(); pointer++) {
10185     if (character_sets::bit_at(character_set, *pointer)) {
10186       result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10187     } else {
10188       result += *pointer;
10189     }
10190   }
10191 
10192   return result;
10193 }
10194 
10195 template <bool append>
percent_encode(const std::string_view input,const uint8_t character_set[],std::string & out)10196 bool percent_encode(const std::string_view input, const uint8_t character_set[],
10197                     std::string& out) {
10198   ada_log("percent_encode ", input, " to output string while ",
10199           append ? "appending" : "overwriting");
10200   auto pointer =
10201       std::find_if(input.begin(), input.end(), [character_set](const char c) {
10202         return character_sets::bit_at(character_set, c);
10203       });
10204   ada_log("percent_encode done checking, moved to ",
10205           std::distance(input.begin(), pointer));
10206 
10207   // Optimization: Don't iterate if percent encode is not required
10208   if (pointer == input.end()) {
10209     ada_log("percent_encode encoding not needed.");
10210     return false;
10211   }
10212   if (!append) {
10213     out.clear();
10214   }
10215   ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10216           " bytes");
10217   out.append(input.data(), std::distance(input.begin(), pointer));
10218   ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10219           " bytes");
10220   for (; pointer != input.end(); pointer++) {
10221     if (character_sets::bit_at(character_set, *pointer)) {
10222       out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10223     } else {
10224       out += *pointer;
10225     }
10226   }
10227   return true;
10228 }
10229 
to_ascii(std::optional<std::string> & out,const std::string_view plain,size_t first_percent)10230 bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10231               size_t first_percent) {
10232   std::string percent_decoded_buffer;
10233   std::string_view input = plain;
10234   if (first_percent != std::string_view::npos) {
10235     percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10236     input = percent_decoded_buffer;
10237   }
10238   // input is a non-empty UTF-8 string, must be percent decoded
10239   std::string idna_ascii = ada::idna::to_ascii(input);
10240   if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10241                                 idna_ascii.data(), idna_ascii.size())) {
10242     return false;
10243   }
10244   out = std::move(idna_ascii);
10245   return true;
10246 }
10247 
percent_encode(const std::string_view input,const uint8_t character_set[],size_t index)10248 std::string percent_encode(const std::string_view input,
10249                            const uint8_t character_set[], size_t index) {
10250   std::string out;
10251   out.append(input.data(), index);
10252   auto pointer = input.begin() + index;
10253   for (; pointer != input.end(); pointer++) {
10254     if (character_sets::bit_at(character_set, *pointer)) {
10255       out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10256     } else {
10257       out += *pointer;
10258     }
10259   }
10260   return out;
10261 }
10262 
to_unicode(std::string_view input)10263 std::string to_unicode(std::string_view input) {
10264   return ada::idna::to_unicode(input);
10265 }
10266 
10267 }  // namespace ada::unicode
10268 /* end file src/unicode.cpp */
10269 /* begin file src/serializers.cpp */
10270 
10271 #include <array>
10272 #include <string>
10273 
10274 namespace ada::serializers {
10275 
find_longest_sequence_of_ipv6_pieces(const std::array<uint16_t,8> & address,size_t & compress,size_t & compress_length)10276 void find_longest_sequence_of_ipv6_pieces(
10277     const std::array<uint16_t, 8>& address, size_t& compress,
10278     size_t& compress_length) noexcept {
10279   for (size_t i = 0; i < 8; i++) {
10280     if (address[i] == 0) {
10281       size_t next = i + 1;
10282       while (next != 8 && address[next] == 0) ++next;
10283       const size_t count = next - i;
10284       if (compress_length < count) {
10285         compress_length = count;
10286         compress = i;
10287         if (next == 8) break;
10288         i = next;
10289       }
10290     }
10291   }
10292 }
10293 
ipv6(const std::array<uint16_t,8> & address)10294 std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
10295   size_t compress_length = 0;  // The length of a long sequence of zeros.
10296   size_t compress = 0;         // The start of a long sequence of zeros.
10297   find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
10298 
10299   if (compress_length <= 1) {
10300     // Optimization opportunity: Find a faster way then snprintf for imploding
10301     // and return here.
10302     compress = compress_length = 8;
10303   }
10304 
10305   std::string output(4 * 8 + 7 + 2, '\0');
10306   size_t piece_index = 0;
10307   char* point = output.data();
10308   char* point_end = output.data() + output.size();
10309   *point++ = '[';
10310   while (true) {
10311     if (piece_index == compress) {
10312       *point++ = ':';
10313       // If we skip a value initially, we need to write '::', otherwise
10314       // a single ':' will do since it follows a previous ':'.
10315       if (piece_index == 0) {
10316         *point++ = ':';
10317       }
10318       piece_index += compress_length;
10319       if (piece_index == 8) {
10320         break;
10321       }
10322     }
10323     point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
10324     piece_index++;
10325     if (piece_index == 8) {
10326       break;
10327     }
10328     *point++ = ':';
10329   }
10330   *point++ = ']';
10331   output.resize(point - output.data());
10332   return output;
10333 }
10334 
ipv4(const uint64_t address)10335 std::string ipv4(const uint64_t address) noexcept {
10336   std::string output(15, '\0');
10337   char* point = output.data();
10338   char* point_end = output.data() + output.size();
10339   point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
10340   for (int i = 2; i >= 0; i--) {
10341     *point++ = '.';
10342     point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
10343   }
10344   output.resize(point - output.data());
10345   return output;
10346 }
10347 
10348 }  // namespace ada::serializers
10349 /* end file src/serializers.cpp */
10350 /* begin file src/implementation.cpp */
10351 #include <string_view>
10352 
10353 
10354 namespace ada {
10355 
10356 template <class result_type>
parse(std::string_view input,const result_type * base_url)10357 ada_warn_unused tl::expected<result_type, ada::errors> parse(
10358     std::string_view input, const result_type* base_url) {
10359   result_type u = ada::parser::parse_url<result_type>(input, base_url);
10360   if (!u.is_valid) {
10361     return tl::unexpected(errors::generic_error);
10362   }
10363   return u;
10364 }
10365 
10366 template ada::result<url> parse<url>(std::string_view input,
10367                                      const url* base_url = nullptr);
10368 template ada::result<url_aggregator> parse<url_aggregator>(
10369     std::string_view input, const url_aggregator* base_url = nullptr);
10370 
href_from_file(std::string_view input)10371 std::string href_from_file(std::string_view input) {
10372   // This is going to be much faster than constructing a URL.
10373   std::string tmp_buffer;
10374   std::string_view internal_input;
10375   if (unicode::has_tabs_or_newline(input)) {
10376     tmp_buffer = input;
10377     helpers::remove_ascii_tab_or_newline(tmp_buffer);
10378     internal_input = tmp_buffer;
10379   } else {
10380     internal_input = input;
10381   }
10382   std::string path;
10383   if (internal_input.empty()) {
10384     path = "/";
10385   } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
10386     helpers::parse_prepared_path(internal_input.substr(1),
10387                                  ada::scheme::type::FILE, path);
10388   } else {
10389     helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
10390   }
10391   return "file://" + path;
10392 }
10393 
can_parse(std::string_view input,const std::string_view * base_input)10394 bool can_parse(std::string_view input, const std::string_view* base_input) {
10395   ada::result<ada::url_aggregator> base;
10396   ada::url_aggregator* base_pointer = nullptr;
10397   if (base_input != nullptr) {
10398     base = ada::parse<url_aggregator>(*base_input);
10399     if (!base) {
10400       return false;
10401     }
10402     base_pointer = &base.value();
10403   }
10404   return ada::parse<url_aggregator>(input, base_pointer).has_value();
10405 }
10406 
to_string(ada::encoding_type type)10407 ada_warn_unused std::string to_string(ada::encoding_type type) {
10408   switch (type) {
10409     case ada::encoding_type::UTF8:
10410       return "UTF-8";
10411     case ada::encoding_type::UTF_16LE:
10412       return "UTF-16LE";
10413     case ada::encoding_type::UTF_16BE:
10414       return "UTF-16BE";
10415     default:
10416       unreachable();
10417   }
10418 }
10419 
10420 }  // namespace ada
10421 /* end file src/implementation.cpp */
10422 /* begin file src/helpers.cpp */
10423 
10424 #include <algorithm>
10425 #include <charconv>
10426 #include <cstring>
10427 #include <sstream>
10428 
10429 namespace ada::helpers {
10430 
10431 template <typename out_iter>
encode_json(std::string_view view,out_iter out)10432 void encode_json(std::string_view view, out_iter out) {
10433   // trivial implementation. could be faster.
10434   const char* hexvalues =
10435       "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
10436   for (uint8_t c : view) {
10437     if (c == '\\') {
10438       *out++ = '\\';
10439       *out++ = '\\';
10440     } else if (c == '"') {
10441       *out++ = '\\';
10442       *out++ = '"';
10443     } else if (c <= 0x1f) {
10444       *out++ = '\\';
10445       *out++ = 'u';
10446       *out++ = '0';
10447       *out++ = '0';
10448       *out++ = hexvalues[2 * c];
10449       *out++ = hexvalues[2 * c + 1];
10450     } else {
10451       *out++ = c;
10452     }
10453   }
10454 }
10455 
get_state(ada::state s)10456 ada_unused std::string get_state(ada::state s) {
10457   switch (s) {
10458     case ada::state::AUTHORITY:
10459       return "Authority";
10460     case ada::state::SCHEME_START:
10461       return "Scheme Start";
10462     case ada::state::SCHEME:
10463       return "Scheme";
10464     case ada::state::HOST:
10465       return "Host";
10466     case ada::state::NO_SCHEME:
10467       return "No Scheme";
10468     case ada::state::FRAGMENT:
10469       return "Fragment";
10470     case ada::state::RELATIVE_SCHEME:
10471       return "Relative Scheme";
10472     case ada::state::RELATIVE_SLASH:
10473       return "Relative Slash";
10474     case ada::state::FILE:
10475       return "File";
10476     case ada::state::FILE_HOST:
10477       return "File Host";
10478     case ada::state::FILE_SLASH:
10479       return "File Slash";
10480     case ada::state::PATH_OR_AUTHORITY:
10481       return "Path or Authority";
10482     case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
10483       return "Special Authority Ignore Slashes";
10484     case ada::state::SPECIAL_AUTHORITY_SLASHES:
10485       return "Special Authority Slashes";
10486     case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
10487       return "Special Relative or Authority";
10488     case ada::state::QUERY:
10489       return "Query";
10490     case ada::state::PATH:
10491       return "Path";
10492     case ada::state::PATH_START:
10493       return "Path Start";
10494     case ada::state::OPAQUE_PATH:
10495       return "Opaque Path";
10496     case ada::state::PORT:
10497       return "Port";
10498     default:
10499       return "unknown state";
10500   }
10501 }
10502 
prune_hash(std::string_view & input)10503 ada_really_inline std::optional<std::string_view> prune_hash(
10504     std::string_view& input) noexcept {
10505   // compiles down to 20--30 instructions including a class to memchr (C
10506   // function). this function should be quite fast.
10507   size_t location_of_first = input.find('#');
10508   if (location_of_first == std::string_view::npos) {
10509     return std::nullopt;
10510   }
10511   std::string_view hash = input;
10512   hash.remove_prefix(location_of_first + 1);
10513   input.remove_suffix(input.size() - location_of_first);
10514   return hash;
10515 }
10516 
shorten_path(std::string & path,ada::scheme::type type)10517 ada_really_inline bool shorten_path(std::string& path,
10518                                     ada::scheme::type type) noexcept {
10519   size_t first_delimiter = path.find_first_of('/', 1);
10520 
10521   // Let path be url's path.
10522   // If url's scheme is "file", path's size is 1, and path[0] is a normalized
10523   // Windows drive letter, then return.
10524   if (type == ada::scheme::type::FILE &&
10525       first_delimiter == std::string_view::npos && !path.empty()) {
10526     if (checkers::is_normalized_windows_drive_letter(
10527             helpers::substring(path, 1))) {
10528       return false;
10529     }
10530   }
10531 
10532   // Remove path's last item, if any.
10533   size_t last_delimiter = path.rfind('/');
10534   if (last_delimiter != std::string::npos) {
10535     path.erase(last_delimiter);
10536     return true;
10537   }
10538 
10539   return false;
10540 }
10541 
shorten_path(std::string_view & path,ada::scheme::type type)10542 ada_really_inline bool shorten_path(std::string_view& path,
10543                                     ada::scheme::type type) noexcept {
10544   size_t first_delimiter = path.find_first_of('/', 1);
10545 
10546   // Let path be url's path.
10547   // If url's scheme is "file", path's size is 1, and path[0] is a normalized
10548   // Windows drive letter, then return.
10549   if (type == ada::scheme::type::FILE &&
10550       first_delimiter == std::string_view::npos && !path.empty()) {
10551     if (checkers::is_normalized_windows_drive_letter(
10552             helpers::substring(path, 1))) {
10553       return false;
10554     }
10555   }
10556 
10557   // Remove path's last item, if any.
10558   if (!path.empty()) {
10559     size_t slash_loc = path.rfind('/');
10560     if (slash_loc != std::string_view::npos) {
10561       path.remove_suffix(path.size() - slash_loc);
10562       return true;
10563     }
10564   }
10565 
10566   return false;
10567 }
10568 
remove_ascii_tab_or_newline(std::string & input)10569 ada_really_inline void remove_ascii_tab_or_newline(
10570     std::string& input) noexcept {
10571   // if this ever becomes a performance issue, we could use an approach similar
10572   // to has_tabs_or_newline
10573   input.erase(std::remove_if(input.begin(), input.end(),
10574                              [](char c) {
10575                                return ada::unicode::is_ascii_tab_or_newline(c);
10576                              }),
10577               input.end());
10578 }
10579 
substring(std::string_view input,size_t pos)10580 ada_really_inline std::string_view substring(std::string_view input,
10581                                              size_t pos) noexcept {
10582   ADA_ASSERT_TRUE(pos <= input.size());
10583   // The following is safer but unneeded if we have the above line:
10584   // return pos > input.size() ? std::string_view() : input.substr(pos);
10585   return input.substr(pos);
10586 }
10587 
resize(std::string_view & input,size_t pos)10588 ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
10589   ADA_ASSERT_TRUE(pos <= input.size());
10590   input.remove_suffix(input.size() - pos);
10591 }
10592 
10593 // computes the number of trailing zeroes
10594 // this is a private inline function only defined in this source file.
trailing_zeroes(uint32_t input_num)10595 ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
10596 #ifdef ADA_REGULAR_VISUAL_STUDIO
10597   unsigned long ret;
10598   // Search the mask data from least significant bit (LSB)
10599   // to the most significant bit (MSB) for a set bit (1).
10600   _BitScanForward(&ret, input_num);
10601   return (int)ret;
10602 #else   // ADA_REGULAR_VISUAL_STUDIO
10603   return __builtin_ctzl(input_num);
10604 #endif  // ADA_REGULAR_VISUAL_STUDIO
10605 }
10606 
10607 // starting at index location, this finds the next location of a character
10608 // :, /, \\, ? or [. If none is found, view.size() is returned.
10609 // For use within get_host_delimiter_location.
10610 #if ADA_NEON
10611 // The ada_make_uint8x16_t macro is necessary because Visual Studio does not
10612 // support direct initialization of uint8x16_t. See
10613 // https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
10614 #ifndef ada_make_uint8x16_t
10615 #define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
10616                             x13, x14, x15, x16)                                \
10617   ([=]() {                                                                     \
10618     static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
10619                                 x9, x10, x11, x12, x13, x14, x15, x16};        \
10620     return vld1q_u8(array);                                                    \
10621   }())
10622 #endif
10623 
find_next_host_delimiter_special(std::string_view view,size_t location)10624 ada_really_inline size_t find_next_host_delimiter_special(
10625     std::string_view view, size_t location) noexcept {
10626   // first check for short strings in which case we do it naively.
10627   if (view.size() - location < 16) {  // slow path
10628     for (size_t i = location; i < view.size(); i++) {
10629       if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
10630           view[i] == '?' || view[i] == '[') {
10631         return i;
10632       }
10633     }
10634     return size_t(view.size());
10635   }
10636   auto to_bitmask = [](uint8x16_t input) -> uint16_t {
10637     uint8x16_t bit_mask =
10638         ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
10639                             0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
10640     uint8x16_t minput = vandq_u8(input, bit_mask);
10641     uint8x16_t tmp = vpaddq_u8(minput, minput);
10642     tmp = vpaddq_u8(tmp, tmp);
10643     tmp = vpaddq_u8(tmp, tmp);
10644     return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
10645   };
10646 
10647   // fast path for long strings (expected to be common)
10648   size_t i = location;
10649   uint8x16_t low_mask =
10650       ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10651                           0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
10652   uint8x16_t high_mask =
10653       ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
10654                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
10655   uint8x16_t fmask = vmovq_n_u8(0xf);
10656   uint8x16_t zero{0};
10657   for (; i + 15 < view.size(); i += 16) {
10658     uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
10659     uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10660     uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10661     uint8x16_t classify = vandq_u8(lowpart, highpart);
10662     if (vmaxvq_u8(classify) != 0) {
10663       uint8x16_t is_zero = vceqq_u8(classify, zero);
10664       uint16_t is_non_zero = ~to_bitmask(is_zero);
10665       return i + trailing_zeroes(is_non_zero);
10666     }
10667   }
10668 
10669   if (i < view.size()) {
10670     uint8x16_t word =
10671         vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
10672     uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10673     uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10674     uint8x16_t classify = vandq_u8(lowpart, highpart);
10675     if (vmaxvq_u8(classify) != 0) {
10676       uint8x16_t is_zero = vceqq_u8(classify, zero);
10677       uint16_t is_non_zero = ~to_bitmask(is_zero);
10678       return view.length() - 16 + trailing_zeroes(is_non_zero);
10679     }
10680   }
10681   return size_t(view.size());
10682 }
10683 #elif ADA_SSE2
find_next_host_delimiter_special(std::string_view view,size_t location)10684 ada_really_inline size_t find_next_host_delimiter_special(
10685     std::string_view view, size_t location) noexcept {
10686   // first check for short strings in which case we do it naively.
10687   if (view.size() - location < 16) {  // slow path
10688     for (size_t i = location; i < view.size(); i++) {
10689       if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
10690           view[i] == '?' || view[i] == '[') {
10691         return i;
10692       }
10693     }
10694     return size_t(view.size());
10695   }
10696   // fast path for long strings (expected to be common)
10697   size_t i = location;
10698   const __m128i mask1 = _mm_set1_epi8(':');
10699   const __m128i mask2 = _mm_set1_epi8('/');
10700   const __m128i mask3 = _mm_set1_epi8('\\');
10701   const __m128i mask4 = _mm_set1_epi8('?');
10702   const __m128i mask5 = _mm_set1_epi8('[');
10703 
10704   for (; i + 15 < view.size(); i += 16) {
10705     __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
10706     __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10707     __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10708     __m128i m3 = _mm_cmpeq_epi8(word, mask3);
10709     __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10710     __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10711     __m128i m = _mm_or_si128(
10712         _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
10713     int mask = _mm_movemask_epi8(m);
10714     if (mask != 0) {
10715       return i + trailing_zeroes(mask);
10716     }
10717   }
10718   if (i < view.size()) {
10719     __m128i word =
10720         _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
10721     __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10722     __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10723     __m128i m3 = _mm_cmpeq_epi8(word, mask3);
10724     __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10725     __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10726     __m128i m = _mm_or_si128(
10727         _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
10728     int mask = _mm_movemask_epi8(m);
10729     if (mask != 0) {
10730       return view.length() - 16 + trailing_zeroes(mask);
10731     }
10732   }
10733   return size_t(view.length());
10734 }
10735 #else
10736 // : / [ \\ ?
10737 static constexpr std::array<uint8_t, 256> special_host_delimiters =
__anon4ddc785e1202() 10738     []() constexpr {
10739       std::array<uint8_t, 256> result{};
10740       for (int i : {':', '/', '[', '\\', '?'}) {
10741         result[i] = 1;
10742       }
10743       return result;
10744     }();
10745 // credit: @the-moisrex recommended a table-based approach
find_next_host_delimiter_special(std::string_view view,size_t location)10746 ada_really_inline size_t find_next_host_delimiter_special(
10747     std::string_view view, size_t location) noexcept {
10748   auto const str = view.substr(location);
10749   for (auto pos = str.begin(); pos != str.end(); ++pos) {
10750     if (special_host_delimiters[(uint8_t)*pos]) {
10751       return pos - str.begin() + location;
10752     }
10753   }
10754   return size_t(view.size());
10755 }
10756 #endif
10757 
10758 // starting at index location, this finds the next location of a character
10759 // :, /, ? or [. If none is found, view.size() is returned.
10760 // For use within get_host_delimiter_location.
10761 #if ADA_NEON
find_next_host_delimiter(std::string_view view,size_t location)10762 ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10763                                                   size_t location) noexcept {
10764   // first check for short strings in which case we do it naively.
10765   if (view.size() - location < 16) {  // slow path
10766     for (size_t i = location; i < view.size(); i++) {
10767       if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
10768           view[i] == '[') {
10769         return i;
10770       }
10771     }
10772     return size_t(view.size());
10773   }
10774   auto to_bitmask = [](uint8x16_t input) -> uint16_t {
10775     uint8x16_t bit_mask =
10776         ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
10777                             0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
10778     uint8x16_t minput = vandq_u8(input, bit_mask);
10779     uint8x16_t tmp = vpaddq_u8(minput, minput);
10780     tmp = vpaddq_u8(tmp, tmp);
10781     tmp = vpaddq_u8(tmp, tmp);
10782     return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
10783   };
10784 
10785   // fast path for long strings (expected to be common)
10786   size_t i = location;
10787   uint8x16_t low_mask =
10788       ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10789                           0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
10790   uint8x16_t high_mask =
10791       ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
10792                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
10793   uint8x16_t fmask = vmovq_n_u8(0xf);
10794   uint8x16_t zero{0};
10795   for (; i + 15 < view.size(); i += 16) {
10796     uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
10797     uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10798     uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10799     uint8x16_t classify = vandq_u8(lowpart, highpart);
10800     if (vmaxvq_u8(classify) != 0) {
10801       uint8x16_t is_zero = vceqq_u8(classify, zero);
10802       uint16_t is_non_zero = ~to_bitmask(is_zero);
10803       return i + trailing_zeroes(is_non_zero);
10804     }
10805   }
10806 
10807   if (i < view.size()) {
10808     uint8x16_t word =
10809         vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
10810     uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
10811     uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
10812     uint8x16_t classify = vandq_u8(lowpart, highpart);
10813     if (vmaxvq_u8(classify) != 0) {
10814       uint8x16_t is_zero = vceqq_u8(classify, zero);
10815       uint16_t is_non_zero = ~to_bitmask(is_zero);
10816       return view.length() - 16 + trailing_zeroes(is_non_zero);
10817     }
10818   }
10819   return size_t(view.size());
10820 }
10821 #elif ADA_SSE2
find_next_host_delimiter(std::string_view view,size_t location)10822 ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10823                                                   size_t location) noexcept {
10824   // first check for short strings in which case we do it naively.
10825   if (view.size() - location < 16) {  // slow path
10826     for (size_t i = location; i < view.size(); i++) {
10827       if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
10828           view[i] == '[') {
10829         return i;
10830       }
10831     }
10832     return size_t(view.size());
10833   }
10834   // fast path for long strings (expected to be common)
10835   size_t i = location;
10836   const __m128i mask1 = _mm_set1_epi8(':');
10837   const __m128i mask2 = _mm_set1_epi8('/');
10838   const __m128i mask4 = _mm_set1_epi8('?');
10839   const __m128i mask5 = _mm_set1_epi8('[');
10840 
10841   for (; i + 15 < view.size(); i += 16) {
10842     __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
10843     __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10844     __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10845     __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10846     __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10847     __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
10848     int mask = _mm_movemask_epi8(m);
10849     if (mask != 0) {
10850       return i + trailing_zeroes(mask);
10851     }
10852   }
10853   if (i < view.size()) {
10854     __m128i word =
10855         _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
10856     __m128i m1 = _mm_cmpeq_epi8(word, mask1);
10857     __m128i m2 = _mm_cmpeq_epi8(word, mask2);
10858     __m128i m4 = _mm_cmpeq_epi8(word, mask4);
10859     __m128i m5 = _mm_cmpeq_epi8(word, mask5);
10860     __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
10861     int mask = _mm_movemask_epi8(m);
10862     if (mask != 0) {
10863       return view.length() - 16 + trailing_zeroes(mask);
10864     }
10865   }
10866   return size_t(view.length());
10867 }
10868 #else
10869 // : / [ ?
__anon4ddc785e1402() 10870 static constexpr std::array<uint8_t, 256> host_delimiters = []() constexpr {
10871   std::array<uint8_t, 256> result{};
10872   for (int i : {':', '/', '?', '['}) {
10873     result[i] = 1;
10874   }
10875   return result;
10876 }();
10877 // credit: @the-moisrex recommended a table-based approach
find_next_host_delimiter(std::string_view view,size_t location)10878 ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10879                                                   size_t location) noexcept {
10880   auto const str = view.substr(location);
10881   for (auto pos = str.begin(); pos != str.end(); ++pos) {
10882     if (host_delimiters[(uint8_t)*pos]) {
10883       return pos - str.begin() + location;
10884     }
10885   }
10886   return size_t(view.size());
10887 }
10888 #endif
10889 
get_host_delimiter_location(const bool is_special,std::string_view & view)10890 ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
10891     const bool is_special, std::string_view& view) noexcept {
10892   /**
10893    * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
10894    * compute a variable called insideBrackets but this variable is only used
10895    * once, to check whether a ':' character was found outside brackets. Exact
10896    * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
10897    * It is conceptually simpler and arguably more efficient to just return a
10898    * Boolean indicating whether ':' was found outside brackets.
10899    */
10900   const size_t view_size = view.size();
10901   size_t location = 0;
10902   bool found_colon = false;
10903   /**
10904    * Performance analysis:
10905    *
10906    * We are basically seeking the end of the hostname which can be indicated
10907    * by the end of the view, or by one of the characters ':', '/', '?', '\\'
10908    * (where '\\' is only applicable for special URLs). However, these must
10909    * appear outside a bracket range. E.g., if you have [something?]fd: then the
10910    * '?' does not count.
10911    *
10912    * So we can skip ahead to the next delimiter, as long as we include '[' in
10913    * the set of delimiters, and that we handle it first.
10914    *
10915    * So the trick is to have a fast function that locates the next delimiter.
10916    * Unless we find '[', then it only needs to be called once! Ideally, such a
10917    * function would be provided by the C++ standard library, but it seems that
10918    * find_first_of is not very fast, so we are forced to roll our own.
10919    *
10920    * We do not break into two loops for speed, but for clarity.
10921    */
10922   if (is_special) {
10923     // We move to the next delimiter.
10924     location = find_next_host_delimiter_special(view, location);
10925     // Unless we find '[' then we are going only going to have to call
10926     // find_next_host_delimiter_special once.
10927     for (; location < view_size;
10928          location = find_next_host_delimiter_special(view, location)) {
10929       if (view[location] == '[') {
10930         location = view.find(']', location);
10931         if (location == std::string_view::npos) {
10932           // performance: view.find might get translated to a memchr, which
10933           // has no notion of std::string_view::npos, so the code does not
10934           // reflect the assembly.
10935           location = view_size;
10936           break;
10937         }
10938       } else {
10939         found_colon = view[location] == ':';
10940         break;
10941       }
10942     }
10943   } else {
10944     // We move to the next delimiter.
10945     location = find_next_host_delimiter(view, location);
10946     // Unless we find '[' then we are going only going to have to call
10947     // find_next_host_delimiter_special once.
10948     for (; location < view_size;
10949          location = find_next_host_delimiter(view, location)) {
10950       if (view[location] == '[') {
10951         location = view.find(']', location);
10952         if (location == std::string_view::npos) {
10953           // performance: view.find might get translated to a memchr, which
10954           // has no notion of std::string_view::npos, so the code does not
10955           // reflect the assembly.
10956           location = view_size;
10957           break;
10958         }
10959       } else {
10960         found_colon = view[location] == ':';
10961         break;
10962       }
10963     }
10964   }
10965   // performance: remove_suffix may translate into a single instruction.
10966   view.remove_suffix(view_size - location);
10967   return {location, found_colon};
10968 }
10969 
trim_c0_whitespace(std::string_view & input)10970 ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
10971   while (!input.empty() &&
10972          ada::unicode::is_c0_control_or_space(input.front())) {
10973     input.remove_prefix(1);
10974   }
10975   while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
10976     input.remove_suffix(1);
10977   }
10978 }
10979 
parse_prepared_path(std::string_view input,ada::scheme::type type,std::string & path)10980 ada_really_inline void parse_prepared_path(std::string_view input,
10981                                            ada::scheme::type type,
10982                                            std::string& path) {
10983   ada_log("parse_prepared_path ", input);
10984   uint8_t accumulator = checkers::path_signature(input);
10985   // Let us first detect a trivial case.
10986   // If it is special, we check that we have no dot, no %,  no \ and no
10987   // character needing percent encoding. Otherwise, we check that we have no %,
10988   // no dot, and no character needing percent encoding.
10989   constexpr uint8_t need_encoding = 1;
10990   constexpr uint8_t backslash_char = 2;
10991   constexpr uint8_t dot_char = 4;
10992   constexpr uint8_t percent_char = 8;
10993   bool special = type != ada::scheme::NOT_SPECIAL;
10994   bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
10995                                       checkers::is_windows_drive_letter(input));
10996   bool trivial_path =
10997       (special ? (accumulator == 0)
10998                : ((accumulator & (need_encoding | dot_char | percent_char)) ==
10999                   0)) &&
11000       (!may_need_slow_file_handling);
11001   if (accumulator == dot_char && !may_need_slow_file_handling) {
11002     // '4' means that we have at least one dot, but nothing that requires
11003     // percent encoding or decoding. The only part that is not trivial is
11004     // that we may have single dots and double dots path segments.
11005     // If we have such segments, then we either have a path that begins
11006     // with '.' (easy to check), or we have the sequence './'.
11007     // Note: input cannot be empty, it must at least contain one character ('.')
11008     // Note: we know that '\' is not present.
11009     if (input[0] != '.') {
11010       size_t slashdot = input.find("/.");
11011       if (slashdot == std::string_view::npos) {  // common case
11012         trivial_path = true;
11013       } else {  // uncommon
11014         // only three cases matter: /./, /.. or a final /
11015         trivial_path =
11016             !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
11017               input[slashdot + 2] == '/');
11018       }
11019     }
11020   }
11021   if (trivial_path) {
11022     ada_log("parse_path trivial");
11023     path += '/';
11024     path += input;
11025     return;
11026   }
11027   // We are going to need to look a bit at the path, but let us see if we can
11028   // ignore percent encoding *and* backslashes *and* percent characters.
11029   // Except for the trivial case, this is likely to capture 99% of paths out
11030   // there.
11031   bool fast_path =
11032       (special &&
11033        (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
11034       (type != ada::scheme::type::FILE);
11035   if (fast_path) {
11036     ada_log("parse_prepared_path fast");
11037     // Here we don't need to worry about \ or percent encoding.
11038     // We also do not have a file protocol. We might have dots, however,
11039     // but dots must as appear as '.', and they cannot be encoded because
11040     // the symbol '%' is not present.
11041     size_t previous_location = 0;  // We start at 0.
11042     do {
11043       size_t new_location = input.find('/', previous_location);
11044       // std::string_view path_view = input;
11045       //  We process the last segment separately:
11046       if (new_location == std::string_view::npos) {
11047         std::string_view path_view = input.substr(previous_location);
11048         if (path_view == "..") {  // The path ends with ..
11049           // e.g., if you receive ".." with an empty path, you go to "/".
11050           if (path.empty()) {
11051             path = '/';
11052             return;
11053           }
11054           // Fast case where we have nothing to do:
11055           if (path.back() == '/') {
11056             return;
11057           }
11058           // If you have the path "/joe/myfriend",
11059           // then you delete 'myfriend'.
11060           path.resize(path.rfind('/') + 1);
11061           return;
11062         }
11063         path += '/';
11064         if (path_view != ".") {
11065           path.append(path_view);
11066         }
11067         return;
11068       } else {
11069         // This is a non-final segment.
11070         std::string_view path_view =
11071             input.substr(previous_location, new_location - previous_location);
11072         previous_location = new_location + 1;
11073         if (path_view == "..") {
11074           size_t last_delimiter = path.rfind('/');
11075           if (last_delimiter != std::string::npos) {
11076             path.erase(last_delimiter);
11077           }
11078         } else if (path_view != ".") {
11079           path += '/';
11080           path.append(path_view);
11081         }
11082       }
11083     } while (true);
11084   } else {
11085     ada_log("parse_path slow");
11086     // we have reached the general case
11087     bool needs_percent_encoding = (accumulator & 1);
11088     std::string path_buffer_tmp;
11089     do {
11090       size_t location = (special && (accumulator & 2))
11091                             ? input.find_first_of("/\\")
11092                             : input.find('/');
11093       std::string_view path_view = input;
11094       if (location != std::string_view::npos) {
11095         path_view.remove_suffix(path_view.size() - location);
11096         input.remove_prefix(location + 1);
11097       }
11098       // path_buffer is either path_view or it might point at a percent encoded
11099       // temporary file.
11100       std::string_view path_buffer =
11101           (needs_percent_encoding &&
11102            ada::unicode::percent_encode<false>(
11103                path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
11104               ? path_buffer_tmp
11105               : path_view;
11106       if (unicode::is_double_dot_path_segment(path_buffer)) {
11107         if ((helpers::shorten_path(path, type) || special) &&
11108             location == std::string_view::npos) {
11109           path += '/';
11110         }
11111       } else if (unicode::is_single_dot_path_segment(path_buffer) &&
11112                  (location == std::string_view::npos)) {
11113         path += '/';
11114       }
11115       // Otherwise, if path_buffer is not a single-dot path segment, then:
11116       else if (!unicode::is_single_dot_path_segment(path_buffer)) {
11117         // If url's scheme is "file", url's path is empty, and path_buffer is a
11118         // Windows drive letter, then replace the second code point in
11119         // path_buffer with U+003A (:).
11120         if (type == ada::scheme::type::FILE && path.empty() &&
11121             checkers::is_windows_drive_letter(path_buffer)) {
11122           path += '/';
11123           path += path_buffer[0];
11124           path += ':';
11125           path_buffer.remove_prefix(2);
11126           path.append(path_buffer);
11127         } else {
11128           // Append path_buffer to url's path.
11129           path += '/';
11130           path.append(path_buffer);
11131         }
11132       }
11133       if (location == std::string_view::npos) {
11134         return;
11135       }
11136     } while (true);
11137   }
11138 }
11139 
overlaps(std::string_view input1,const std::string & input2)11140 bool overlaps(std::string_view input1, const std::string& input2) noexcept {
11141   ada_log("helpers::overlaps check if string_view '", input1, "' [",
11142           input1.size(), " bytes] is part of string '", input2, "' [",
11143           input2.size(), " bytes]");
11144   return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
11145          input1.data() < input2.data() + input2.size();
11146 }
11147 
11148 template <class url_type>
strip_trailing_spaces_from_opaque_path(url_type & url)11149 ada_really_inline void strip_trailing_spaces_from_opaque_path(
11150     url_type& url) noexcept {
11151   ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11152   if (!url.has_opaque_path) return;
11153   if (url.has_hash()) return;
11154   if (url.has_search()) return;
11155 
11156   auto path = std::string(url.get_pathname());
11157   while (!path.empty() && path.back() == ' ') {
11158     path.resize(path.size() - 1);
11159   }
11160   url.update_base_pathname(path);
11161 }
11162 
11163 // @ / \\ ?
11164 static constexpr std::array<uint8_t, 256> authority_delimiter_special =
__anon4ddc785e1502() 11165     []() constexpr {
11166       std::array<uint8_t, 256> result{};
11167       for (int i : {'@', '/', '\\', '?'}) {
11168         result[i] = 1;
11169       }
11170       return result;
11171     }();
11172 // credit: @the-moisrex recommended a table-based approach
11173 ada_really_inline size_t
find_authority_delimiter_special(std::string_view view)11174 find_authority_delimiter_special(std::string_view view) noexcept {
11175   // performance note: we might be able to gain further performance
11176   // with SIMD instrinsics.
11177   for (auto pos = view.begin(); pos != view.end(); ++pos) {
11178     if (authority_delimiter_special[(uint8_t)*pos]) {
11179       return pos - view.begin();
11180     }
11181   }
11182   return size_t(view.size());
11183 }
11184 
11185 // @ / ?
__anon4ddc785e1602() 11186 static constexpr std::array<uint8_t, 256> authority_delimiter = []() constexpr {
11187   std::array<uint8_t, 256> result{};
11188   for (int i : {'@', '/', '?'}) {
11189     result[i] = 1;
11190   }
11191   return result;
11192 }();
11193 // credit: @the-moisrex recommended a table-based approach
11194 ada_really_inline size_t
find_authority_delimiter(std::string_view view)11195 find_authority_delimiter(std::string_view view) noexcept {
11196   // performance note: we might be able to gain further performance
11197   // with SIMD instrinsics.
11198   for (auto pos = view.begin(); pos != view.end(); ++pos) {
11199     if (authority_delimiter[(uint8_t)*pos]) {
11200       return pos - view.begin();
11201     }
11202   }
11203   return size_t(view.size());
11204 }
11205 
11206 }  // namespace ada::helpers
11207 
11208 namespace ada {
to_string(ada::state state)11209 ada_warn_unused std::string to_string(ada::state state) {
11210   return ada::helpers::get_state(state);
11211 }
11212 #undef ada_make_uint8x16_t
11213 }  // namespace ada
11214 /* end file src/helpers.cpp */
11215 /* begin file src/url.cpp */
11216 
11217 #include <numeric>
11218 #include <algorithm>
11219 #include <string>
11220 
11221 namespace ada {
11222 
parse_opaque_host(std::string_view input)11223 bool url::parse_opaque_host(std::string_view input) {
11224   ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
11225   if (std::any_of(input.begin(), input.end(),
11226                   ada::unicode::is_forbidden_host_code_point)) {
11227     return is_valid = false;
11228   }
11229 
11230   // Return the result of running UTF-8 percent-encode on input using the C0
11231   // control percent-encode set.
11232   host = ada::unicode::percent_encode(
11233       input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
11234   return true;
11235 }
11236 
parse_ipv4(std::string_view input)11237 bool url::parse_ipv4(std::string_view input) {
11238   ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
11239   if (input.back() == '.') {
11240     input.remove_suffix(1);
11241   }
11242   size_t digit_count{0};
11243   int pure_decimal_count = 0;  // entries that are decimal
11244   std::string_view original_input =
11245       input;  // we might use this if pure_decimal_count == 4.
11246   uint64_t ipv4{0};
11247   // we could unroll for better performance?
11248   for (; (digit_count < 4) && !(input.empty()); digit_count++) {
11249     uint32_t
11250         segment_result{};  // If any number exceeds 32 bits, we have an error.
11251     bool is_hex = checkers::has_hex_prefix(input);
11252     if (is_hex && ((input.length() == 2) ||
11253                    ((input.length() > 2) && (input[2] == '.')))) {
11254       // special case
11255       segment_result = 0;
11256       input.remove_prefix(2);
11257     } else {
11258       std::from_chars_result r;
11259       if (is_hex) {
11260         r = std::from_chars(input.data() + 2, input.data() + input.size(),
11261                             segment_result, 16);
11262       } else if ((input.length() >= 2) && input[0] == '0' &&
11263                  checkers::is_digit(input[1])) {
11264         r = std::from_chars(input.data() + 1, input.data() + input.size(),
11265                             segment_result, 8);
11266       } else {
11267         pure_decimal_count++;
11268         r = std::from_chars(input.data(), input.data() + input.size(),
11269                             segment_result, 10);
11270       }
11271       if (r.ec != std::errc()) {
11272         return is_valid = false;
11273       }
11274       input.remove_prefix(r.ptr - input.data());
11275     }
11276     if (input.empty()) {
11277       // We have the last value.
11278       // At this stage, ipv4 contains digit_count*8 bits.
11279       // So we have 32-digit_count*8 bits left.
11280       if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
11281         return is_valid = false;
11282       }
11283       ipv4 <<= (32 - digit_count * 8);
11284       ipv4 |= segment_result;
11285       goto final;
11286     } else {
11287       // There is more, so that the value must no be larger than 255
11288       // and we must have a '.'.
11289       if ((segment_result > 255) || (input[0] != '.')) {
11290         return is_valid = false;
11291       }
11292       ipv4 <<= 8;
11293       ipv4 |= segment_result;
11294       input.remove_prefix(1);  // remove '.'
11295     }
11296   }
11297   if ((digit_count != 4) || (!input.empty())) {
11298     return is_valid = false;
11299   }
11300 final:
11301   // We could also check r.ptr to see where the parsing ended.
11302   if (pure_decimal_count == 4) {
11303     host = original_input;  // The original input was already all decimal and we
11304                             // validated it.
11305   } else {
11306     host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
11307   }
11308   host_type = IPV4;
11309   return true;
11310 }
11311 
parse_ipv6(std::string_view input)11312 bool url::parse_ipv6(std::string_view input) {
11313   ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
11314 
11315   if (input.empty()) {
11316     return is_valid = false;
11317   }
11318   // Let address be a new IPv6 address whose IPv6 pieces are all 0.
11319   std::array<uint16_t, 8> address{};
11320 
11321   // Let pieceIndex be 0.
11322   int piece_index = 0;
11323 
11324   // Let compress be null.
11325   std::optional<int> compress{};
11326 
11327   // Let pointer be a pointer for input.
11328   std::string_view::iterator pointer = input.begin();
11329 
11330   // If c is U+003A (:), then:
11331   if (input[0] == ':') {
11332     // If remaining does not start with U+003A (:), validation error, return
11333     // failure.
11334     if (input.size() == 1 || input[1] != ':') {
11335       ada_log("parse_ipv6 starts with : but the rest does not start with :");
11336       return is_valid = false;
11337     }
11338 
11339     // Increase pointer by 2.
11340     pointer += 2;
11341 
11342     // Increase pieceIndex by 1 and then set compress to pieceIndex.
11343     compress = ++piece_index;
11344   }
11345 
11346   // While c is not the EOF code point:
11347   while (pointer != input.end()) {
11348     // If pieceIndex is 8, validation error, return failure.
11349     if (piece_index == 8) {
11350       ada_log("parse_ipv6 piece_index == 8");
11351       return is_valid = false;
11352     }
11353 
11354     // If c is U+003A (:), then:
11355     if (*pointer == ':') {
11356       // If compress is non-null, validation error, return failure.
11357       if (compress.has_value()) {
11358         ada_log("parse_ipv6 compress is non-null");
11359         return is_valid = false;
11360       }
11361 
11362       // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
11363       // then continue.
11364       pointer++;
11365       compress = ++piece_index;
11366       continue;
11367     }
11368 
11369     // Let value and length be 0.
11370     uint16_t value = 0, length = 0;
11371 
11372     // While length is less than 4 and c is an ASCII hex digit,
11373     // set value to value times 0x10 + c interpreted as hexadecimal number, and
11374     // increase pointer and length by 1.
11375     while (length < 4 && pointer != input.end() &&
11376            unicode::is_ascii_hex_digit(*pointer)) {
11377       // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11378       value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
11379       pointer++;
11380       length++;
11381     }
11382 
11383     // If c is U+002E (.), then:
11384     if (pointer != input.end() && *pointer == '.') {
11385       // If length is 0, validation error, return failure.
11386       if (length == 0) {
11387         ada_log("parse_ipv6 length is 0");
11388         return is_valid = false;
11389       }
11390 
11391       // Decrease pointer by length.
11392       pointer -= length;
11393 
11394       // If pieceIndex is greater than 6, validation error, return failure.
11395       if (piece_index > 6) {
11396         ada_log("parse_ipv6 piece_index > 6");
11397         return is_valid = false;
11398       }
11399 
11400       // Let numbersSeen be 0.
11401       int numbers_seen = 0;
11402 
11403       // While c is not the EOF code point:
11404       while (pointer != input.end()) {
11405         // Let ipv4Piece be null.
11406         std::optional<uint16_t> ipv4_piece{};
11407 
11408         // If numbersSeen is greater than 0, then:
11409         if (numbers_seen > 0) {
11410           // If c is a U+002E (.) and numbersSeen is less than 4, then increase
11411           // pointer by 1.
11412           if (*pointer == '.' && numbers_seen < 4) {
11413             pointer++;
11414           }
11415           // Otherwise, validation error, return failure.
11416           else {
11417             ada_log("parse_ipv6 Otherwise, validation error, return failure");
11418             return is_valid = false;
11419           }
11420         }
11421 
11422         // If c is not an ASCII digit, validation error, return failure.
11423         if (pointer == input.end() || !checkers::is_digit(*pointer)) {
11424           ada_log(
11425               "parse_ipv6 If c is not an ASCII digit, validation error, return "
11426               "failure");
11427           return is_valid = false;
11428         }
11429 
11430         // While c is an ASCII digit:
11431         while (pointer != input.end() && checkers::is_digit(*pointer)) {
11432           // Let number be c interpreted as decimal number.
11433           int number = *pointer - '0';
11434 
11435           // If ipv4Piece is null, then set ipv4Piece to number.
11436           if (!ipv4_piece.has_value()) {
11437             ipv4_piece = number;
11438           }
11439           // Otherwise, if ipv4Piece is 0, validation error, return failure.
11440           else if (ipv4_piece == 0) {
11441             ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
11442             return is_valid = false;
11443           }
11444           // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
11445           else {
11446             ipv4_piece = *ipv4_piece * 10 + number;
11447           }
11448 
11449           // If ipv4Piece is greater than 255, validation error, return failure.
11450           if (ipv4_piece > 255) {
11451             ada_log("parse_ipv6 ipv4_piece > 255");
11452             return is_valid = false;
11453           }
11454 
11455           // Increase pointer by 1.
11456           pointer++;
11457         }
11458 
11459         // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
11460         // ipv4Piece.
11461         // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11462         address[piece_index] =
11463             uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
11464 
11465         // Increase numbersSeen by 1.
11466         numbers_seen++;
11467 
11468         // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
11469         if (numbers_seen == 2 || numbers_seen == 4) {
11470           piece_index++;
11471         }
11472       }
11473 
11474       // If numbersSeen is not 4, validation error, return failure.
11475       if (numbers_seen != 4) {
11476         return is_valid = false;
11477       }
11478 
11479       // Break.
11480       break;
11481     }
11482     // Otherwise, if c is U+003A (:):
11483     else if ((pointer != input.end()) && (*pointer == ':')) {
11484       // Increase pointer by 1.
11485       pointer++;
11486 
11487       // If c is the EOF code point, validation error, return failure.
11488       if (pointer == input.end()) {
11489         ada_log(
11490             "parse_ipv6 If c is the EOF code point, validation error, return "
11491             "failure");
11492         return is_valid = false;
11493       }
11494     }
11495     // Otherwise, if c is not the EOF code point, validation error, return
11496     // failure.
11497     else if (pointer != input.end()) {
11498       ada_log(
11499           "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
11500           "error, return failure");
11501       return is_valid = false;
11502     }
11503 
11504     // Set address[pieceIndex] to value.
11505     address[piece_index] = value;
11506 
11507     // Increase pieceIndex by 1.
11508     piece_index++;
11509   }
11510 
11511   // If compress is non-null, then:
11512   if (compress.has_value()) {
11513     // Let swaps be pieceIndex - compress.
11514     int swaps = piece_index - *compress;
11515 
11516     // Set pieceIndex to 7.
11517     piece_index = 7;
11518 
11519     // While pieceIndex is not 0 and swaps is greater than 0,
11520     // swap address[pieceIndex] with address[compress + swaps - 1], and then
11521     // decrease both pieceIndex and swaps by 1.
11522     while (piece_index != 0 && swaps > 0) {
11523       std::swap(address[piece_index], address[*compress + swaps - 1]);
11524       piece_index--;
11525       swaps--;
11526     }
11527   }
11528   // Otherwise, if compress is null and pieceIndex is not 8, validation error,
11529   // return failure.
11530   else if (piece_index != 8) {
11531     ada_log(
11532         "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
11533         "error, return failure");
11534     return is_valid = false;
11535   }
11536   host = ada::serializers::ipv6(address);
11537   ada_log("parse_ipv6 ", *host);
11538   host_type = IPV6;
11539   return true;
11540 }
11541 
11542 template <bool has_state_override>
parse_scheme(const std::string_view input)11543 ada_really_inline bool url::parse_scheme(const std::string_view input) {
11544   auto parsed_type = ada::scheme::get_scheme_type(input);
11545   bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11546   /**
11547    * In the common case, we will immediately recognize a special scheme (e.g.,
11548    *http, https), in which case, we can go really fast.
11549    **/
11550   if (is_input_special) {  // fast path!!!
11551     if (has_state_override) {
11552       // If url's scheme is not a special scheme and buffer is a special scheme,
11553       // then return.
11554       if (is_special() != is_input_special) {
11555         return true;
11556       }
11557 
11558       // If url includes credentials or has a non-null port, and buffer is
11559       // "file", then return.
11560       if ((has_credentials() || port.has_value()) &&
11561           parsed_type == ada::scheme::type::FILE) {
11562         return true;
11563       }
11564 
11565       // If url's scheme is "file" and its host is an empty host, then return.
11566       // An empty host is the empty string.
11567       if (type == ada::scheme::type::FILE && host.has_value() &&
11568           host.value().empty()) {
11569         return true;
11570       }
11571     }
11572 
11573     type = parsed_type;
11574 
11575     if (has_state_override) {
11576       // This is uncommon.
11577       uint16_t urls_scheme_port = get_special_port();
11578 
11579       if (urls_scheme_port) {
11580         // If url's port is url's scheme's default port, then set url's port to
11581         // null.
11582         if (port.has_value() && *port == urls_scheme_port) {
11583           port = std::nullopt;
11584         }
11585       }
11586     }
11587   } else {  // slow path
11588     std::string _buffer = std::string(input);
11589     // Next function is only valid if the input is ASCII and returns false
11590     // otherwise, but it seems that we always have ascii content so we do not
11591     // need to check the return value.
11592     // bool is_ascii =
11593     unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11594 
11595     if (has_state_override) {
11596       // If url's scheme is a special scheme and buffer is not a special scheme,
11597       // then return. If url's scheme is not a special scheme and buffer is a
11598       // special scheme, then return.
11599       if (is_special() != ada::scheme::is_special(_buffer)) {
11600         return true;
11601       }
11602 
11603       // If url includes credentials or has a non-null port, and buffer is
11604       // "file", then return.
11605       if ((has_credentials() || port.has_value()) && _buffer == "file") {
11606         return true;
11607       }
11608 
11609       // If url's scheme is "file" and its host is an empty host, then return.
11610       // An empty host is the empty string.
11611       if (type == ada::scheme::type::FILE && host.has_value() &&
11612           host.value().empty()) {
11613         return true;
11614       }
11615     }
11616 
11617     set_scheme(std::move(_buffer));
11618 
11619     if (has_state_override) {
11620       // This is uncommon.
11621       uint16_t urls_scheme_port = get_special_port();
11622 
11623       if (urls_scheme_port) {
11624         // If url's port is url's scheme's default port, then set url's port to
11625         // null.
11626         if (port.has_value() && *port == urls_scheme_port) {
11627           port = std::nullopt;
11628         }
11629       }
11630     }
11631   }
11632 
11633   return true;
11634 }
11635 
parse_host(std::string_view input)11636 ada_really_inline bool url::parse_host(std::string_view input) {
11637   ada_log("parse_host ", input, " [", input.size(), " bytes]");
11638   if (input.empty()) {
11639     return is_valid = false;
11640   }  // technically unnecessary.
11641   // If input starts with U+005B ([), then:
11642   if (input[0] == '[') {
11643     // If input does not end with U+005D (]), validation error, return failure.
11644     if (input.back() != ']') {
11645       return is_valid = false;
11646     }
11647     ada_log("parse_host ipv6");
11648 
11649     // Return the result of IPv6 parsing input with its leading U+005B ([) and
11650     // trailing U+005D (]) removed.
11651     input.remove_prefix(1);
11652     input.remove_suffix(1);
11653     return parse_ipv6(input);
11654   }
11655 
11656   // If isNotSpecial is true, then return the result of opaque-host parsing
11657   // input.
11658   if (!is_special()) {
11659     return parse_opaque_host(input);
11660   }
11661   // Let domain be the result of running UTF-8 decode without BOM on the
11662   // percent-decoding of input. Let asciiDomain be the result of running domain
11663   // to ASCII with domain and false. The most common case is an ASCII input, in
11664   // which case we do not need to call the expensive 'to_ascii' if a few
11665   // conditions are met: no '%' and no 'xn-' subsequence.
11666   std::string buffer = std::string(input);
11667   // This next function checks that the result is ascii, but we are going to
11668   // to check anyhow with is_forbidden.
11669   // bool is_ascii =
11670   unicode::to_lower_ascii(buffer.data(), buffer.size());
11671   bool is_forbidden = unicode::contains_forbidden_domain_code_point(
11672       buffer.data(), buffer.size());
11673   if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
11674     // fast path
11675     host = std::move(buffer);
11676     if (checkers::is_ipv4(host.value())) {
11677       ada_log("parse_host fast path ipv4");
11678       return parse_ipv4(host.value());
11679     }
11680     ada_log("parse_host fast path ", *host);
11681     return true;
11682   }
11683   ada_log("parse_host calling to_ascii");
11684   is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
11685   if (!is_valid) {
11686     ada_log("parse_host to_ascii returns false");
11687     return is_valid = false;
11688   }
11689   ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
11690           " bytes]");
11691 
11692   if (std::any_of(host.value().begin(), host.value().end(),
11693                   ada::unicode::is_forbidden_domain_code_point)) {
11694     host = std::nullopt;
11695     return is_valid = false;
11696   }
11697 
11698   // If asciiDomain ends in a number, then return the result of IPv4 parsing
11699   // asciiDomain.
11700   if (checkers::is_ipv4(host.value())) {
11701     ada_log("parse_host got ipv4 ", *host);
11702     return parse_ipv4(host.value());
11703   }
11704 
11705   return true;
11706 }
11707 
parse_path(std::string_view input)11708 ada_really_inline void url::parse_path(std::string_view input) {
11709   ada_log("parse_path ", input);
11710   std::string tmp_buffer;
11711   std::string_view internal_input;
11712   if (unicode::has_tabs_or_newline(input)) {
11713     tmp_buffer = input;
11714     // Optimization opportunity: Instead of copying and then pruning, we could
11715     // just directly build the string from user_input.
11716     helpers::remove_ascii_tab_or_newline(tmp_buffer);
11717     internal_input = tmp_buffer;
11718   } else {
11719     internal_input = input;
11720   }
11721 
11722   // If url is special, then:
11723   if (is_special()) {
11724     if (internal_input.empty()) {
11725       path = "/";
11726     } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11727       helpers::parse_prepared_path(internal_input.substr(1), type, path);
11728       return;
11729     } else {
11730       helpers::parse_prepared_path(internal_input, type, path);
11731       return;
11732     }
11733   } else if (!internal_input.empty()) {
11734     if (internal_input[0] == '/') {
11735       helpers::parse_prepared_path(internal_input.substr(1), type, path);
11736       return;
11737     } else {
11738       helpers::parse_prepared_path(internal_input, type, path);
11739       return;
11740     }
11741   } else {
11742     if (!host.has_value()) {
11743       path = "/";
11744     }
11745   }
11746 }
11747 
to_string() const11748 [[nodiscard]] std::string url::to_string() const {
11749   if (!is_valid) {
11750     return "null";
11751   }
11752   std::string answer;
11753   auto back = std::back_insert_iterator(answer);
11754   answer.append("{\n");
11755   answer.append("\t\"protocol\":\"");
11756   helpers::encode_json(get_protocol(), back);
11757   answer.append("\",\n");
11758   if (has_credentials()) {
11759     answer.append("\t\"username\":\"");
11760     helpers::encode_json(username, back);
11761     answer.append("\",\n");
11762     answer.append("\t\"password\":\"");
11763     helpers::encode_json(password, back);
11764     answer.append("\",\n");
11765   }
11766   if (host.has_value()) {
11767     answer.append("\t\"host\":\"");
11768     helpers::encode_json(host.value(), back);
11769     answer.append("\",\n");
11770   }
11771   if (port.has_value()) {
11772     answer.append("\t\"port\":\"");
11773     answer.append(std::to_string(port.value()));
11774     answer.append("\",\n");
11775   }
11776   answer.append("\t\"path\":\"");
11777   helpers::encode_json(path, back);
11778   answer.append("\",\n");
11779   answer.append("\t\"opaque path\":");
11780   answer.append((has_opaque_path ? "true" : "false"));
11781   if (has_search()) {
11782     answer.append(",\n");
11783     answer.append("\t\"query\":\"");
11784     helpers::encode_json(query.value(), back);
11785     answer.append("\"");
11786   }
11787   if (hash.has_value()) {
11788     answer.append(",\n");
11789     answer.append("\t\"hash\":\"");
11790     helpers::encode_json(hash.value(), back);
11791     answer.append("\"");
11792   }
11793   answer.append("\n}");
11794   return answer;
11795 }
11796 
has_valid_domain() const11797 [[nodiscard]] bool url::has_valid_domain() const noexcept {
11798   if (!host.has_value()) {
11799     return false;
11800   }
11801   return checkers::verify_dns_length(host.value());
11802 }
11803 
11804 }  // namespace ada
11805 /* end file src/url.cpp */
11806 /* begin file src/url-getters.cpp */
11807 /**
11808  * @file url-getters.cpp
11809  * Includes all the getters of `ada::url`
11810  */
11811 
11812 #include <algorithm>
11813 #include <string>
11814 
11815 namespace ada {
get_origin() const11816 [[nodiscard]] std::string url::get_origin() const noexcept {
11817   if (is_special()) {
11818     // Return a new opaque origin.
11819     if (type == scheme::FILE) {
11820       return "null";
11821     }
11822     return ada::helpers::concat(get_protocol(), "//", get_host());
11823   }
11824 
11825   if (non_special_scheme == "blob") {
11826     if (!path.empty()) {
11827       auto result = ada::parse<ada::url>(path);
11828       if (result &&
11829           (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
11830         // If pathURL's scheme is not "http" and not "https", then return a
11831         // new opaque origin.
11832         return ada::helpers::concat(result->get_protocol(), "//",
11833                                     result->get_host());
11834       }
11835     }
11836   }
11837 
11838   // Return a new opaque origin.
11839   return "null";
11840 }
11841 
get_protocol() const11842 [[nodiscard]] std::string url::get_protocol() const noexcept {
11843   if (is_special()) {
11844     return helpers::concat(ada::scheme::details::is_special_list[type], ":");
11845   }
11846   // We only move the 'scheme' if it is non-special.
11847   return helpers::concat(non_special_scheme, ":");
11848 }
11849 
get_host() const11850 [[nodiscard]] std::string url::get_host() const noexcept {
11851   // If url's host is null, then return the empty string.
11852   // If url's port is null, return url's host, serialized.
11853   // Return url's host, serialized, followed by U+003A (:) and url's port,
11854   // serialized.
11855   if (!host.has_value()) {
11856     return "";
11857   }
11858   if (port.has_value()) {
11859     return host.value() + ":" + get_port();
11860   }
11861   return host.value();
11862 }
11863 
get_hostname() const11864 [[nodiscard]] std::string url::get_hostname() const noexcept {
11865   return host.value_or("");
11866 }
11867 
get_pathname() const11868 [[nodiscard]] std::string_view url::get_pathname() const noexcept {
11869   return path;
11870 }
11871 
get_search() const11872 [[nodiscard]] std::string url::get_search() const noexcept {
11873   // If this's URL's query is either null or the empty string, then return the
11874   // empty string. Return U+003F (?), followed by this's URL's query.
11875   return (!query.has_value() || (query.value().empty())) ? ""
11876                                                          : "?" + query.value();
11877 }
11878 
get_username() const11879 [[nodiscard]] const std::string& url::get_username() const noexcept {
11880   return username;
11881 }
11882 
get_password() const11883 [[nodiscard]] const std::string& url::get_password() const noexcept {
11884   return password;
11885 }
11886 
get_port() const11887 [[nodiscard]] std::string url::get_port() const noexcept {
11888   return port.has_value() ? std::to_string(port.value()) : "";
11889 }
11890 
get_hash() const11891 [[nodiscard]] std::string url::get_hash() const noexcept {
11892   // If this's URL's fragment is either null or the empty string, then return
11893   // the empty string. Return U+0023 (#), followed by this's URL's fragment.
11894   return (!hash.has_value() || (hash.value().empty())) ? ""
11895                                                        : "#" + hash.value();
11896 }
11897 
11898 }  // namespace ada
11899 /* end file src/url-getters.cpp */
11900 /* begin file src/url-setters.cpp */
11901 /**
11902  * @file url-setters.cpp
11903  * Includes all the setters of `ada::url`
11904  */
11905 
11906 #include <optional>
11907 #include <string>
11908 
11909 namespace ada {
11910 
11911 template <bool override_hostname>
set_host_or_hostname(const std::string_view input)11912 bool url::set_host_or_hostname(const std::string_view input) {
11913   if (has_opaque_path) {
11914     return false;
11915   }
11916 
11917   std::optional<std::string> previous_host = host;
11918   std::optional<uint16_t> previous_port = port;
11919 
11920   size_t host_end_pos = input.find('#');
11921   std::string _host(input.data(), host_end_pos != std::string_view::npos
11922                                       ? host_end_pos
11923                                       : input.size());
11924   helpers::remove_ascii_tab_or_newline(_host);
11925   std::string_view new_host(_host);
11926 
11927   // If url's scheme is "file", then set state to file host state, instead of
11928   // host state.
11929   if (type != ada::scheme::type::FILE) {
11930     std::string_view host_view(_host.data(), _host.length());
11931     auto [location, found_colon] =
11932         helpers::get_host_delimiter_location(is_special(), host_view);
11933 
11934     // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11935     // Note: the 'found_colon' value is true if and only if a colon was
11936     // encountered while not inside brackets.
11937     if (found_colon) {
11938       if (override_hostname) {
11939         return false;
11940       }
11941       std::string_view buffer = new_host.substr(location + 1);
11942       if (!buffer.empty()) {
11943         set_port(buffer);
11944       }
11945     }
11946     // If url is special and host_view is the empty string, validation error,
11947     // return failure. Otherwise, if state override is given, host_view is the
11948     // empty string, and either url includes credentials or url's port is
11949     // non-null, return.
11950     else if (host_view.empty() &&
11951              (is_special() || has_credentials() || port.has_value())) {
11952       return false;
11953     }
11954 
11955     // Let host be the result of host parsing host_view with url is not special.
11956     if (host_view.empty() && !is_special()) {
11957       host = "";
11958       return true;
11959     }
11960 
11961     bool succeeded = parse_host(host_view);
11962     if (!succeeded) {
11963       host = previous_host;
11964       update_base_port(previous_port);
11965     }
11966     return succeeded;
11967   }
11968 
11969   size_t location = new_host.find_first_of("/\\?");
11970   if (location != std::string_view::npos) {
11971     new_host.remove_suffix(new_host.length() - location);
11972   }
11973 
11974   if (new_host.empty()) {
11975     // Set url's host to the empty string.
11976     host = "";
11977   } else {
11978     // Let host be the result of host parsing buffer with url is not special.
11979     if (!parse_host(new_host)) {
11980       host = previous_host;
11981       update_base_port(previous_port);
11982       return false;
11983     }
11984 
11985     // If host is "localhost", then set host to the empty string.
11986     if (host.has_value() && host.value() == "localhost") {
11987       host = "";
11988     }
11989   }
11990   return true;
11991 }
11992 
set_host(const std::string_view input)11993 bool url::set_host(const std::string_view input) {
11994   return set_host_or_hostname<false>(input);
11995 }
11996 
set_hostname(const std::string_view input)11997 bool url::set_hostname(const std::string_view input) {
11998   return set_host_or_hostname<true>(input);
11999 }
12000 
set_username(const std::string_view input)12001 bool url::set_username(const std::string_view input) {
12002   if (cannot_have_credentials_or_port()) {
12003     return false;
12004   }
12005   username = ada::unicode::percent_encode(
12006       input, character_sets::USERINFO_PERCENT_ENCODE);
12007   return true;
12008 }
12009 
set_password(const std::string_view input)12010 bool url::set_password(const std::string_view input) {
12011   if (cannot_have_credentials_or_port()) {
12012     return false;
12013   }
12014   password = ada::unicode::percent_encode(
12015       input, character_sets::USERINFO_PERCENT_ENCODE);
12016   return true;
12017 }
12018 
set_port(const std::string_view input)12019 bool url::set_port(const std::string_view input) {
12020   if (cannot_have_credentials_or_port()) {
12021     return false;
12022   }
12023   std::string trimmed(input);
12024   helpers::remove_ascii_tab_or_newline(trimmed);
12025   if (trimmed.empty()) {
12026     port = std::nullopt;
12027     return true;
12028   }
12029   // Input should not start with control characters.
12030   if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
12031     return false;
12032   }
12033   // Input should contain at least one ascii digit.
12034   if (input.find_first_of("0123456789") == std::string_view::npos) {
12035     return false;
12036   }
12037 
12038   // Revert changes if parse_port fails.
12039   std::optional<uint16_t> previous_port = port;
12040   parse_port(trimmed);
12041   if (is_valid) {
12042     return true;
12043   }
12044   port = previous_port;
12045   is_valid = true;
12046   return false;
12047 }
12048 
set_hash(const std::string_view input)12049 void url::set_hash(const std::string_view input) {
12050   if (input.empty()) {
12051     hash = std::nullopt;
12052     helpers::strip_trailing_spaces_from_opaque_path(*this);
12053     return;
12054   }
12055 
12056   std::string new_value;
12057   new_value = input[0] == '#' ? input.substr(1) : input;
12058   helpers::remove_ascii_tab_or_newline(new_value);
12059   hash = unicode::percent_encode(new_value,
12060                                  ada::character_sets::FRAGMENT_PERCENT_ENCODE);
12061   return;
12062 }
12063 
set_search(const std::string_view input)12064 void url::set_search(const std::string_view input) {
12065   if (input.empty()) {
12066     query = std::nullopt;
12067     helpers::strip_trailing_spaces_from_opaque_path(*this);
12068     return;
12069   }
12070 
12071   std::string new_value;
12072   new_value = input[0] == '?' ? input.substr(1) : input;
12073   helpers::remove_ascii_tab_or_newline(new_value);
12074 
12075   auto query_percent_encode_set =
12076       is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12077                    : ada::character_sets::QUERY_PERCENT_ENCODE;
12078 
12079   query = ada::unicode::percent_encode(std::string_view(new_value),
12080                                        query_percent_encode_set);
12081 }
12082 
set_pathname(const std::string_view input)12083 bool url::set_pathname(const std::string_view input) {
12084   if (has_opaque_path) {
12085     return false;
12086   }
12087   path = "";
12088   parse_path(input);
12089   return true;
12090 }
12091 
set_protocol(const std::string_view input)12092 bool url::set_protocol(const std::string_view input) {
12093   std::string view(input);
12094   helpers::remove_ascii_tab_or_newline(view);
12095   if (view.empty()) {
12096     return true;
12097   }
12098 
12099   // Schemes should start with alpha values.
12100   if (!checkers::is_alpha(view[0])) {
12101     return false;
12102   }
12103 
12104   view.append(":");
12105 
12106   std::string::iterator pointer =
12107       std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
12108 
12109   if (pointer != view.end() && *pointer == ':') {
12110     return parse_scheme<true>(
12111         std::string_view(view.data(), pointer - view.begin()));
12112   }
12113   return false;
12114 }
12115 
set_href(const std::string_view input)12116 bool url::set_href(const std::string_view input) {
12117   ada::result<ada::url> out = ada::parse<ada::url>(input);
12118 
12119   if (out) {
12120     username = out->username;
12121     password = out->password;
12122     host = out->host;
12123     port = out->port;
12124     path = out->path;
12125     query = out->query;
12126     hash = out->hash;
12127     type = out->type;
12128     non_special_scheme = out->non_special_scheme;
12129     has_opaque_path = out->has_opaque_path;
12130   }
12131 
12132   return out.has_value();
12133 }
12134 
12135 }  // namespace ada
12136 /* end file src/url-setters.cpp */
12137 /* begin file src/parser.cpp */
12138 
12139 #include <numeric>
12140 #include <limits>
12141 
12142 namespace ada::parser {
12143 
12144 template <class result_type>
parse_url(std::string_view user_input,const result_type * base_url)12145 result_type parse_url(std::string_view user_input,
12146                       const result_type* base_url) {
12147   // We can specialize the implementation per type.
12148   // Important: result_type_is_ada_url is evaluated at *compile time*. This
12149   // means that doing if constexpr(result_type_is_ada_url) { something } else {
12150   // something else } is free (at runtime). This means that ada::url_aggregator
12151   // and ada::url **do not have to support the exact same API**.
12152   constexpr bool result_type_is_ada_url =
12153       std::is_same<ada::url, result_type>::value;
12154   constexpr bool result_type_is_ada_url_aggregator =
12155       std::is_same<ada::url_aggregator, result_type>::value;
12156   static_assert(result_type_is_ada_url ||
12157                 result_type_is_ada_url_aggregator);  // We don't support
12158                                                      // anything else for now.
12159 
12160   ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12161           " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12162           ")");
12163 
12164   ada::state state = ada::state::SCHEME_START;
12165   result_type url{};
12166 
12167   // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12168   // surely the result of a bug or are otherwise a security concern.
12169   if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12170     url.is_valid = false;
12171   }
12172   // Going forward, user_input.size() is in [0,
12173   // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12174   // base, or the optional_url was invalid, we must return.
12175   if (base_url != nullptr) {
12176     url.is_valid &= base_url->is_valid;
12177   }
12178   if (!url.is_valid) {
12179     return url;
12180   }
12181   if constexpr (result_type_is_ada_url_aggregator) {
12182     // Most of the time, we just need user_input.size().
12183     // In some instances, we may need a bit more.
12184     ///////////////////////////
12185     // This is *very* important. This line should *not* be removed
12186     // hastily. There are principled reasons why reserve is important
12187     // for performance. If you have a benchmark with small inputs,
12188     // it may not matter, but in other instances, it could.
12189     ////
12190     // This rounds up to the next power of two.
12191     // We know that user_input.size() is in [0,
12192     // std::numeric_limits<uint32_t>::max).
12193     uint32_t reserve_capacity =
12194         (0xFFFFFFFF >>
12195          helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12196         1;
12197     url.reserve(reserve_capacity);
12198     //
12199     //
12200     //
12201   }
12202   std::string tmp_buffer;
12203   std::string_view internal_input;
12204   if (unicode::has_tabs_or_newline(user_input)) {
12205     tmp_buffer = user_input;
12206     // Optimization opportunity: Instead of copying and then pruning, we could
12207     // just directly build the string from user_input.
12208     helpers::remove_ascii_tab_or_newline(tmp_buffer);
12209     internal_input = tmp_buffer;
12210   } else {
12211     internal_input = user_input;
12212   }
12213 
12214   // Leading and trailing control characters are uncommon and easy to deal with
12215   // (no performance concern).
12216   std::string_view url_data = internal_input;
12217   helpers::trim_c0_whitespace(url_data);
12218 
12219   // Optimization opportunity. Most websites do not have fragment.
12220   std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12221   // We add it last so that an implementation like ada::url_aggregator
12222   // can append it last to its internal buffer, thus improving performance.
12223 
12224   // Here url_data no longer has its fragment.
12225   // We are going to access the data from url_data (it is immutable).
12226   // At any given time, we are pointing at byte 'input_position' in url_data.
12227   // The input_position variable should range from 0 to input_size.
12228   // It is illegal to access url_data at input_size.
12229   size_t input_position = 0;
12230   const size_t input_size = url_data.size();
12231   // Keep running the following state machine by switching on state.
12232   // If after a run pointer points to the EOF code point, go to the next step.
12233   // Otherwise, increase pointer by 1 and continue with the state machine.
12234   // We never decrement input_position.
12235   while (input_position <= input_size) {
12236     ada_log("In parsing at ", input_position, " out of ", input_size,
12237             " in state ", ada::to_string(state));
12238     switch (state) {
12239       case ada::state::SCHEME_START: {
12240         ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12241         // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12242         // state to scheme state.
12243         if ((input_position != input_size) &&
12244             checkers::is_alpha(url_data[input_position])) {
12245           state = ada::state::SCHEME;
12246           input_position++;
12247         } else {
12248           // Otherwise, if state override is not given, set state to no scheme
12249           // state and decrease pointer by 1.
12250           state = ada::state::NO_SCHEME;
12251         }
12252         break;
12253       }
12254       case ada::state::SCHEME: {
12255         ada_log("SCHEME ", helpers::substring(url_data, input_position));
12256         // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12257         // append c, lowercased, to buffer.
12258         while ((input_position != input_size) &&
12259                (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12260           input_position++;
12261         }
12262         // Otherwise, if c is U+003A (:), then:
12263         if ((input_position != input_size) &&
12264             (url_data[input_position] == ':')) {
12265           ada_log("SCHEME the scheme should be ",
12266                   url_data.substr(0, input_position));
12267           if constexpr (result_type_is_ada_url) {
12268             if (!url.parse_scheme(url_data.substr(0, input_position))) {
12269               return url;
12270             }
12271           } else {
12272             // we pass the colon along instead of painfully adding it back.
12273             if (!url.parse_scheme_with_colon(
12274                     url_data.substr(0, input_position + 1))) {
12275               return url;
12276             }
12277           }
12278           ada_log("SCHEME the scheme is ", url.get_protocol());
12279 
12280           // If url's scheme is "file", then:
12281           if (url.type == ada::scheme::type::FILE) {
12282             // Set state to file state.
12283             state = ada::state::FILE;
12284           }
12285           // Otherwise, if url is special, base is non-null, and base's scheme
12286           // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12287           // != nullptr is false.
12288           else if (url.is_special() && base_url != nullptr &&
12289                    base_url->type == url.type) {
12290             // Set state to special relative or authority state.
12291             state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12292           }
12293           // Otherwise, if url is special, set state to special authority
12294           // slashes state.
12295           else if (url.is_special()) {
12296             state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12297           }
12298           // Otherwise, if remaining starts with an U+002F (/), set state to
12299           // path or authority state and increase pointer by 1.
12300           else if (input_position + 1 < input_size &&
12301                    url_data[input_position + 1] == '/') {
12302             state = ada::state::PATH_OR_AUTHORITY;
12303             input_position++;
12304           }
12305           // Otherwise, set url's path to the empty string and set state to
12306           // opaque path state.
12307           else {
12308             state = ada::state::OPAQUE_PATH;
12309           }
12310         }
12311         // Otherwise, if state override is not given, set buffer to the empty
12312         // string, state to no scheme state, and start over (from the first code
12313         // point in input).
12314         else {
12315           state = ada::state::NO_SCHEME;
12316           input_position = 0;
12317           break;
12318         }
12319         input_position++;
12320         break;
12321       }
12322       case ada::state::NO_SCHEME: {
12323         ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12324         // If base is null, or base has an opaque path and c is not U+0023 (#),
12325         // validation error, return failure.
12326         if (base_url == nullptr ||
12327             (base_url->has_opaque_path && !fragment.has_value())) {
12328           ada_log("NO_SCHEME validation error");
12329           url.is_valid = false;
12330           return url;
12331         }
12332         // Otherwise, if base has an opaque path and c is U+0023 (#),
12333         // set url's scheme to base's scheme, url's path to base's path, url's
12334         // query to base's query, and set state to fragment state.
12335         else if (base_url->has_opaque_path && fragment.has_value() &&
12336                  input_position == input_size) {
12337           ada_log("NO_SCHEME opaque base with fragment");
12338           url.copy_scheme(*base_url);
12339           url.has_opaque_path = base_url->has_opaque_path;
12340 
12341           if constexpr (result_type_is_ada_url) {
12342             url.path = base_url->path;
12343             url.query = base_url->query;
12344           } else {
12345             url.update_base_pathname(base_url->get_pathname());
12346             url.update_base_search(base_url->get_search());
12347           }
12348           url.update_unencoded_base_hash(*fragment);
12349           return url;
12350         }
12351         // Otherwise, if base's scheme is not "file", set state to relative
12352         // state and decrease pointer by 1.
12353         else if (base_url->type != ada::scheme::type::FILE) {
12354           ada_log("NO_SCHEME non-file relative path");
12355           state = ada::state::RELATIVE_SCHEME;
12356         }
12357         // Otherwise, set state to file state and decrease pointer by 1.
12358         else {
12359           ada_log("NO_SCHEME file base type");
12360           state = ada::state::FILE;
12361         }
12362         break;
12363       }
12364       case ada::state::AUTHORITY: {
12365         ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12366         // most URLs have no @. Having no @ tells us that we don't have to worry
12367         // about AUTHORITY. Of course, we could have @ and still not have to
12368         // worry about AUTHORITY.
12369         // TODO: Instead of just collecting a bool, collect the location of the
12370         // '@' and do something useful with it.
12371         // TODO: We could do various processing early on, using a single pass
12372         // over the string to collect information about it, e.g., telling us
12373         // whether there is a @ and if so, where (or how many).
12374         const bool contains_ampersand =
12375             (url_data.find('@', input_position) != std::string_view::npos);
12376 
12377         if (!contains_ampersand) {
12378           state = ada::state::HOST;
12379           break;
12380         }
12381         bool at_sign_seen{false};
12382         bool password_token_seen{false};
12383         /**
12384          * We expect something of the sort...
12385          * https://user:pass@example.com:1234/foo/bar?baz#quux
12386          * --------^
12387          */
12388         do {
12389           std::string_view view = helpers::substring(url_data, input_position);
12390           // The delimiters are @, /, ? \\.
12391           size_t location =
12392               url.is_special() ? helpers::find_authority_delimiter_special(view)
12393                                : helpers::find_authority_delimiter(view);
12394           std::string_view authority_view(view.data(), location);
12395           size_t end_of_authority = input_position + authority_view.size();
12396           // If c is U+0040 (@), then:
12397           if ((end_of_authority != input_size) &&
12398               (url_data[end_of_authority] == '@')) {
12399             // If atSignSeen is true, then prepend "%40" to buffer.
12400             if (at_sign_seen) {
12401               if (password_token_seen) {
12402                 if constexpr (result_type_is_ada_url) {
12403                   url.password += "%40";
12404                 } else {
12405                   url.append_base_password("%40");
12406                 }
12407               } else {
12408                 if constexpr (result_type_is_ada_url) {
12409                   url.username += "%40";
12410                 } else {
12411                   url.append_base_username("%40");
12412                 }
12413               }
12414             }
12415 
12416             at_sign_seen = true;
12417 
12418             if (!password_token_seen) {
12419               size_t password_token_location = authority_view.find(':');
12420               password_token_seen =
12421                   password_token_location != std::string_view::npos;
12422 
12423               if (!password_token_seen) {
12424                 if constexpr (result_type_is_ada_url) {
12425                   url.username += unicode::percent_encode(
12426                       authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12427                 } else {
12428                   url.append_base_username(unicode::percent_encode(
12429                       authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12430                 }
12431               } else {
12432                 if constexpr (result_type_is_ada_url) {
12433                   url.username += unicode::percent_encode(
12434                       authority_view.substr(0, password_token_location),
12435                       character_sets::USERINFO_PERCENT_ENCODE);
12436                   url.password += unicode::percent_encode(
12437                       authority_view.substr(password_token_location + 1),
12438                       character_sets::USERINFO_PERCENT_ENCODE);
12439                 } else {
12440                   url.append_base_username(unicode::percent_encode(
12441                       authority_view.substr(0, password_token_location),
12442                       character_sets::USERINFO_PERCENT_ENCODE));
12443                   url.append_base_password(unicode::percent_encode(
12444                       authority_view.substr(password_token_location + 1),
12445                       character_sets::USERINFO_PERCENT_ENCODE));
12446                 }
12447               }
12448             } else {
12449               if constexpr (result_type_is_ada_url) {
12450                 url.password += unicode::percent_encode(
12451                     authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12452               } else {
12453                 url.append_base_password(unicode::percent_encode(
12454                     authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12455               }
12456             }
12457           }
12458           // Otherwise, if one of the following is true:
12459           // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12460           // - url is special and c is U+005C (\)
12461           else if (end_of_authority == input_size ||
12462                    url_data[end_of_authority] == '/' ||
12463                    url_data[end_of_authority] == '?' ||
12464                    (url.is_special() && url_data[end_of_authority] == '\\')) {
12465             // If atSignSeen is true and authority_view is the empty string,
12466             // validation error, return failure.
12467             if (at_sign_seen && authority_view.empty()) {
12468               url.is_valid = false;
12469               return url;
12470             }
12471             state = ada::state::HOST;
12472             break;
12473           }
12474           if (end_of_authority == input_size) {
12475             if (fragment.has_value()) {
12476               url.update_unencoded_base_hash(*fragment);
12477             }
12478             return url;
12479           }
12480           input_position = end_of_authority + 1;
12481         } while (true);
12482 
12483         break;
12484       }
12485       case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12486         ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12487                 helpers::substring(url_data, input_position));
12488 
12489         // If c is U+002F (/) and remaining starts with U+002F (/),
12490         // then set state to special authority ignore slashes state and increase
12491         // pointer by 1.
12492         std::string_view view = helpers::substring(url_data, input_position);
12493         if (ada::checkers::begins_with(view, "//")) {
12494           state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12495           input_position += 2;
12496         } else {
12497           // Otherwise, validation error, set state to relative state and
12498           // decrease pointer by 1.
12499           state = ada::state::RELATIVE_SCHEME;
12500         }
12501 
12502         break;
12503       }
12504       case ada::state::PATH_OR_AUTHORITY: {
12505         ada_log("PATH_OR_AUTHORITY ",
12506                 helpers::substring(url_data, input_position));
12507 
12508         // If c is U+002F (/), then set state to authority state.
12509         if ((input_position != input_size) &&
12510             (url_data[input_position] == '/')) {
12511           state = ada::state::AUTHORITY;
12512           input_position++;
12513         } else {
12514           // Otherwise, set state to path state, and decrease pointer by 1.
12515           state = ada::state::PATH;
12516         }
12517 
12518         break;
12519       }
12520       case ada::state::RELATIVE_SCHEME: {
12521         ada_log("RELATIVE_SCHEME ",
12522                 helpers::substring(url_data, input_position));
12523 
12524         // Set url's scheme to base's scheme.
12525         url.copy_scheme(*base_url);
12526 
12527         // If c is U+002F (/), then set state to relative slash state.
12528         if ((input_position != input_size) &&
12529             (url_data[input_position] == '/')) {
12530           ada_log(
12531               "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12532               "slash state");
12533           state = ada::state::RELATIVE_SLASH;
12534         } else if (url.is_special() && (input_position != input_size) &&
12535                    (url_data[input_position] == '\\')) {
12536           // Otherwise, if url is special and c is U+005C (\), validation error,
12537           // set state to relative slash state.
12538           ada_log(
12539               "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12540               "error, set state to relative slash state");
12541           state = ada::state::RELATIVE_SLASH;
12542         } else {
12543           ada_log("RELATIVE_SCHEME otherwise");
12544           // Set url's username to base's username, url's password to base's
12545           // password, url's host to base's host, url's port to base's port,
12546           // url's path to a clone of base's path, and url's query to base's
12547           // query.
12548           if constexpr (result_type_is_ada_url) {
12549             url.username = base_url->username;
12550             url.password = base_url->password;
12551             url.host = base_url->host;
12552             url.port = base_url->port;
12553             // cloning the base path includes cloning the has_opaque_path flag
12554             url.has_opaque_path = base_url->has_opaque_path;
12555             url.path = base_url->path;
12556             url.query = base_url->query;
12557           } else {
12558             url.update_base_authority(base_url->get_href(),
12559                                       base_url->get_components());
12560             // TODO: Get rid of set_hostname and replace it with
12561             // update_base_hostname
12562             url.set_hostname(base_url->get_hostname());
12563             url.update_base_port(base_url->retrieve_base_port());
12564             // cloning the base path includes cloning the has_opaque_path flag
12565             url.has_opaque_path = base_url->has_opaque_path;
12566             url.update_base_pathname(base_url->get_pathname());
12567             url.update_base_search(base_url->get_search());
12568           }
12569 
12570           url.has_opaque_path = base_url->has_opaque_path;
12571 
12572           // If c is U+003F (?), then set url's query to the empty string, and
12573           // state to query state.
12574           if ((input_position != input_size) &&
12575               (url_data[input_position] == '?')) {
12576             state = ada::state::QUERY;
12577           }
12578           // Otherwise, if c is not the EOF code point:
12579           else if (input_position != input_size) {
12580             // Set url's query to null.
12581             url.clear_search();
12582             if constexpr (result_type_is_ada_url) {
12583               // Shorten url's path.
12584               helpers::shorten_path(url.path, url.type);
12585             } else {
12586               std::string_view path = url.get_pathname();
12587               if (helpers::shorten_path(path, url.type)) {
12588                 url.update_base_pathname(std::string(path));
12589               }
12590             }
12591             // Set state to path state and decrease pointer by 1.
12592             state = ada::state::PATH;
12593             break;
12594           }
12595         }
12596         input_position++;
12597         break;
12598       }
12599       case ada::state::RELATIVE_SLASH: {
12600         ada_log("RELATIVE_SLASH ",
12601                 helpers::substring(url_data, input_position));
12602 
12603         // If url is special and c is U+002F (/) or U+005C (\), then:
12604         if (url.is_special() && (input_position != input_size) &&
12605             (url_data[input_position] == '/' ||
12606              url_data[input_position] == '\\')) {
12607           // Set state to special authority ignore slashes state.
12608           state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12609         }
12610         // Otherwise, if c is U+002F (/), then set state to authority state.
12611         else if ((input_position != input_size) &&
12612                  (url_data[input_position] == '/')) {
12613           state = ada::state::AUTHORITY;
12614         }
12615         // Otherwise, set
12616         // - url's username to base's username,
12617         // - url's password to base's password,
12618         // - url's host to base's host,
12619         // - url's port to base's port,
12620         // - state to path state, and then, decrease pointer by 1.
12621         else {
12622           if constexpr (result_type_is_ada_url) {
12623             url.username = base_url->username;
12624             url.password = base_url->password;
12625             url.host = base_url->host;
12626             url.port = base_url->port;
12627           } else {
12628             url.update_base_authority(base_url->get_href(),
12629                                       base_url->get_components());
12630             // TODO: Get rid of set_hostname and replace it with
12631             // update_base_hostname
12632             url.set_hostname(base_url->get_hostname());
12633             url.update_base_port(base_url->retrieve_base_port());
12634           }
12635           state = ada::state::PATH;
12636           break;
12637         }
12638 
12639         input_position++;
12640         break;
12641       }
12642       case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12643         ada_log("SPECIAL_AUTHORITY_SLASHES ",
12644                 helpers::substring(url_data, input_position));
12645 
12646         // If c is U+002F (/) and remaining starts with U+002F (/),
12647         // then set state to special authority ignore slashes state and increase
12648         // pointer by 1.
12649         std::string_view view = helpers::substring(url_data, input_position);
12650         if (ada::checkers::begins_with(view, "//")) {
12651           input_position += 2;
12652         }
12653 
12654         [[fallthrough]];
12655       }
12656       case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12657         ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12658                 helpers::substring(url_data, input_position));
12659 
12660         // If c is neither U+002F (/) nor U+005C (\), then set state to
12661         // authority state and decrease pointer by 1.
12662         while ((input_position != input_size) &&
12663                ((url_data[input_position] == '/') ||
12664                 (url_data[input_position] == '\\'))) {
12665           input_position++;
12666         }
12667         state = ada::state::AUTHORITY;
12668 
12669         break;
12670       }
12671       case ada::state::QUERY: {
12672         ada_log("QUERY ", helpers::substring(url_data, input_position));
12673         // Let queryPercentEncodeSet be the special-query percent-encode set if
12674         // url is special; otherwise the query percent-encode set.
12675         const uint8_t* query_percent_encode_set =
12676             url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12677                              : ada::character_sets::QUERY_PERCENT_ENCODE;
12678 
12679         // Percent-encode after encoding, with encoding, buffer, and
12680         // queryPercentEncodeSet, and append the result to url's query.
12681         url.update_base_search(helpers::substring(url_data, input_position),
12682                                query_percent_encode_set);
12683         ada_log("QUERY update_base_search completed ");
12684         if (fragment.has_value()) {
12685           url.update_unencoded_base_hash(*fragment);
12686         }
12687         return url;
12688       }
12689       case ada::state::HOST: {
12690         ada_log("HOST ", helpers::substring(url_data, input_position));
12691 
12692         std::string_view host_view =
12693             helpers::substring(url_data, input_position);
12694         auto [location, found_colon] =
12695             helpers::get_host_delimiter_location(url.is_special(), host_view);
12696         input_position = (location != std::string_view::npos)
12697                              ? input_position + location
12698                              : input_size;
12699         // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12700         // Note: the 'found_colon' value is true if and only if a colon was
12701         // encountered while not inside brackets.
12702         if (found_colon) {
12703           // If buffer is the empty string, validation error, return failure.
12704           // Let host be the result of host parsing buffer with url is not
12705           // special.
12706           ada_log("HOST parsing ", host_view);
12707           if (!url.parse_host(host_view)) {
12708             return url;
12709           }
12710           ada_log("HOST parsing results in ", url.get_hostname());
12711           // Set url's host to host, buffer to the empty string, and state to
12712           // port state.
12713           state = ada::state::PORT;
12714           input_position++;
12715         }
12716         // Otherwise, if one of the following is true:
12717         // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12718         // - url is special and c is U+005C (\)
12719         // The get_host_delimiter_location function either brings us to
12720         // the colon outside of the bracket, or to one of those characters.
12721         else {
12722           // If url is special and host_view is the empty string, validation
12723           // error, return failure.
12724           if (url.is_special() && host_view.empty()) {
12725             url.is_valid = false;
12726             return url;
12727           }
12728           ada_log("HOST parsing ", host_view, " href=", url.get_href());
12729           // Let host be the result of host parsing host_view with url is not
12730           // special.
12731           if (host_view.empty()) {
12732             url.update_base_hostname("");
12733           } else if (!url.parse_host(host_view)) {
12734             return url;
12735           }
12736           ada_log("HOST parsing results in ", url.get_hostname(),
12737                   " href=", url.get_href());
12738 
12739           // Set url's host to host, and state to path start state.
12740           state = ada::state::PATH_START;
12741         }
12742 
12743         break;
12744       }
12745       case ada::state::OPAQUE_PATH: {
12746         ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12747         std::string_view view = helpers::substring(url_data, input_position);
12748         // If c is U+003F (?), then set url's query to the empty string and
12749         // state to query state.
12750         size_t location = view.find('?');
12751         if (location != std::string_view::npos) {
12752           view.remove_suffix(view.size() - location);
12753           state = ada::state::QUERY;
12754           input_position += location + 1;
12755         } else {
12756           input_position = input_size + 1;
12757         }
12758         url.has_opaque_path = true;
12759         // This is a really unlikely scenario in real world. We should not seek
12760         // to optimize it.
12761         url.update_base_pathname(unicode::percent_encode(
12762             view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12763         break;
12764       }
12765       case ada::state::PORT: {
12766         ada_log("PORT ", helpers::substring(url_data, input_position));
12767         std::string_view port_view =
12768             helpers::substring(url_data, input_position);
12769         size_t consumed_bytes = url.parse_port(port_view, true);
12770         input_position += consumed_bytes;
12771         if (!url.is_valid) {
12772           return url;
12773         }
12774         state = state::PATH_START;
12775         [[fallthrough]];
12776       }
12777       case ada::state::PATH_START: {
12778         ada_log("PATH_START ", helpers::substring(url_data, input_position));
12779 
12780         // If url is special, then:
12781         if (url.is_special()) {
12782           // Set state to path state.
12783           state = ada::state::PATH;
12784 
12785           // Optimization: Avoiding going into PATH state improves the
12786           // performance of urls ending with /.
12787           if (input_position == input_size) {
12788             url.update_base_pathname("/");
12789             if (fragment.has_value()) {
12790               url.update_unencoded_base_hash(*fragment);
12791             }
12792             return url;
12793           }
12794           // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12795           // by 1. We know that (input_position == input_size) is impossible
12796           // here, because of the previous if-check.
12797           if ((url_data[input_position] != '/') &&
12798               (url_data[input_position] != '\\')) {
12799             break;
12800           }
12801         }
12802         // Otherwise, if state override is not given and c is U+003F (?),
12803         // set url's query to the empty string and state to query state.
12804         else if ((input_position != input_size) &&
12805                  (url_data[input_position] == '?')) {
12806           state = ada::state::QUERY;
12807         }
12808         // Otherwise, if c is not the EOF code point:
12809         else if (input_position != input_size) {
12810           // Set state to path state.
12811           state = ada::state::PATH;
12812 
12813           // If c is not U+002F (/), then decrease pointer by 1.
12814           if (url_data[input_position] != '/') {
12815             break;
12816           }
12817         }
12818 
12819         input_position++;
12820         break;
12821       }
12822       case ada::state::PATH: {
12823         std::string_view view = helpers::substring(url_data, input_position);
12824         ada_log("PATH ", helpers::substring(url_data, input_position));
12825 
12826         // Most time, we do not need percent encoding.
12827         // Furthermore, we can immediately locate the '?'.
12828         size_t locofquestionmark = view.find('?');
12829         if (locofquestionmark != std::string_view::npos) {
12830           state = ada::state::QUERY;
12831           view.remove_suffix(view.size() - locofquestionmark);
12832           input_position += locofquestionmark + 1;
12833         } else {
12834           input_position = input_size + 1;
12835         }
12836         if constexpr (result_type_is_ada_url) {
12837           helpers::parse_prepared_path(view, url.type, url.path);
12838         } else {
12839           url.consume_prepared_path(view);
12840           ADA_ASSERT_TRUE(url.validate());
12841         }
12842         break;
12843       }
12844       case ada::state::FILE_SLASH: {
12845         ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12846 
12847         // If c is U+002F (/) or U+005C (\), then:
12848         if ((input_position != input_size) &&
12849             (url_data[input_position] == '/' ||
12850              url_data[input_position] == '\\')) {
12851           ada_log("FILE_SLASH c is U+002F or U+005C");
12852           // Set state to file host state.
12853           state = ada::state::FILE_HOST;
12854           input_position++;
12855         } else {
12856           ada_log("FILE_SLASH otherwise");
12857           // If base is non-null and base's scheme is "file", then:
12858           // Note: it is unsafe to do base_url->scheme unless you know that
12859           // base_url_has_value() is true.
12860           if (base_url != nullptr &&
12861               base_url->type == ada::scheme::type::FILE) {
12862             // Set url's host to base's host.
12863             if constexpr (result_type_is_ada_url) {
12864               url.host = base_url->host;
12865             } else {
12866               // TODO: Optimization opportunity.
12867               url.set_host(base_url->get_host());
12868             }
12869             // If the code point substring from pointer to the end of input does
12870             // not start with a Windows drive letter and base's path[0] is a
12871             // normalized Windows drive letter, then append base's path[0] to
12872             // url's path.
12873             if (!base_url->get_pathname().empty()) {
12874               if (!checkers::is_windows_drive_letter(
12875                       helpers::substring(url_data, input_position))) {
12876                 std::string_view first_base_url_path =
12877                     base_url->get_pathname().substr(1);
12878                 size_t loc = first_base_url_path.find('/');
12879                 if (loc != std::string_view::npos) {
12880                   helpers::resize(first_base_url_path, loc);
12881                 }
12882                 if (checkers::is_normalized_windows_drive_letter(
12883                         first_base_url_path)) {
12884                   if constexpr (result_type_is_ada_url) {
12885                     url.path += '/';
12886                     url.path += first_base_url_path;
12887                   } else {
12888                     url.append_base_pathname(
12889                         helpers::concat("/", first_base_url_path));
12890                   }
12891                 }
12892               }
12893             }
12894           }
12895 
12896           // Set state to path state, and decrease pointer by 1.
12897           state = ada::state::PATH;
12898         }
12899 
12900         break;
12901       }
12902       case ada::state::FILE_HOST: {
12903         std::string_view view = helpers::substring(url_data, input_position);
12904         ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12905 
12906         size_t location = view.find_first_of("/\\?");
12907         std::string_view file_host_buffer(
12908             view.data(),
12909             (location != std::string_view::npos) ? location : view.size());
12910 
12911         if (checkers::is_windows_drive_letter(file_host_buffer)) {
12912           state = ada::state::PATH;
12913         } else if (file_host_buffer.empty()) {
12914           // Set url's host to the empty string.
12915           if constexpr (result_type_is_ada_url) {
12916             url.host = "";
12917           } else {
12918             url.update_base_hostname("");
12919           }
12920           // Set state to path start state.
12921           state = ada::state::PATH_START;
12922         } else {
12923           size_t consumed_bytes = file_host_buffer.size();
12924           input_position += consumed_bytes;
12925           // Let host be the result of host parsing buffer with url is not
12926           // special.
12927           if (!url.parse_host(file_host_buffer)) {
12928             return url;
12929           }
12930 
12931           if constexpr (result_type_is_ada_url) {
12932             // If host is "localhost", then set host to the empty string.
12933             if (url.host.has_value() && url.host.value() == "localhost") {
12934               url.host = "";
12935             }
12936           } else {
12937             if (url.get_hostname() == "localhost") {
12938               url.update_base_hostname("");
12939             }
12940           }
12941 
12942           // Set buffer to the empty string and state to path start state.
12943           state = ada::state::PATH_START;
12944         }
12945 
12946         break;
12947       }
12948       case ada::state::FILE: {
12949         ada_log("FILE ", helpers::substring(url_data, input_position));
12950         std::string_view file_view =
12951             helpers::substring(url_data, input_position);
12952 
12953         url.set_protocol_as_file();
12954         if constexpr (result_type_is_ada_url) {
12955           // Set url's host to the empty string.
12956           url.host = "";
12957         } else {
12958           url.update_base_hostname("");
12959         }
12960         // If c is U+002F (/) or U+005C (\), then:
12961         if (input_position != input_size &&
12962             (url_data[input_position] == '/' ||
12963              url_data[input_position] == '\\')) {
12964           ada_log("FILE c is U+002F or U+005C");
12965           // Set state to file slash state.
12966           state = ada::state::FILE_SLASH;
12967         }
12968         // Otherwise, if base is non-null and base's scheme is "file":
12969         else if (base_url != nullptr &&
12970                  base_url->type == ada::scheme::type::FILE) {
12971           // Set url's host to base's host, url's path to a clone of base's
12972           // path, and url's query to base's query.
12973           ada_log("FILE base non-null");
12974           if constexpr (result_type_is_ada_url) {
12975             url.host = base_url->host;
12976             url.path = base_url->path;
12977             url.query = base_url->query;
12978           } else {
12979             // TODO: Get rid of set_hostname and replace it with
12980             // update_base_hostname
12981             url.set_hostname(base_url->get_hostname());
12982             url.update_base_pathname(base_url->get_pathname());
12983             url.update_base_search(base_url->get_search());
12984           }
12985           url.has_opaque_path = base_url->has_opaque_path;
12986 
12987           // If c is U+003F (?), then set url's query to the empty string and
12988           // state to query state.
12989           if (input_position != input_size && url_data[input_position] == '?') {
12990             state = ada::state::QUERY;
12991           }
12992           // Otherwise, if c is not the EOF code point:
12993           else if (input_position != input_size) {
12994             // Set url's query to null.
12995             url.clear_search();
12996             // If the code point substring from pointer to the end of input does
12997             // not start with a Windows drive letter, then shorten url's path.
12998             if (!checkers::is_windows_drive_letter(file_view)) {
12999               if constexpr (result_type_is_ada_url) {
13000                 helpers::shorten_path(url.path, url.type);
13001               } else {
13002                 std::string_view path = url.get_pathname();
13003                 if (helpers::shorten_path(path, url.type)) {
13004                   url.update_base_pathname(std::string(path));
13005                 }
13006               }
13007             }
13008             // Otherwise:
13009             else {
13010               // Set url's path to an empty list.
13011               url.clear_pathname();
13012               url.has_opaque_path = true;
13013             }
13014 
13015             // Set state to path state and decrease pointer by 1.
13016             state = ada::state::PATH;
13017             break;
13018           }
13019         }
13020         // Otherwise, set state to path state, and decrease pointer by 1.
13021         else {
13022           ada_log("FILE go to path");
13023           state = ada::state::PATH;
13024           break;
13025         }
13026 
13027         input_position++;
13028         break;
13029       }
13030       default:
13031         ada::unreachable();
13032     }
13033   }
13034   if (fragment.has_value()) {
13035     url.update_unencoded_base_hash(*fragment);
13036   }
13037   return url;
13038 }
13039 
13040 template url parse_url<url>(std::string_view user_input,
13041                             const url* base_url = nullptr);
13042 template url_aggregator parse_url<url_aggregator>(
13043     std::string_view user_input, const url_aggregator* base_url = nullptr);
13044 
13045 }  // namespace ada::parser
13046 /* end file src/parser.cpp */
13047 /* begin file src/url_components.cpp */
13048 
13049 #include <numeric>
13050 #include <string>
13051 
13052 namespace ada {
13053 
check_offset_consistency() const13054 [[nodiscard]] bool url_components::check_offset_consistency() const noexcept {
13055   /**
13056    * https://user:pass@example.com:1234/foo/bar?baz#quux
13057    *       |     |    |          | ^^^^|       |   |
13058    *       |     |    |          | |   |       |   `----- hash_start
13059    *       |     |    |          | |   |       `--------- search_start
13060    *       |     |    |          | |   `----------------- pathname_start
13061    *       |     |    |          | `--------------------- port
13062    *       |     |    |          `----------------------- host_end
13063    *       |     |    `---------------------------------- host_start
13064    *       |     `--------------------------------------- username_end
13065    *       `--------------------------------------------- protocol_end
13066    */
13067   // These conditions can be made more strict.
13068   uint32_t index = 0;
13069 
13070   if (protocol_end == url_components::omitted) {
13071     return false;
13072   }
13073   if (protocol_end < index) {
13074     return false;
13075   }
13076   index = protocol_end;
13077 
13078   if (username_end == url_components::omitted) {
13079     return false;
13080   }
13081   if (username_end < index) {
13082     return false;
13083   }
13084   index = username_end;
13085 
13086   if (host_start == url_components::omitted) {
13087     return false;
13088   }
13089   if (host_start < index) {
13090     return false;
13091   }
13092   index = host_start;
13093 
13094   if (port != url_components::omitted) {
13095     if (port > 0xffff) {
13096       return false;
13097     }
13098     uint32_t port_length = helpers::fast_digit_count(port) + 1;
13099     if (index + port_length < index) {
13100       return false;
13101     }
13102     index += port_length;
13103   }
13104 
13105   if (pathname_start == url_components::omitted) {
13106     return false;
13107   }
13108   if (pathname_start < index) {
13109     return false;
13110   }
13111   index = pathname_start;
13112 
13113   if (search_start != url_components::omitted) {
13114     if (search_start < index) {
13115       return false;
13116     }
13117     index = search_start;
13118   }
13119 
13120   if (hash_start != url_components::omitted) {
13121     if (hash_start < index) {
13122       return false;
13123     }
13124     index = hash_start;
13125   }
13126 
13127   return true;
13128 }
13129 
to_string() const13130 [[nodiscard]] std::string url_components::to_string() const {
13131   std::string answer;
13132   auto back = std::back_insert_iterator(answer);
13133   answer.append("{\n");
13134 
13135   answer.append("\t\"protocol_end\":\"");
13136   helpers::encode_json(std::to_string(protocol_end), back);
13137   answer.append("\",\n");
13138 
13139   answer.append("\t\"username_end\":\"");
13140   helpers::encode_json(std::to_string(username_end), back);
13141   answer.append("\",\n");
13142 
13143   answer.append("\t\"host_start\":\"");
13144   helpers::encode_json(std::to_string(host_start), back);
13145   answer.append("\",\n");
13146 
13147   answer.append("\t\"host_end\":\"");
13148   helpers::encode_json(std::to_string(host_end), back);
13149   answer.append("\",\n");
13150 
13151   answer.append("\t\"port\":\"");
13152   helpers::encode_json(std::to_string(port), back);
13153   answer.append("\",\n");
13154 
13155   answer.append("\t\"pathname_start\":\"");
13156   helpers::encode_json(std::to_string(pathname_start), back);
13157   answer.append("\",\n");
13158 
13159   answer.append("\t\"search_start\":\"");
13160   helpers::encode_json(std::to_string(search_start), back);
13161   answer.append("\",\n");
13162 
13163   answer.append("\t\"hash_start\":\"");
13164   helpers::encode_json(std::to_string(hash_start), back);
13165   answer.append("\",\n");
13166 
13167   answer.append("\n}");
13168   return answer;
13169 }
13170 
13171 }  // namespace ada
13172 /* end file src/url_components.cpp */
13173 /* begin file src/url_aggregator.cpp */
13174 
13175 #include <string>
13176 #include <string_view>
13177 
13178 namespace ada {
13179 template <bool has_state_override>
parse_scheme_with_colon(const std::string_view input_with_colon)13180 [[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13181     const std::string_view input_with_colon) {
13182   ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13183   ADA_ASSERT_TRUE(validate());
13184   ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13185   std::string_view input{input_with_colon};
13186   input.remove_suffix(1);
13187   auto parsed_type = ada::scheme::get_scheme_type(input);
13188   bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13189   /**
13190    * In the common case, we will immediately recognize a special scheme (e.g.,
13191    *http, https), in which case, we can go really fast.
13192    **/
13193   if (is_input_special) {  // fast path!!!
13194     if (has_state_override) {
13195       // If url's scheme is not a special scheme and buffer is a special scheme,
13196       // then return.
13197       if (is_special() != is_input_special) {
13198         return true;
13199       }
13200 
13201       // If url includes credentials or has a non-null port, and buffer is
13202       // "file", then return.
13203       if ((has_credentials() || components.port != url_components::omitted) &&
13204           parsed_type == ada::scheme::type::FILE) {
13205         return true;
13206       }
13207 
13208       // If url's scheme is "file" and its host is an empty host, then return.
13209       // An empty host is the empty string.
13210       if (type == ada::scheme::type::FILE &&
13211           components.host_start == components.host_end) {
13212         return true;
13213       }
13214     }
13215 
13216     type = parsed_type;
13217     set_scheme_from_view_with_colon(input_with_colon);
13218 
13219     if (has_state_override) {
13220       // This is uncommon.
13221       uint16_t urls_scheme_port = get_special_port();
13222 
13223       // If url's port is url's scheme's default port, then set url's port to
13224       // null.
13225       if (components.port == urls_scheme_port) {
13226         clear_port();
13227       }
13228     }
13229   } else {  // slow path
13230     std::string _buffer = std::string(input);
13231     // Next function is only valid if the input is ASCII and returns false
13232     // otherwise, but it seems that we always have ascii content so we do not
13233     // need to check the return value.
13234     unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13235 
13236     if (has_state_override) {
13237       // If url's scheme is a special scheme and buffer is not a special scheme,
13238       // then return. If url's scheme is not a special scheme and buffer is a
13239       // special scheme, then return.
13240       if (is_special() != ada::scheme::is_special(_buffer)) {
13241         return true;
13242       }
13243 
13244       // If url includes credentials or has a non-null port, and buffer is
13245       // "file", then return.
13246       if ((has_credentials() || components.port != url_components::omitted) &&
13247           _buffer == "file") {
13248         return true;
13249       }
13250 
13251       // If url's scheme is "file" and its host is an empty host, then return.
13252       // An empty host is the empty string.
13253       if (type == ada::scheme::type::FILE &&
13254           components.host_start == components.host_end) {
13255         return true;
13256       }
13257     }
13258 
13259     set_scheme(_buffer);
13260 
13261     if (has_state_override) {
13262       // This is uncommon.
13263       uint16_t urls_scheme_port = get_special_port();
13264 
13265       // If url's port is url's scheme's default port, then set url's port to
13266       // null.
13267       if (components.port == urls_scheme_port) {
13268         clear_port();
13269       }
13270     }
13271   }
13272   ADA_ASSERT_TRUE(validate());
13273   return true;
13274 }
13275 
copy_scheme(const url_aggregator & u)13276 inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
13277   ada_log("url_aggregator::copy_scheme ", u.buffer);
13278   ADA_ASSERT_TRUE(validate());
13279   // next line could overflow but unsigned arithmetic has well-defined
13280   // overflows.
13281   uint32_t new_difference = u.components.protocol_end - components.protocol_end;
13282   type = u.type;
13283   buffer.erase(0, components.protocol_end);
13284   buffer.insert(0, u.get_protocol());
13285   components.protocol_end = u.components.protocol_end;
13286 
13287   // No need to update the components
13288   if (new_difference == 0) {
13289     return;
13290   }
13291 
13292   // Update the rest of the components.
13293   components.username_end += new_difference;
13294   components.host_start += new_difference;
13295   components.host_end += new_difference;
13296   components.pathname_start += new_difference;
13297   if (components.search_start != url_components::omitted) {
13298     components.search_start += new_difference;
13299   }
13300   if (components.hash_start != url_components::omitted) {
13301     components.hash_start += new_difference;
13302   }
13303   ADA_ASSERT_TRUE(validate());
13304 }
13305 
set_scheme_from_view_with_colon(std::string_view new_scheme_with_colon)13306 inline void url_aggregator::set_scheme_from_view_with_colon(
13307     std::string_view new_scheme_with_colon) noexcept {
13308   ada_log("url_aggregator::set_scheme_from_view_with_colon ",
13309           new_scheme_with_colon);
13310   ADA_ASSERT_TRUE(validate());
13311   ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
13312                   new_scheme_with_colon.back() == ':');
13313   // next line could overflow but unsigned arithmetic has well-defined
13314   // overflows.
13315   uint32_t new_difference =
13316       uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
13317 
13318   if (buffer.empty()) {
13319     buffer.append(new_scheme_with_colon);
13320   } else {
13321     buffer.erase(0, components.protocol_end);
13322     buffer.insert(0, new_scheme_with_colon);
13323   }
13324   components.protocol_end += new_difference;
13325 
13326   // Update the rest of the components.
13327   components.username_end += new_difference;
13328   components.host_start += new_difference;
13329   components.host_end += new_difference;
13330   components.pathname_start += new_difference;
13331   if (components.search_start != url_components::omitted) {
13332     components.search_start += new_difference;
13333   }
13334   if (components.hash_start != url_components::omitted) {
13335     components.hash_start += new_difference;
13336   }
13337   ADA_ASSERT_TRUE(validate());
13338 }
13339 
set_scheme(std::string_view new_scheme)13340 inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
13341   ada_log("url_aggregator::set_scheme ", new_scheme);
13342   ADA_ASSERT_TRUE(validate());
13343   ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
13344   // next line could overflow but unsigned arithmetic has well-defined
13345   // overflows.
13346   uint32_t new_difference =
13347       uint32_t(new_scheme.size()) - components.protocol_end + 1;
13348 
13349   type = ada::scheme::get_scheme_type(new_scheme);
13350   if (buffer.empty()) {
13351     buffer.append(helpers::concat(new_scheme, ":"));
13352   } else {
13353     buffer.erase(0, components.protocol_end);
13354     buffer.insert(0, helpers::concat(new_scheme, ":"));
13355   }
13356   components.protocol_end = uint32_t(new_scheme.size() + 1);
13357 
13358   // Update the rest of the components.
13359   components.username_end += new_difference;
13360   components.host_start += new_difference;
13361   components.host_end += new_difference;
13362   components.pathname_start += new_difference;
13363   if (components.search_start != url_components::omitted) {
13364     components.search_start += new_difference;
13365   }
13366   if (components.hash_start != url_components::omitted) {
13367     components.hash_start += new_difference;
13368   }
13369   ADA_ASSERT_TRUE(validate());
13370 }
13371 
set_protocol(const std::string_view input)13372 bool url_aggregator::set_protocol(const std::string_view input) {
13373   ada_log("url_aggregator::set_protocol ", input);
13374   ADA_ASSERT_TRUE(validate());
13375   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13376   std::string view(input);
13377   helpers::remove_ascii_tab_or_newline(view);
13378   if (view.empty()) {
13379     return true;
13380   }
13381 
13382   // Schemes should start with alpha values.
13383   if (!checkers::is_alpha(view[0])) {
13384     return false;
13385   }
13386 
13387   view.append(":");
13388 
13389   std::string::iterator pointer =
13390       std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
13391 
13392   if (pointer != view.end() && *pointer == ':') {
13393     return parse_scheme_with_colon<true>(
13394         std::string_view(view.data(), pointer - view.begin() + 1));
13395   }
13396   return false;
13397 }
13398 
set_username(const std::string_view input)13399 bool url_aggregator::set_username(const std::string_view input) {
13400   ada_log("url_aggregator::set_username '", input, "' ");
13401   ADA_ASSERT_TRUE(validate());
13402   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13403   if (cannot_have_credentials_or_port()) {
13404     return false;
13405   }
13406   size_t idx = ada::unicode::percent_encode_index(
13407       input, character_sets::USERINFO_PERCENT_ENCODE);
13408   if (idx == input.size()) {
13409     update_base_username(input);
13410   } else {
13411     // We only create a temporary string if we have to!
13412     update_base_username(ada::unicode::percent_encode(
13413         input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13414   }
13415   ADA_ASSERT_TRUE(validate());
13416   return true;
13417 }
13418 
set_password(const std::string_view input)13419 bool url_aggregator::set_password(const std::string_view input) {
13420   ada_log("url_aggregator::set_password '", input, "'");
13421   ADA_ASSERT_TRUE(validate());
13422   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13423   if (cannot_have_credentials_or_port()) {
13424     return false;
13425   }
13426   size_t idx = ada::unicode::percent_encode_index(
13427       input, character_sets::USERINFO_PERCENT_ENCODE);
13428   if (idx == input.size()) {
13429     update_base_password(input);
13430   } else {
13431     // We only create a temporary string if we have to!
13432     update_base_password(ada::unicode::percent_encode(
13433         input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13434   }
13435   ADA_ASSERT_TRUE(validate());
13436   return true;
13437 }
13438 
set_port(const std::string_view input)13439 bool url_aggregator::set_port(const std::string_view input) {
13440   ada_log("url_aggregator::set_port ", input);
13441   ADA_ASSERT_TRUE(validate());
13442   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13443   if (cannot_have_credentials_or_port()) {
13444     return false;
13445   }
13446   std::string trimmed(input);
13447   helpers::remove_ascii_tab_or_newline(trimmed);
13448   if (trimmed.empty()) {
13449     clear_port();
13450     return true;
13451   }
13452   // Input should not start with control characters.
13453   if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
13454     return false;
13455   }
13456   // Input should contain at least one ascii digit.
13457   if (input.find_first_of("0123456789") == std::string_view::npos) {
13458     return false;
13459   }
13460 
13461   // Revert changes if parse_port fails.
13462   uint32_t previous_port = components.port;
13463   parse_port(trimmed);
13464   if (is_valid) {
13465     return true;
13466   }
13467   update_base_port(previous_port);
13468   is_valid = true;
13469   ADA_ASSERT_TRUE(validate());
13470   return false;
13471 }
13472 
set_pathname(const std::string_view input)13473 bool url_aggregator::set_pathname(const std::string_view input) {
13474   ada_log("url_aggregator::set_pathname ", input);
13475   ADA_ASSERT_TRUE(validate());
13476   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13477   if (has_opaque_path) {
13478     return false;
13479   }
13480   clear_pathname();
13481   parse_path(input);
13482   if (checkers::begins_with(input, "//") && !has_authority() &&
13483       !has_dash_dot()) {
13484     buffer.insert(components.pathname_start, "/.");
13485     components.pathname_start += 2;
13486   }
13487   ADA_ASSERT_TRUE(validate());
13488   return true;
13489 }
13490 
parse_path(std::string_view input)13491 ada_really_inline void url_aggregator::parse_path(std::string_view input) {
13492   ada_log("url_aggregator::parse_path ", input);
13493   ADA_ASSERT_TRUE(validate());
13494   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13495   std::string tmp_buffer;
13496   std::string_view internal_input;
13497   if (unicode::has_tabs_or_newline(input)) {
13498     tmp_buffer = input;
13499     // Optimization opportunity: Instead of copying and then pruning, we could
13500     // just directly build the string from user_input.
13501     helpers::remove_ascii_tab_or_newline(tmp_buffer);
13502     internal_input = tmp_buffer;
13503   } else {
13504     internal_input = input;
13505   }
13506 
13507   // If url is special, then:
13508   if (is_special()) {
13509     if (internal_input.empty()) {
13510       update_base_pathname("/");
13511     } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13512       consume_prepared_path(internal_input.substr(1));
13513     } else {
13514       consume_prepared_path(internal_input);
13515     }
13516   } else if (!internal_input.empty()) {
13517     if (internal_input[0] == '/') {
13518       consume_prepared_path(internal_input.substr(1));
13519     } else {
13520       consume_prepared_path(internal_input);
13521     }
13522   } else {
13523     // Non-special URLs with an empty host can have their paths erased
13524     // Path-only URLs cannot have their paths erased
13525     if (components.host_start == components.host_end && !has_authority()) {
13526       update_base_pathname("/");
13527     }
13528   }
13529   ADA_ASSERT_TRUE(validate());
13530 }
13531 
set_search(const std::string_view input)13532 void url_aggregator::set_search(const std::string_view input) {
13533   ada_log("url_aggregator::set_search ", input);
13534   ADA_ASSERT_TRUE(validate());
13535   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13536   if (input.empty()) {
13537     clear_search();
13538     helpers::strip_trailing_spaces_from_opaque_path(*this);
13539     return;
13540   }
13541 
13542   std::string new_value;
13543   new_value = input[0] == '?' ? input.substr(1) : input;
13544   helpers::remove_ascii_tab_or_newline(new_value);
13545 
13546   auto query_percent_encode_set =
13547       is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13548                    : ada::character_sets::QUERY_PERCENT_ENCODE;
13549 
13550   update_base_search(new_value, query_percent_encode_set);
13551   ADA_ASSERT_TRUE(validate());
13552 }
13553 
set_hash(const std::string_view input)13554 void url_aggregator::set_hash(const std::string_view input) {
13555   ada_log("url_aggregator::set_hash ", input);
13556   ADA_ASSERT_TRUE(validate());
13557   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13558   if (input.empty()) {
13559     if (components.hash_start != url_components::omitted) {
13560       buffer.resize(components.hash_start);
13561       components.hash_start = url_components::omitted;
13562     }
13563     helpers::strip_trailing_spaces_from_opaque_path(*this);
13564     return;
13565   }
13566 
13567   std::string new_value;
13568   new_value = input[0] == '#' ? input.substr(1) : input;
13569   helpers::remove_ascii_tab_or_newline(new_value);
13570   update_unencoded_base_hash(new_value);
13571   ADA_ASSERT_TRUE(validate());
13572 }
13573 
set_href(const std::string_view input)13574 bool url_aggregator::set_href(const std::string_view input) {
13575   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13576   ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
13577   ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
13578   ada_log("url_aggregator::set_href, success :", out.has_value());
13579 
13580   if (out) {
13581     ada_log("url_aggregator::set_href, parsed ", out->to_string());
13582     // TODO: Figure out why the following line puts test to never finish.
13583     *this = *out;
13584   }
13585 
13586   return out.has_value();
13587 }
13588 
parse_host(std::string_view input)13589 ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
13590   ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
13591           " bytes]");
13592   ADA_ASSERT_TRUE(validate());
13593   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13594   if (input.empty()) {
13595     return is_valid = false;
13596   }  // technically unnecessary.
13597   // If input starts with U+005B ([), then:
13598   if (input[0] == '[') {
13599     // If input does not end with U+005D (]), validation error, return failure.
13600     if (input.back() != ']') {
13601       return is_valid = false;
13602     }
13603     ada_log("parse_host ipv6");
13604 
13605     // Return the result of IPv6 parsing input with its leading U+005B ([) and
13606     // trailing U+005D (]) removed.
13607     input.remove_prefix(1);
13608     input.remove_suffix(1);
13609     return parse_ipv6(input);
13610   }
13611 
13612   // If isNotSpecial is true, then return the result of opaque-host parsing
13613   // input.
13614   if (!is_special()) {
13615     return parse_opaque_host(input);
13616   }
13617   // Let domain be the result of running UTF-8 decode without BOM on the
13618   // percent-decoding of input. Let asciiDomain be the result of running domain
13619   // to ASCII with domain and false. The most common case is an ASCII input, in
13620   // which case we do not need to call the expensive 'to_ascii' if a few
13621   // conditions are met: no '%' and no 'xn-' subsequence.
13622 
13623   // Often, the input does not contain any forbidden code points, and no upper
13624   // case ASCII letter, then we can just copy it to the buffer. We want to
13625   // optimize for such a common case.
13626   uint8_t is_forbidden_or_upper =
13627       unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
13628                                                              input.size());
13629   // Minor optimization opportunity:
13630   // contains_forbidden_domain_code_point_or_upper could be extend to check for
13631   // the presence of characters that cannot appear in the ipv4 address and we
13632   // could also check whether x and n and - are present, and so we could skip
13633   // some of the checks below. However, the gains are likely to be small, and
13634   // the code would be more complex.
13635   if (is_forbidden_or_upper == 0 &&
13636       input.find("xn-") == std::string_view::npos) {
13637     // fast path
13638     update_base_hostname(input);
13639     if (checkers::is_ipv4(get_hostname())) {
13640       ada_log("parse_host fast path ipv4");
13641       return parse_ipv4(get_hostname(), true);
13642     }
13643     ada_log("parse_host fast path ", get_hostname());
13644     return true;
13645   }
13646   // We have encountered at least one forbidden code point or the input contains
13647   // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
13648   // conversion.
13649 
13650   ada_log("parse_host calling to_ascii");
13651   std::optional<std::string> host = std::string(get_hostname());
13652   is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13653   if (!is_valid) {
13654     ada_log("parse_host to_ascii returns false");
13655     return is_valid = false;
13656   }
13657   ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
13658           " bytes]");
13659 
13660   if (std::any_of(host.value().begin(), host.value().end(),
13661                   ada::unicode::is_forbidden_domain_code_point)) {
13662     return is_valid = false;
13663   }
13664 
13665   // If asciiDomain ends in a number, then return the result of IPv4 parsing
13666   // asciiDomain.
13667   if (checkers::is_ipv4(host.value())) {
13668     ada_log("parse_host got ipv4 ", *host);
13669     return parse_ipv4(host.value(), false);
13670   }
13671 
13672   update_base_hostname(host.value());
13673   ADA_ASSERT_TRUE(validate());
13674   return true;
13675 }
13676 
13677 template <bool override_hostname>
set_host_or_hostname(const std::string_view input)13678 bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13679   ada_log("url_aggregator::set_host_or_hostname ", input);
13680   ADA_ASSERT_TRUE(validate());
13681   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13682   if (has_opaque_path) {
13683     return false;
13684   }
13685 
13686   std::string previous_host = std::string(get_hostname());
13687   uint32_t previous_port = components.port;
13688 
13689   size_t host_end_pos = input.find('#');
13690   std::string _host(input.data(), host_end_pos != std::string_view::npos
13691                                       ? host_end_pos
13692                                       : input.size());
13693   helpers::remove_ascii_tab_or_newline(_host);
13694   std::string_view new_host(_host);
13695 
13696   // If url's scheme is "file", then set state to file host state, instead of
13697   // host state.
13698   if (type != ada::scheme::type::FILE) {
13699     std::string_view host_view(_host.data(), _host.length());
13700     auto [location, found_colon] =
13701         helpers::get_host_delimiter_location(is_special(), host_view);
13702 
13703     // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13704     // Note: the 'found_colon' value is true if and only if a colon was
13705     // encountered while not inside brackets.
13706     if (found_colon) {
13707       if (override_hostname) {
13708         return false;
13709       }
13710       std::string_view sub_buffer = new_host.substr(location + 1);
13711       if (!sub_buffer.empty()) {
13712         set_port(sub_buffer);
13713       }
13714     }
13715     // If url is special and host_view is the empty string, validation error,
13716     // return failure. Otherwise, if state override is given, host_view is the
13717     // empty string, and either url includes credentials or url's port is
13718     // non-null, return.
13719     else if (host_view.empty() &&
13720              (is_special() || has_credentials() || has_port())) {
13721       return false;
13722     }
13723 
13724     // Let host be the result of host parsing host_view with url is not special.
13725     if (host_view.empty() && !is_special()) {
13726       if (has_hostname()) {
13727         clear_hostname();  // easy!
13728       } else if (has_dash_dot()) {
13729         add_authority_slashes_if_needed();
13730         delete_dash_dot();
13731       }
13732       return true;
13733     }
13734 
13735     bool succeeded = parse_host(host_view);
13736     if (!succeeded) {
13737       update_base_hostname(previous_host);
13738       update_base_port(previous_port);
13739     } else if (has_dash_dot()) {
13740       // Should remove dash_dot from pathname
13741       delete_dash_dot();
13742     }
13743     return succeeded;
13744   }
13745 
13746   size_t location = new_host.find_first_of("/\\?");
13747   if (location != std::string_view::npos) {
13748     new_host.remove_suffix(new_host.length() - location);
13749   }
13750 
13751   if (new_host.empty()) {
13752     // Set url's host to the empty string.
13753     clear_hostname();
13754   } else {
13755     // Let host be the result of host parsing buffer with url is not special.
13756     if (!parse_host(new_host)) {
13757       update_base_hostname(previous_host);
13758       update_base_port(previous_port);
13759       return false;
13760     }
13761 
13762     // If host is "localhost", then set host to the empty string.
13763     if (helpers::substring(buffer, components.host_start,
13764                            components.host_end) == "localhost") {
13765       clear_hostname();
13766     }
13767   }
13768   ADA_ASSERT_TRUE(validate());
13769   return true;
13770 }
13771 
set_host(const std::string_view input)13772 bool url_aggregator::set_host(const std::string_view input) {
13773   ada_log("url_aggregator::set_host '", input, "'");
13774   ADA_ASSERT_TRUE(validate());
13775   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13776   return set_host_or_hostname<false>(input);
13777 }
13778 
set_hostname(const std::string_view input)13779 bool url_aggregator::set_hostname(const std::string_view input) {
13780   ada_log("url_aggregator::set_hostname '", input, "'");
13781   ADA_ASSERT_TRUE(validate());
13782   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13783   return set_host_or_hostname<true>(input);
13784 }
13785 
get_origin() const13786 [[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
13787   ada_log("url_aggregator::get_origin");
13788   if (is_special()) {
13789     // Return a new opaque origin.
13790     if (type == scheme::FILE) {
13791       return "null";
13792     }
13793 
13794     return helpers::concat(get_protocol(), "//", get_host());
13795   }
13796 
13797   if (get_protocol() == "blob:") {
13798     std::string_view path = get_pathname();
13799     if (!path.empty()) {
13800       auto out = ada::parse<ada::url_aggregator>(path);
13801       if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
13802         // If pathURL's scheme is not "http" and not "https", then return a
13803         // new opaque origin.
13804         return helpers::concat(out->get_protocol(), "//", out->get_host());
13805       }
13806     }
13807   }
13808 
13809   // Return a new opaque origin.
13810   return "null";
13811 }
13812 
get_username() const13813 [[nodiscard]] std::string_view url_aggregator::get_username() const noexcept {
13814   ada_log("url_aggregator::get_username");
13815   if (has_non_empty_username()) {
13816     return helpers::substring(buffer, components.protocol_end + 2,
13817                               components.username_end);
13818   }
13819   return "";
13820 }
13821 
get_password() const13822 [[nodiscard]] std::string_view url_aggregator::get_password() const noexcept {
13823   ada_log("url_aggregator::get_password");
13824   if (has_non_empty_password()) {
13825     return helpers::substring(buffer, components.username_end + 1,
13826                               components.host_start);
13827   }
13828   return "";
13829 }
13830 
get_port() const13831 [[nodiscard]] std::string_view url_aggregator::get_port() const noexcept {
13832   ada_log("url_aggregator::get_port");
13833   if (components.port == url_components::omitted) {
13834     return "";
13835   }
13836   return helpers::substring(buffer, components.host_end + 1,
13837                             components.pathname_start);
13838 }
13839 
get_hash() const13840 [[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept {
13841   ada_log("url_aggregator::get_hash");
13842   // If this's URL's fragment is either null or the empty string, then return
13843   // the empty string. Return U+0023 (#), followed by this's URL's fragment.
13844   if (components.hash_start == url_components::omitted) {
13845     return "";
13846   }
13847   if (buffer.size() - components.hash_start <= 1) {
13848     return "";
13849   }
13850   return helpers::substring(buffer, components.hash_start);
13851 }
13852 
get_host() const13853 [[nodiscard]] std::string_view url_aggregator::get_host() const noexcept {
13854   ada_log("url_aggregator::get_host");
13855   // Technically, we should check if there is a hostname, but
13856   // the code below works even if there isn't.
13857   // if(!has_hostname()) { return ""; }
13858   size_t start = components.host_start;
13859   if (components.host_end > components.host_start &&
13860       buffer[components.host_start] == '@') {
13861     start++;
13862   }
13863   // if we have an empty host, then the space between components.host_end and
13864   // components.pathname_start may be occupied by /.
13865   if (start == components.host_end) {
13866     return std::string_view();
13867   }
13868   return helpers::substring(buffer, start, components.pathname_start);
13869 }
13870 
get_hostname() const13871 [[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept {
13872   ada_log("url_aggregator::get_hostname");
13873   // Technically, we should check if there is a hostname, but
13874   // the code below works even if there isn't.
13875   // if(!has_hostname()) { return ""; }
13876   size_t start = components.host_start;
13877   // So host_start is not where the host begins.
13878   if (components.host_end > components.host_start &&
13879       buffer[components.host_start] == '@') {
13880     start++;
13881   }
13882   return helpers::substring(buffer, start, components.host_end);
13883 }
13884 
get_pathname() const13885 [[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept {
13886   ada_log("url_aggregator::get_pathname pathname_start = ",
13887           components.pathname_start, " buffer.size() = ", buffer.size(),
13888           " components.search_start = ", components.search_start,
13889           " components.hash_start = ", components.hash_start);
13890   uint32_t ending_index = uint32_t(buffer.size());
13891   if (components.search_start != url_components::omitted) {
13892     ending_index = components.search_start;
13893   } else if (components.hash_start != url_components::omitted) {
13894     ending_index = components.hash_start;
13895   }
13896   return helpers::substring(buffer, components.pathname_start, ending_index);
13897 }
13898 
get_search() const13899 [[nodiscard]] std::string_view url_aggregator::get_search() const noexcept {
13900   ada_log("url_aggregator::get_search");
13901   // If this's URL's query is either null or the empty string, then return the
13902   // empty string. Return U+003F (?), followed by this's URL's query.
13903   if (components.search_start == url_components::omitted) {
13904     return "";
13905   }
13906   uint32_t ending_index = uint32_t(buffer.size());
13907   if (components.hash_start != url_components::omitted) {
13908     ending_index = components.hash_start;
13909   }
13910   if (ending_index - components.search_start <= 1) {
13911     return "";
13912   }
13913   return helpers::substring(buffer, components.search_start, ending_index);
13914 }
13915 
get_protocol() const13916 [[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept {
13917   ada_log("url_aggregator::get_protocol");
13918   return helpers::substring(buffer, 0, components.protocol_end);
13919 }
13920 
to_string() const13921 [[nodiscard]] std::string ada::url_aggregator::to_string() const {
13922   ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
13923           " bytes]");
13924   if (!is_valid) {
13925     return "null";
13926   }
13927 
13928   std::string answer;
13929   auto back = std::back_insert_iterator(answer);
13930   answer.append("{\n");
13931 
13932   answer.append("\t\"buffer\":\"");
13933   helpers::encode_json(buffer, back);
13934   answer.append("\",\n");
13935 
13936   answer.append("\t\"protocol\":\"");
13937   helpers::encode_json(get_protocol(), back);
13938   answer.append("\",\n");
13939 
13940   if (has_credentials()) {
13941     answer.append("\t\"username\":\"");
13942     helpers::encode_json(get_username(), back);
13943     answer.append("\",\n");
13944     answer.append("\t\"password\":\"");
13945     helpers::encode_json(get_password(), back);
13946     answer.append("\",\n");
13947   }
13948 
13949   answer.append("\t\"host\":\"");
13950   helpers::encode_json(get_host(), back);
13951   answer.append("\",\n");
13952 
13953   answer.append("\t\"path\":\"");
13954   helpers::encode_json(get_pathname(), back);
13955   answer.append("\",\n");
13956   answer.append("\t\"opaque path\":");
13957   answer.append((has_opaque_path ? "true" : "false"));
13958   answer.append(",\n");
13959 
13960   if (components.search_start != url_components::omitted) {
13961     answer.append("\t\"query\":\"");
13962     helpers::encode_json(get_search(), back);
13963     answer.append("\",\n");
13964   }
13965   if (components.hash_start != url_components::omitted) {
13966     answer.append("\t\"fragment\":\"");
13967     helpers::encode_json(get_hash(), back);
13968     answer.append("\",\n");
13969   }
13970 
13971   auto convert_offset_to_string = [](uint32_t offset) -> std::string {
13972     if (offset == url_components::omitted) {
13973       return "null";
13974     } else {
13975       return std::to_string(offset);
13976     }
13977   };
13978 
13979   answer.append("\t\"protocol_end\":");
13980   answer.append(convert_offset_to_string(components.protocol_end));
13981   answer.append(",\n");
13982 
13983   answer.append("\t\"username_end\":");
13984   answer.append(convert_offset_to_string(components.username_end));
13985   answer.append(",\n");
13986 
13987   answer.append("\t\"host_start\":");
13988   answer.append(convert_offset_to_string(components.host_start));
13989   answer.append(",\n");
13990 
13991   answer.append("\t\"host_end\":");
13992   answer.append(convert_offset_to_string(components.host_end));
13993   answer.append(",\n");
13994 
13995   answer.append("\t\"port\":");
13996   answer.append(convert_offset_to_string(components.port));
13997   answer.append(",\n");
13998 
13999   answer.append("\t\"pathname_start\":");
14000   answer.append(convert_offset_to_string(components.pathname_start));
14001   answer.append(",\n");
14002 
14003   answer.append("\t\"search_start\":");
14004   answer.append(convert_offset_to_string(components.search_start));
14005   answer.append(",\n");
14006 
14007   answer.append("\t\"hash_start\":");
14008   answer.append(convert_offset_to_string(components.hash_start));
14009   answer.append("\n}");
14010 
14011   return answer;
14012 }
14013 
has_valid_domain() const14014 [[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
14015   if (components.host_start == components.host_end) {
14016     return false;
14017   }
14018   return checkers::verify_dns_length(get_hostname());
14019 }
14020 
parse_ipv4(std::string_view input,bool in_place)14021 bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
14022   ada_log("parse_ipv4 ", input, " [", input.size(),
14023           " bytes], overlaps with buffer: ",
14024           helpers::overlaps(input, buffer) ? "yes" : "no");
14025   ADA_ASSERT_TRUE(validate());
14026   const bool trailing_dot = (input.back() == '.');
14027   if (trailing_dot) {
14028     input.remove_suffix(1);
14029   }
14030   size_t digit_count{0};
14031   int pure_decimal_count = 0;  // entries that are decimal
14032   uint64_t ipv4{0};
14033   // we could unroll for better performance?
14034   for (; (digit_count < 4) && !(input.empty()); digit_count++) {
14035     uint32_t
14036         segment_result{};  // If any number exceeds 32 bits, we have an error.
14037     bool is_hex = checkers::has_hex_prefix(input);
14038     if (is_hex && ((input.length() == 2) ||
14039                    ((input.length() > 2) && (input[2] == '.')))) {
14040       // special case
14041       segment_result = 0;
14042       input.remove_prefix(2);
14043     } else {
14044       std::from_chars_result r;
14045       if (is_hex) {
14046         ada_log("parse_ipv4 trying to parse hex number");
14047         r = std::from_chars(input.data() + 2, input.data() + input.size(),
14048                             segment_result, 16);
14049       } else if ((input.length() >= 2) && input[0] == '0' &&
14050                  checkers::is_digit(input[1])) {
14051         ada_log("parse_ipv4 trying to parse octal number");
14052         r = std::from_chars(input.data() + 1, input.data() + input.size(),
14053                             segment_result, 8);
14054       } else {
14055         ada_log("parse_ipv4 trying to parse decimal number");
14056         pure_decimal_count++;
14057         r = std::from_chars(input.data(), input.data() + input.size(),
14058                             segment_result, 10);
14059       }
14060       if (r.ec != std::errc()) {
14061         ada_log("parse_ipv4 parsing failed");
14062         return is_valid = false;
14063       }
14064       ada_log("parse_ipv4 parsed ", segment_result);
14065       input.remove_prefix(r.ptr - input.data());
14066     }
14067     if (input.empty()) {
14068       // We have the last value.
14069       // At this stage, ipv4 contains digit_count*8 bits.
14070       // So we have 32-digit_count*8 bits left.
14071       if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
14072         return is_valid = false;
14073       }
14074       ipv4 <<= (32 - digit_count * 8);
14075       ipv4 |= segment_result;
14076       goto final;
14077     } else {
14078       // There is more, so that the value must no be larger than 255
14079       // and we must have a '.'.
14080       if ((segment_result > 255) || (input[0] != '.')) {
14081         return is_valid = false;
14082       }
14083       ipv4 <<= 8;
14084       ipv4 |= segment_result;
14085       input.remove_prefix(1);  // remove '.'
14086     }
14087   }
14088   if ((digit_count != 4) || (!input.empty())) {
14089     ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
14090     return is_valid = false;
14091   }
14092 final:
14093   ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14094           " host: ", get_host());
14095 
14096   // We could also check r.ptr to see where the parsing ended.
14097   if (in_place && pure_decimal_count == 4 && !trailing_dot) {
14098     ada_log(
14099         "url_aggregator::parse_ipv4 completed and was already correct in the "
14100         "buffer");
14101     // The original input was already all decimal and we validated it. So we
14102     // don't need to do anything.
14103   } else {
14104     ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
14105     // Optimization opportunity: Get rid of unnecessary string return in ipv4
14106     // serializer.
14107     // TODO: This is likely a bug because it goes back update_base_hostname, not
14108     // what we want to do.
14109     update_base_hostname(
14110         ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14111   }
14112   host_type = IPV4;
14113   ADA_ASSERT_TRUE(validate());
14114   return true;
14115 }
14116 
parse_ipv6(std::string_view input)14117 bool url_aggregator::parse_ipv6(std::string_view input) {
14118   // TODO: Implement in_place optimization: we know that input points
14119   // in the buffer, so we can just check whether the buffer is already
14120   // well formatted.
14121   // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14122   ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
14123   ADA_ASSERT_TRUE(validate());
14124   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14125   if (input.empty()) {
14126     return is_valid = false;
14127   }
14128   // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14129   std::array<uint16_t, 8> address{};
14130 
14131   // Let pieceIndex be 0.
14132   int piece_index = 0;
14133 
14134   // Let compress be null.
14135   std::optional<int> compress{};
14136 
14137   // Let pointer be a pointer for input.
14138   std::string_view::iterator pointer = input.begin();
14139 
14140   // If c is U+003A (:), then:
14141   if (input[0] == ':') {
14142     // If remaining does not start with U+003A (:), validation error, return
14143     // failure.
14144     if (input.size() == 1 || input[1] != ':') {
14145       ada_log("parse_ipv6 starts with : but the rest does not start with :");
14146       return is_valid = false;
14147     }
14148 
14149     // Increase pointer by 2.
14150     pointer += 2;
14151 
14152     // Increase pieceIndex by 1 and then set compress to pieceIndex.
14153     compress = ++piece_index;
14154   }
14155 
14156   // While c is not the EOF code point:
14157   while (pointer != input.end()) {
14158     // If pieceIndex is 8, validation error, return failure.
14159     if (piece_index == 8) {
14160       ada_log("parse_ipv6 piece_index == 8");
14161       return is_valid = false;
14162     }
14163 
14164     // If c is U+003A (:), then:
14165     if (*pointer == ':') {
14166       // If compress is non-null, validation error, return failure.
14167       if (compress.has_value()) {
14168         ada_log("parse_ipv6 compress is non-null");
14169         return is_valid = false;
14170       }
14171 
14172       // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
14173       // then continue.
14174       pointer++;
14175       compress = ++piece_index;
14176       continue;
14177     }
14178 
14179     // Let value and length be 0.
14180     uint16_t value = 0, length = 0;
14181 
14182     // While length is less than 4 and c is an ASCII hex digit,
14183     // set value to value times 0x10 + c interpreted as hexadecimal number, and
14184     // increase pointer and length by 1.
14185     while (length < 4 && pointer != input.end() &&
14186            unicode::is_ascii_hex_digit(*pointer)) {
14187       // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14188       value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
14189       pointer++;
14190       length++;
14191     }
14192 
14193     // If c is U+002E (.), then:
14194     if (pointer != input.end() && *pointer == '.') {
14195       // If length is 0, validation error, return failure.
14196       if (length == 0) {
14197         ada_log("parse_ipv6 length is 0");
14198         return is_valid = false;
14199       }
14200 
14201       // Decrease pointer by length.
14202       pointer -= length;
14203 
14204       // If pieceIndex is greater than 6, validation error, return failure.
14205       if (piece_index > 6) {
14206         ada_log("parse_ipv6 piece_index > 6");
14207         return is_valid = false;
14208       }
14209 
14210       // Let numbersSeen be 0.
14211       int numbers_seen = 0;
14212 
14213       // While c is not the EOF code point:
14214       while (pointer != input.end()) {
14215         // Let ipv4Piece be null.
14216         std::optional<uint16_t> ipv4_piece{};
14217 
14218         // If numbersSeen is greater than 0, then:
14219         if (numbers_seen > 0) {
14220           // If c is a U+002E (.) and numbersSeen is less than 4, then increase
14221           // pointer by 1.
14222           if (*pointer == '.' && numbers_seen < 4) {
14223             pointer++;
14224           } else {
14225             // Otherwise, validation error, return failure.
14226             ada_log("parse_ipv6 Otherwise, validation error, return failure");
14227             return is_valid = false;
14228           }
14229         }
14230 
14231         // If c is not an ASCII digit, validation error, return failure.
14232         if (pointer == input.end() || !checkers::is_digit(*pointer)) {
14233           ada_log(
14234               "parse_ipv6 If c is not an ASCII digit, validation error, return "
14235               "failure");
14236           return is_valid = false;
14237         }
14238 
14239         // While c is an ASCII digit:
14240         while (pointer != input.end() && checkers::is_digit(*pointer)) {
14241           // Let number be c interpreted as decimal number.
14242           int number = *pointer - '0';
14243 
14244           // If ipv4Piece is null, then set ipv4Piece to number.
14245           if (!ipv4_piece.has_value()) {
14246             ipv4_piece = number;
14247           }
14248           // Otherwise, if ipv4Piece is 0, validation error, return failure.
14249           else if (ipv4_piece == 0) {
14250             ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
14251             return is_valid = false;
14252           }
14253           // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
14254           else {
14255             ipv4_piece = *ipv4_piece * 10 + number;
14256           }
14257 
14258           // If ipv4Piece is greater than 255, validation error, return failure.
14259           if (ipv4_piece > 255) {
14260             ada_log("parse_ipv6 ipv4_piece > 255");
14261             return is_valid = false;
14262           }
14263 
14264           // Increase pointer by 1.
14265           pointer++;
14266         }
14267 
14268         // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
14269         // ipv4Piece.
14270         // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14271         address[piece_index] =
14272             uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
14273 
14274         // Increase numbersSeen by 1.
14275         numbers_seen++;
14276 
14277         // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
14278         if (numbers_seen == 2 || numbers_seen == 4) {
14279           piece_index++;
14280         }
14281       }
14282 
14283       // If numbersSeen is not 4, validation error, return failure.
14284       if (numbers_seen != 4) {
14285         return is_valid = false;
14286       }
14287 
14288       // Break.
14289       break;
14290     }
14291     // Otherwise, if c is U+003A (:):
14292     else if ((pointer != input.end()) && (*pointer == ':')) {
14293       // Increase pointer by 1.
14294       pointer++;
14295 
14296       // If c is the EOF code point, validation error, return failure.
14297       if (pointer == input.end()) {
14298         ada_log(
14299             "parse_ipv6 If c is the EOF code point, validation error, return "
14300             "failure");
14301         return is_valid = false;
14302       }
14303     }
14304     // Otherwise, if c is not the EOF code point, validation error, return
14305     // failure.
14306     else if (pointer != input.end()) {
14307       ada_log(
14308           "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
14309           "error, return failure");
14310       return is_valid = false;
14311     }
14312 
14313     // Set address[pieceIndex] to value.
14314     address[piece_index] = value;
14315 
14316     // Increase pieceIndex by 1.
14317     piece_index++;
14318   }
14319 
14320   // If compress is non-null, then:
14321   if (compress.has_value()) {
14322     // Let swaps be pieceIndex - compress.
14323     int swaps = piece_index - *compress;
14324 
14325     // Set pieceIndex to 7.
14326     piece_index = 7;
14327 
14328     // While pieceIndex is not 0 and swaps is greater than 0,
14329     // swap address[pieceIndex] with address[compress + swaps - 1], and then
14330     // decrease both pieceIndex and swaps by 1.
14331     while (piece_index != 0 && swaps > 0) {
14332       std::swap(address[piece_index], address[*compress + swaps - 1]);
14333       piece_index--;
14334       swaps--;
14335     }
14336   }
14337   // Otherwise, if compress is null and pieceIndex is not 8, validation error,
14338   // return failure.
14339   else if (piece_index != 8) {
14340     ada_log(
14341         "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
14342         "error, return failure");
14343     return is_valid = false;
14344   }
14345   // TODO: Optimization opportunity: Get rid of unnecessary string creation.
14346   // TODO: This is likely a bug because it goes back update_base_hostname, not
14347   // what we want to do.
14348   update_base_hostname(ada::serializers::ipv6(address));
14349   ada_log("parse_ipv6 ", get_hostname());
14350   ADA_ASSERT_TRUE(validate());
14351   host_type = IPV6;
14352   return true;
14353 }
14354 
parse_opaque_host(std::string_view input)14355 bool url_aggregator::parse_opaque_host(std::string_view input) {
14356   ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
14357   ADA_ASSERT_TRUE(validate());
14358   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14359   if (std::any_of(input.begin(), input.end(),
14360                   ada::unicode::is_forbidden_host_code_point)) {
14361     return is_valid = false;
14362   }
14363 
14364   // Return the result of running UTF-8 percent-encode on input using the C0
14365   // control percent-encode set.
14366   size_t idx = ada::unicode::percent_encode_index(
14367       input, character_sets::C0_CONTROL_PERCENT_ENCODE);
14368   if (idx == input.size()) {
14369     update_base_hostname(input);
14370   } else {
14371     // We only create a temporary string if we need to.
14372     update_base_hostname(ada::unicode::percent_encode(
14373         input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
14374   }
14375   ADA_ASSERT_TRUE(validate());
14376   return true;
14377 }
14378 
to_diagram() const14379 [[nodiscard]] std::string url_aggregator::to_diagram() const {
14380   if (!is_valid) {
14381     return "invalid";
14382   }
14383   std::string answer;
14384   answer.append(buffer);
14385   answer.append(" [");
14386   answer.append(std::to_string(buffer.size()));
14387   answer.append(" bytes]");
14388   answer.append("\n");
14389   // first line
14390   std::string line1;
14391   line1.resize(buffer.size(), ' ');
14392   if (components.hash_start != url_components::omitted) {
14393     line1[components.hash_start] = '|';
14394   }
14395   if (components.search_start != url_components::omitted) {
14396     line1[components.search_start] = '|';
14397   }
14398   if (components.pathname_start != buffer.size()) {
14399     line1[components.pathname_start] = '|';
14400   }
14401   if (components.host_end != buffer.size()) {
14402     line1[components.host_end] = '|';
14403   }
14404   if (components.host_start != buffer.size()) {
14405     line1[components.host_start] = '|';
14406   }
14407   if (components.username_end != buffer.size()) {
14408     line1[components.username_end] = '|';
14409   }
14410   if (components.protocol_end != buffer.size()) {
14411     line1[components.protocol_end] = '|';
14412   }
14413   answer.append(line1);
14414   answer.append("\n");
14415 
14416   std::string line2 = line1;
14417   if (components.hash_start != url_components::omitted) {
14418     line2[components.hash_start] = '`';
14419     line1[components.hash_start] = ' ';
14420 
14421     for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
14422       line2[i] = '-';
14423     }
14424     line2.append(" hash_start");
14425     answer.append(line2);
14426     answer.append("\n");
14427   }
14428 
14429   std::string line3 = line1;
14430   if (components.search_start != url_components::omitted) {
14431     line3[components.search_start] = '`';
14432     line1[components.search_start] = ' ';
14433 
14434     for (size_t i = components.search_start + 1; i < line3.size(); i++) {
14435       line3[i] = '-';
14436     }
14437     line3.append(" search_start ");
14438     line3.append(std::to_string(components.search_start));
14439     answer.append(line3);
14440     answer.append("\n");
14441   }
14442 
14443   std::string line4 = line1;
14444   if (components.pathname_start != buffer.size()) {
14445     line4[components.pathname_start] = '`';
14446     line1[components.pathname_start] = ' ';
14447     for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
14448       line4[i] = '-';
14449     }
14450     line4.append(" pathname_start ");
14451     line4.append(std::to_string(components.pathname_start));
14452     answer.append(line4);
14453     answer.append("\n");
14454   }
14455 
14456   std::string line5 = line1;
14457   if (components.host_end != buffer.size()) {
14458     line5[components.host_end] = '`';
14459     line1[components.host_end] = ' ';
14460 
14461     for (size_t i = components.host_end + 1; i < line5.size(); i++) {
14462       line5[i] = '-';
14463     }
14464     line5.append(" host_end ");
14465     line5.append(std::to_string(components.host_end));
14466     answer.append(line5);
14467     answer.append("\n");
14468   }
14469 
14470   std::string line6 = line1;
14471   if (components.host_start != buffer.size()) {
14472     line6[components.host_start] = '`';
14473     line1[components.host_start] = ' ';
14474 
14475     for (size_t i = components.host_start + 1; i < line6.size(); i++) {
14476       line6[i] = '-';
14477     }
14478     line6.append(" host_start ");
14479     line6.append(std::to_string(components.host_start));
14480     answer.append(line6);
14481     answer.append("\n");
14482   }
14483 
14484   std::string line7 = line1;
14485   if (components.username_end != buffer.size()) {
14486     line7[components.username_end] = '`';
14487     line1[components.username_end] = ' ';
14488 
14489     for (size_t i = components.username_end + 1; i < line7.size(); i++) {
14490       line7[i] = '-';
14491     }
14492     line7.append(" username_end ");
14493     line7.append(std::to_string(components.username_end));
14494     answer.append(line7);
14495     answer.append("\n");
14496   }
14497 
14498   std::string line8 = line1;
14499   if (components.protocol_end != buffer.size()) {
14500     line8[components.protocol_end] = '`';
14501     line1[components.protocol_end] = ' ';
14502 
14503     for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
14504       line8[i] = '-';
14505     }
14506     line8.append(" protocol_end ");
14507     line8.append(std::to_string(components.protocol_end));
14508     answer.append(line8);
14509     answer.append("\n");
14510   }
14511 
14512   if (components.hash_start == url_components::omitted) {
14513     answer.append("note: hash omitted\n");
14514   }
14515   if (components.search_start == url_components::omitted) {
14516     answer.append("note: search omitted\n");
14517   }
14518   if (components.protocol_end > buffer.size()) {
14519     answer.append("warning: protocol_end overflows\n");
14520   }
14521   if (components.username_end > buffer.size()) {
14522     answer.append("warning: username_end overflows\n");
14523   }
14524   if (components.host_start > buffer.size()) {
14525     answer.append("warning: host_start overflows\n");
14526   }
14527   if (components.host_end > buffer.size()) {
14528     answer.append("warning: host_end overflows\n");
14529   }
14530   if (components.pathname_start > buffer.size()) {
14531     answer.append("warning: pathname_start overflows\n");
14532   }
14533   return answer;
14534 }
14535 
validate() const14536 [[nodiscard]] bool url_aggregator::validate() const noexcept {
14537   if (!is_valid) {
14538     return true;
14539   }
14540   if (!components.check_offset_consistency()) {
14541     ada_log("url_aggregator::validate inconsistent components \n",
14542             to_diagram());
14543     return false;
14544   }
14545   // We have a credible components struct, but let us investivate more
14546   // carefully:
14547   /**
14548    * https://user:pass@example.com:1234/foo/bar?baz#quux
14549    *       |     |    |          | ^^^^|       |   |
14550    *       |     |    |          | |   |       |   `----- hash_start
14551    *       |     |    |          | |   |       `--------- search_start
14552    *       |     |    |          | |   `----------------- pathname_start
14553    *       |     |    |          | `--------------------- port
14554    *       |     |    |          `----------------------- host_end
14555    *       |     |    `---------------------------------- host_start
14556    *       |     `--------------------------------------- username_end
14557    *       `--------------------------------------------- protocol_end
14558    */
14559   if (components.protocol_end == url_components::omitted) {
14560     ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram());
14561     return false;
14562   }
14563   if (components.username_end == url_components::omitted) {
14564     ada_log("url_aggregator::validate omitted username_end \n", to_diagram());
14565     return false;
14566   }
14567   if (components.host_start == url_components::omitted) {
14568     ada_log("url_aggregator::validate omitted host_start \n", to_diagram());
14569     return false;
14570   }
14571   if (components.host_end == url_components::omitted) {
14572     ada_log("url_aggregator::validate omitted host_end \n", to_diagram());
14573     return false;
14574   }
14575   if (components.pathname_start == url_components::omitted) {
14576     ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram());
14577     return false;
14578   }
14579 
14580   if (components.protocol_end > buffer.size()) {
14581     ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram());
14582     return false;
14583   }
14584   if (components.username_end > buffer.size()) {
14585     ada_log("url_aggregator::validate username_end overflow \n", to_diagram());
14586     return false;
14587   }
14588   if (components.host_start > buffer.size()) {
14589     ada_log("url_aggregator::validate host_start overflow \n", to_diagram());
14590     return false;
14591   }
14592   if (components.host_end > buffer.size()) {
14593     ada_log("url_aggregator::validate host_end overflow \n", to_diagram());
14594     return false;
14595   }
14596   if (components.pathname_start > buffer.size()) {
14597     ada_log("url_aggregator::validate pathname_start overflow \n",
14598             to_diagram());
14599     return false;
14600   }
14601 
14602   if (components.protocol_end > 0) {
14603     if (buffer[components.protocol_end - 1] != ':') {
14604       ada_log(
14605           "url_aggregator::validate missing : at the end of the protocol \n",
14606           to_diagram());
14607       return false;
14608     }
14609   }
14610 
14611   if (components.username_end != buffer.size() &&
14612       components.username_end > components.protocol_end + 2) {
14613     if (buffer[components.username_end] != ':' &&
14614         buffer[components.username_end] != '@') {
14615       ada_log(
14616           "url_aggregator::validate missing : or @ at the end of the username "
14617           "\n",
14618           to_diagram());
14619       return false;
14620     }
14621   }
14622 
14623   if (components.host_start != buffer.size()) {
14624     if (components.host_start > components.username_end) {
14625       if (buffer[components.host_start] != '@') {
14626         ada_log(
14627             "url_aggregator::validate missing @ at the end of the password \n",
14628             to_diagram());
14629         return false;
14630       }
14631     } else if (components.host_start == components.username_end &&
14632                components.host_end > components.host_start) {
14633       if (components.host_start == components.protocol_end + 2) {
14634         if (buffer[components.protocol_end] != '/' ||
14635             buffer[components.protocol_end + 1] != '/') {
14636           ada_log(
14637               "url_aggregator::validate missing // between protocol and host "
14638               "\n",
14639               to_diagram());
14640           return false;
14641         }
14642       } else {
14643         if (components.host_start > components.protocol_end &&
14644             buffer[components.host_start] != '@') {
14645           ada_log(
14646               "url_aggregator::validate missing @ at the end of the username "
14647               "\n",
14648               to_diagram());
14649           return false;
14650         }
14651       }
14652     } else {
14653       if (components.host_end != components.host_start) {
14654         ada_log("url_aggregator::validate expected omitted host \n",
14655                 to_diagram());
14656         return false;
14657       }
14658     }
14659   }
14660   if (components.host_end != buffer.size() &&
14661       components.pathname_start > components.host_end) {
14662     if (components.pathname_start == components.host_end + 2 &&
14663         buffer[components.host_end] == '/' &&
14664         buffer[components.host_end + 1] == '.') {
14665       if (components.pathname_start + 1 >= buffer.size() ||
14666           buffer[components.pathname_start] != '/' ||
14667           buffer[components.pathname_start + 1] != '/') {
14668         ada_log(
14669             "url_aggregator::validate expected the path to begin with // \n",
14670             to_diagram());
14671         return false;
14672       }
14673     } else if (buffer[components.host_end] != ':') {
14674       ada_log("url_aggregator::validate missing : at the port \n",
14675               to_diagram());
14676       return false;
14677     }
14678   }
14679   if (components.pathname_start != buffer.size() &&
14680       components.pathname_start < components.search_start &&
14681       components.pathname_start < components.hash_start && !has_opaque_path) {
14682     if (buffer[components.pathname_start] != '/') {
14683       ada_log("url_aggregator::validate missing / at the path \n",
14684               to_diagram());
14685       return false;
14686     }
14687   }
14688   if (components.search_start != url_components::omitted) {
14689     if (buffer[components.search_start] != '?') {
14690       ada_log("url_aggregator::validate missing ? at the search \n",
14691               to_diagram());
14692       return false;
14693     }
14694   }
14695   if (components.hash_start != url_components::omitted) {
14696     if (buffer[components.hash_start] != '#') {
14697       ada_log("url_aggregator::validate missing # at the hash \n",
14698               to_diagram());
14699       return false;
14700     }
14701   }
14702 
14703   return true;
14704 }
14705 
delete_dash_dot()14706 void url_aggregator::delete_dash_dot() {
14707   ada_log("url_aggregator::delete_dash_dot");
14708   ADA_ASSERT_TRUE(validate());
14709   ADA_ASSERT_TRUE(has_dash_dot());
14710   buffer.erase(components.host_end, 2);
14711   components.pathname_start -= 2;
14712   if (components.search_start != url_components::omitted) {
14713     components.search_start -= 2;
14714   }
14715   if (components.hash_start != url_components::omitted) {
14716     components.hash_start -= 2;
14717   }
14718   ADA_ASSERT_TRUE(validate());
14719   ADA_ASSERT_TRUE(!has_dash_dot());
14720 }
14721 
consume_prepared_path(std::string_view input)14722 inline void url_aggregator::consume_prepared_path(std::string_view input) {
14723   ada_log("url_aggregator::consume_prepared_path ", input);
14724   /***
14725    * This is largely duplicated code from helpers::parse_prepared_path, which is
14726    * unfortunate. This particular function is nearly identical, except that it
14727    * is a method on url_aggregator. The idea is that the trivial path (which is
14728    * very common) merely appends to the buffer. This is the same trivial path as
14729    * with helpers::parse_prepared_path, except that we have the additional check
14730    * for is_at_path(). Otherwise, we grab a copy of the current path and we
14731    * modify it, and then insert it back into the buffer.
14732    */
14733   uint8_t accumulator = checkers::path_signature(input);
14734   // Let us first detect a trivial case.
14735   // If it is special, we check that we have no dot, no %,  no \ and no
14736   // character needing percent encoding. Otherwise, we check that we have no %,
14737   // no dot, and no character needing percent encoding.
14738   constexpr uint8_t need_encoding = 1;
14739   constexpr uint8_t backslash_char = 2;
14740   constexpr uint8_t dot_char = 4;
14741   constexpr uint8_t percent_char = 8;
14742   bool special = type != ada::scheme::NOT_SPECIAL;
14743   bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
14744                                       checkers::is_windows_drive_letter(input));
14745   bool trivial_path =
14746       (special ? (accumulator == 0)
14747                : ((accumulator & (need_encoding | dot_char | percent_char)) ==
14748                   0)) &&
14749       (!may_need_slow_file_handling);
14750   if (accumulator == dot_char && !may_need_slow_file_handling) {
14751     // '4' means that we have at least one dot, but nothing that requires
14752     // percent encoding or decoding. The only part that is not trivial is
14753     // that we may have single dots and double dots path segments.
14754     // If we have such segments, then we either have a path that begins
14755     // with '.' (easy to check), or we have the sequence './'.
14756     // Note: input cannot be empty, it must at least contain one character ('.')
14757     // Note: we know that '\' is not present.
14758     if (input[0] != '.') {
14759       size_t slashdot = input.find("/.");
14760       if (slashdot == std::string_view::npos) {  // common case
14761         trivial_path = true;
14762       } else {  // uncommon
14763         // only three cases matter: /./, /.. or a final /
14764         trivial_path =
14765             !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
14766               input[slashdot + 2] == '/');
14767       }
14768     }
14769   }
14770   if (trivial_path && is_at_path()) {
14771     ada_log("parse_path trivial");
14772     buffer += '/';
14773     buffer += input;
14774     return;
14775   }
14776   std::string path = std::string(get_pathname());
14777   // We are going to need to look a bit at the path, but let us see if we can
14778   // ignore percent encoding *and* backslashes *and* percent characters.
14779   // Except for the trivial case, this is likely to capture 99% of paths out
14780   // there.
14781   bool fast_path =
14782       (special &&
14783        (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
14784       (type != ada::scheme::type::FILE);
14785   if (fast_path) {
14786     ada_log("parse_prepared_path fast");
14787     // Here we don't need to worry about \ or percent encoding.
14788     // We also do not have a file protocol. We might have dots, however,
14789     // but dots must as appear as '.', and they cannot be encoded because
14790     // the symbol '%' is not present.
14791     size_t previous_location = 0;  // We start at 0.
14792     do {
14793       size_t new_location = input.find('/', previous_location);
14794       // std::string_view path_view = input;
14795       //  We process the last segment separately:
14796       if (new_location == std::string_view::npos) {
14797         std::string_view path_view = input.substr(previous_location);
14798         if (path_view == "..") {  // The path ends with ..
14799           // e.g., if you receive ".." with an empty path, you go to "/".
14800           if (path.empty()) {
14801             path = '/';
14802             update_base_pathname(path);
14803             return;
14804           }
14805           // Fast case where we have nothing to do:
14806           if (path.back() == '/') {
14807             update_base_pathname(path);
14808             return;
14809           }
14810           // If you have the path "/joe/myfriend",
14811           // then you delete 'myfriend'.
14812           path.resize(path.rfind('/') + 1);
14813           update_base_pathname(path);
14814           return;
14815         }
14816         path += '/';
14817         if (path_view != ".") {
14818           path.append(path_view);
14819         }
14820         update_base_pathname(path);
14821         return;
14822       } else {
14823         // This is a non-final segment.
14824         std::string_view path_view =
14825             input.substr(previous_location, new_location - previous_location);
14826         previous_location = new_location + 1;
14827         if (path_view == "..") {
14828           size_t last_delimiter = path.rfind('/');
14829           if (last_delimiter != std::string::npos) {
14830             path.erase(last_delimiter);
14831           }
14832         } else if (path_view != ".") {
14833           path += '/';
14834           path.append(path_view);
14835         }
14836       }
14837     } while (true);
14838   } else {
14839     ada_log("parse_path slow");
14840     // we have reached the general case
14841     bool needs_percent_encoding = (accumulator & 1);
14842     std::string path_buffer_tmp;
14843     do {
14844       size_t location = (special && (accumulator & 2))
14845                             ? input.find_first_of("/\\")
14846                             : input.find('/');
14847       std::string_view path_view = input;
14848       if (location != std::string_view::npos) {
14849         path_view.remove_suffix(path_view.size() - location);
14850         input.remove_prefix(location + 1);
14851       }
14852       // path_buffer is either path_view or it might point at a percent encoded
14853       // temporary string.
14854       std::string_view path_buffer =
14855           (needs_percent_encoding &&
14856            ada::unicode::percent_encode<false>(
14857                path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
14858               ? path_buffer_tmp
14859               : path_view;
14860       if (unicode::is_double_dot_path_segment(path_buffer)) {
14861         if ((helpers::shorten_path(path, type) || special) &&
14862             location == std::string_view::npos) {
14863           path += '/';
14864         }
14865       } else if (unicode::is_single_dot_path_segment(path_buffer) &&
14866                  (location == std::string_view::npos)) {
14867         path += '/';
14868       }
14869       // Otherwise, if path_buffer is not a single-dot path segment, then:
14870       else if (!unicode::is_single_dot_path_segment(path_buffer)) {
14871         // If url's scheme is "file", url's path is empty, and path_buffer is a
14872         // Windows drive letter, then replace the second code point in
14873         // path_buffer with U+003A (:).
14874         if (type == ada::scheme::type::FILE && path.empty() &&
14875             checkers::is_windows_drive_letter(path_buffer)) {
14876           path += '/';
14877           path += path_buffer[0];
14878           path += ':';
14879           path_buffer.remove_prefix(2);
14880           path.append(path_buffer);
14881         } else {
14882           // Append path_buffer to url's path.
14883           path += '/';
14884           path.append(path_buffer);
14885         }
14886       }
14887       if (location == std::string_view::npos) {
14888         update_base_pathname(path);
14889         return;
14890       }
14891     } while (true);
14892   }
14893 }
14894 }  // namespace ada
14895 /* end file src/url_aggregator.cpp */
14896 /* begin file src/ada_c.cpp */
14897 
get_instance(void * result)14898 ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
14899   return *(ada::result<ada::url_aggregator>*)result;
14900 }
14901 
14902 extern "C" {
14903 typedef void* ada_url;
14904 typedef void* ada_url_search_params;
14905 typedef void* ada_strings;
14906 typedef void* ada_url_search_params_keys_iter;
14907 typedef void* ada_url_search_params_values_iter;
14908 typedef void* ada_url_search_params_entries_iter;
14909 
14910 struct ada_string {
14911   const char* data;
14912   size_t length;
14913 };
14914 
14915 struct ada_owned_string {
14916   const char* data;
14917   size_t length;
14918 };
14919 
14920 struct ada_string_pair {
14921   ada_string key;
14922   ada_string value;
14923 };
14924 
ada_string_create(const char * data,size_t length)14925 ada_string ada_string_create(const char* data, size_t length) {
14926   ada_string out{};
14927   out.data = data;
14928   out.length = length;
14929   return out;
14930 }
14931 
14932 struct ada_url_components {
14933   /*
14934    * By using 32-bit integers, we implicitly assume that the URL string
14935    * cannot exceed 4 GB.
14936    *
14937    * https://user:pass@example.com:1234/foo/bar?baz#quux
14938    *       |     |    |          | ^^^^|       |   |
14939    *       |     |    |          | |   |       |   `----- hash_start
14940    *       |     |    |          | |   |       `--------- search_start
14941    *       |     |    |          | |   `----------------- pathname_start
14942    *       |     |    |          | `--------------------- port
14943    *       |     |    |          `----------------------- host_end
14944    *       |     |    `---------------------------------- host_start
14945    *       |     `--------------------------------------- username_end
14946    *       `--------------------------------------------- protocol_end
14947    */
14948   uint32_t protocol_end;
14949   /**
14950    * Username end is not `omitted` by default (-1) to make username and password
14951    * getters less costly to implement.
14952    */
14953   uint32_t username_end;
14954   uint32_t host_start;
14955   uint32_t host_end;
14956   uint32_t port;
14957   uint32_t pathname_start;
14958   uint32_t search_start;
14959   uint32_t hash_start;
14960 };
14961 
ada_parse(const char * input,size_t length)14962 ada_url ada_parse(const char* input, size_t length) noexcept {
14963   return new ada::result<ada::url_aggregator>(
14964       ada::parse<ada::url_aggregator>(std::string_view(input, length)));
14965 }
14966 
ada_parse_with_base(const char * input,size_t input_length,const char * base,size_t base_length)14967 ada_url ada_parse_with_base(const char* input, size_t input_length,
14968                             const char* base, size_t base_length) noexcept {
14969   auto base_out =
14970       ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
14971 
14972   if (!base_out) {
14973     return new ada::result<ada::url_aggregator>(base_out);
14974   }
14975 
14976   return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
14977       std::string_view(input, input_length), &base_out.value()));
14978 }
14979 
ada_can_parse(const char * input,size_t length)14980 bool ada_can_parse(const char* input, size_t length) noexcept {
14981   return ada::can_parse(std::string_view(input, length));
14982 }
14983 
ada_can_parse_with_base(const char * input,size_t input_length,const char * base,size_t base_length)14984 bool ada_can_parse_with_base(const char* input, size_t input_length,
14985                              const char* base, size_t base_length) noexcept {
14986   auto base_view = std::string_view(base, base_length);
14987   return ada::can_parse(std::string_view(input, input_length), &base_view);
14988 }
14989 
ada_free(ada_url result)14990 void ada_free(ada_url result) noexcept {
14991   ada::result<ada::url_aggregator>* r =
14992       (ada::result<ada::url_aggregator>*)result;
14993   delete r;
14994 }
14995 
ada_copy(ada_url input)14996 ada_url ada_copy(ada_url input) noexcept {
14997   ada::result<ada::url_aggregator>& r = get_instance(input);
14998   return new ada::result<ada::url_aggregator>(r);
14999 }
15000 
ada_is_valid(ada_url result)15001 bool ada_is_valid(ada_url result) noexcept {
15002   ada::result<ada::url_aggregator>& r = get_instance(result);
15003   return r.has_value();
15004 }
15005 
15006 // caller must free the result with ada_free_owned_string
ada_get_origin(ada_url result)15007 ada_owned_string ada_get_origin(ada_url result) noexcept {
15008   ada::result<ada::url_aggregator>& r = get_instance(result);
15009   ada_owned_string owned;
15010   if (!r) {
15011     owned.data = nullptr;
15012     owned.length = 0;
15013     return owned;
15014   }
15015   std::string out = r->get_origin();
15016   owned.length = out.size();
15017   owned.data = new char[owned.length];
15018   memcpy((void*)owned.data, out.data(), owned.length);
15019   return owned;
15020 }
15021 
ada_free_owned_string(ada_owned_string owned)15022 void ada_free_owned_string(ada_owned_string owned) noexcept {
15023   delete[] owned.data;
15024   owned.data = nullptr;
15025   owned.length = 0;
15026 }
15027 
ada_get_href(ada_url result)15028 ada_string ada_get_href(ada_url result) noexcept {
15029   ada::result<ada::url_aggregator>& r = get_instance(result);
15030   if (!r) {
15031     return ada_string_create(NULL, 0);
15032   }
15033   std::string_view out = r->get_href();
15034   return ada_string_create(out.data(), out.length());
15035 }
15036 
ada_get_username(ada_url result)15037 ada_string ada_get_username(ada_url result) noexcept {
15038   ada::result<ada::url_aggregator>& r = get_instance(result);
15039   if (!r) {
15040     return ada_string_create(NULL, 0);
15041   }
15042   std::string_view out = r->get_username();
15043   return ada_string_create(out.data(), out.length());
15044 }
15045 
ada_get_password(ada_url result)15046 ada_string ada_get_password(ada_url result) noexcept {
15047   ada::result<ada::url_aggregator>& r = get_instance(result);
15048   if (!r) {
15049     return ada_string_create(NULL, 0);
15050   }
15051   std::string_view out = r->get_password();
15052   return ada_string_create(out.data(), out.length());
15053 }
15054 
ada_get_port(ada_url result)15055 ada_string ada_get_port(ada_url result) noexcept {
15056   ada::result<ada::url_aggregator>& r = get_instance(result);
15057   if (!r) {
15058     return ada_string_create(NULL, 0);
15059   }
15060   std::string_view out = r->get_port();
15061   return ada_string_create(out.data(), out.length());
15062 }
15063 
ada_get_hash(ada_url result)15064 ada_string ada_get_hash(ada_url result) noexcept {
15065   ada::result<ada::url_aggregator>& r = get_instance(result);
15066   if (!r) {
15067     return ada_string_create(NULL, 0);
15068   }
15069   std::string_view out = r->get_hash();
15070   return ada_string_create(out.data(), out.length());
15071 }
15072 
ada_get_host(ada_url result)15073 ada_string ada_get_host(ada_url result) noexcept {
15074   ada::result<ada::url_aggregator>& r = get_instance(result);
15075   if (!r) {
15076     return ada_string_create(NULL, 0);
15077   }
15078   std::string_view out = r->get_host();
15079   return ada_string_create(out.data(), out.length());
15080 }
15081 
ada_get_hostname(ada_url result)15082 ada_string ada_get_hostname(ada_url result) noexcept {
15083   ada::result<ada::url_aggregator>& r = get_instance(result);
15084   if (!r) {
15085     return ada_string_create(NULL, 0);
15086   }
15087   std::string_view out = r->get_hostname();
15088   return ada_string_create(out.data(), out.length());
15089 }
15090 
ada_get_pathname(ada_url result)15091 ada_string ada_get_pathname(ada_url result) noexcept {
15092   ada::result<ada::url_aggregator>& r = get_instance(result);
15093   if (!r) {
15094     return ada_string_create(NULL, 0);
15095   }
15096   std::string_view out = r->get_pathname();
15097   return ada_string_create(out.data(), out.length());
15098 }
15099 
ada_get_search(ada_url result)15100 ada_string ada_get_search(ada_url result) noexcept {
15101   ada::result<ada::url_aggregator>& r = get_instance(result);
15102   if (!r) {
15103     return ada_string_create(NULL, 0);
15104   }
15105   std::string_view out = r->get_search();
15106   return ada_string_create(out.data(), out.length());
15107 }
15108 
ada_get_protocol(ada_url result)15109 ada_string ada_get_protocol(ada_url result) noexcept {
15110   ada::result<ada::url_aggregator>& r = get_instance(result);
15111   if (!r) {
15112     return ada_string_create(NULL, 0);
15113   }
15114   std::string_view out = r->get_protocol();
15115   return ada_string_create(out.data(), out.length());
15116 }
15117 
ada_get_host_type(ada_url result)15118 uint8_t ada_get_host_type(ada_url result) noexcept {
15119   ada::result<ada::url_aggregator>& r = get_instance(result);
15120   if (!r) {
15121     return 0;
15122   }
15123   return r->host_type;
15124 }
15125 
ada_get_scheme_type(ada_url result)15126 uint8_t ada_get_scheme_type(ada_url result) noexcept {
15127   ada::result<ada::url_aggregator>& r = get_instance(result);
15128   if (!r) {
15129     return 0;
15130   }
15131   return r->type;
15132 }
15133 
ada_set_href(ada_url result,const char * input,size_t length)15134 bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
15135   ada::result<ada::url_aggregator>& r = get_instance(result);
15136   if (!r) {
15137     return false;
15138   }
15139   return r->set_href(std::string_view(input, length));
15140 }
15141 
ada_set_host(ada_url result,const char * input,size_t length)15142 bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
15143   ada::result<ada::url_aggregator>& r = get_instance(result);
15144   if (!r) {
15145     return false;
15146   }
15147   return r->set_host(std::string_view(input, length));
15148 }
15149 
ada_set_hostname(ada_url result,const char * input,size_t length)15150 bool ada_set_hostname(ada_url result, const char* input,
15151                       size_t length) noexcept {
15152   ada::result<ada::url_aggregator>& r = get_instance(result);
15153   if (!r) {
15154     return false;
15155   }
15156   return r->set_hostname(std::string_view(input, length));
15157 }
15158 
ada_set_protocol(ada_url result,const char * input,size_t length)15159 bool ada_set_protocol(ada_url result, const char* input,
15160                       size_t length) noexcept {
15161   ada::result<ada::url_aggregator>& r = get_instance(result);
15162   if (!r) {
15163     return false;
15164   }
15165   return r->set_protocol(std::string_view(input, length));
15166 }
15167 
ada_set_username(ada_url result,const char * input,size_t length)15168 bool ada_set_username(ada_url result, const char* input,
15169                       size_t length) noexcept {
15170   ada::result<ada::url_aggregator>& r = get_instance(result);
15171   if (!r) {
15172     return false;
15173   }
15174   return r->set_username(std::string_view(input, length));
15175 }
15176 
ada_set_password(ada_url result,const char * input,size_t length)15177 bool ada_set_password(ada_url result, const char* input,
15178                       size_t length) noexcept {
15179   ada::result<ada::url_aggregator>& r = get_instance(result);
15180   if (!r) {
15181     return false;
15182   }
15183   return r->set_password(std::string_view(input, length));
15184 }
15185 
ada_set_port(ada_url result,const char * input,size_t length)15186 bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
15187   ada::result<ada::url_aggregator>& r = get_instance(result);
15188   if (!r) {
15189     return false;
15190   }
15191   return r->set_port(std::string_view(input, length));
15192 }
15193 
ada_set_pathname(ada_url result,const char * input,size_t length)15194 bool ada_set_pathname(ada_url result, const char* input,
15195                       size_t length) noexcept {
15196   ada::result<ada::url_aggregator>& r = get_instance(result);
15197   if (!r) {
15198     return false;
15199   }
15200   return r->set_pathname(std::string_view(input, length));
15201 }
15202 
15203 /**
15204  * Update the search/query of the URL.
15205  *
15206  * If a URL has `?` as the search value, passing empty string to this function
15207  * does not remove the attribute. If you need to remove it, please use
15208  * `ada_clear_search` method.
15209  */
ada_set_search(ada_url result,const char * input,size_t length)15210 void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
15211   ada::result<ada::url_aggregator>& r = get_instance(result);
15212   if (r) {
15213     r->set_search(std::string_view(input, length));
15214   }
15215 }
15216 
15217 /**
15218  * Update the hash/fragment of the URL.
15219  *
15220  * If a URL has `#` as the hash value, passing empty string to this function
15221  * does not remove the attribute. If you need to remove it, please use
15222  * `ada_clear_hash` method.
15223  */
ada_set_hash(ada_url result,const char * input,size_t length)15224 void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
15225   ada::result<ada::url_aggregator>& r = get_instance(result);
15226   if (r) {
15227     r->set_hash(std::string_view(input, length));
15228   }
15229 }
15230 
ada_clear_port(ada_url result)15231 void ada_clear_port(ada_url result) noexcept {
15232   ada::result<ada::url_aggregator>& r = get_instance(result);
15233   if (r) {
15234     r->clear_port();
15235   }
15236 }
15237 
15238 /**
15239  * Removes the hash of the URL.
15240  *
15241  * Despite `ada_set_hash` method, this function allows the complete
15242  * removal of the hash attribute, even if it has a value of `#`.
15243  */
ada_clear_hash(ada_url result)15244 void ada_clear_hash(ada_url result) noexcept {
15245   ada::result<ada::url_aggregator>& r = get_instance(result);
15246   if (r) {
15247     r->clear_hash();
15248   }
15249 }
15250 
15251 /**
15252  * Removes the search of the URL.
15253  *
15254  * Despite `ada_set_search` method, this function allows the complete
15255  * removal of the search attribute, even if it has a value of `?`.
15256  */
ada_clear_search(ada_url result)15257 void ada_clear_search(ada_url result) noexcept {
15258   ada::result<ada::url_aggregator>& r = get_instance(result);
15259   if (r) {
15260     r->clear_search();
15261   }
15262 }
15263 
ada_has_credentials(ada_url result)15264 bool ada_has_credentials(ada_url result) noexcept {
15265   ada::result<ada::url_aggregator>& r = get_instance(result);
15266   if (!r) {
15267     return false;
15268   }
15269   return r->has_credentials();
15270 }
15271 
ada_has_empty_hostname(ada_url result)15272 bool ada_has_empty_hostname(ada_url result) noexcept {
15273   ada::result<ada::url_aggregator>& r = get_instance(result);
15274   if (!r) {
15275     return false;
15276   }
15277   return r->has_empty_hostname();
15278 }
15279 
ada_has_hostname(ada_url result)15280 bool ada_has_hostname(ada_url result) noexcept {
15281   ada::result<ada::url_aggregator>& r = get_instance(result);
15282   if (!r) {
15283     return false;
15284   }
15285   return r->has_hostname();
15286 }
15287 
ada_has_non_empty_username(ada_url result)15288 bool ada_has_non_empty_username(ada_url result) noexcept {
15289   ada::result<ada::url_aggregator>& r = get_instance(result);
15290   if (!r) {
15291     return false;
15292   }
15293   return r->has_non_empty_username();
15294 }
15295 
ada_has_non_empty_password(ada_url result)15296 bool ada_has_non_empty_password(ada_url result) noexcept {
15297   ada::result<ada::url_aggregator>& r = get_instance(result);
15298   if (!r) {
15299     return false;
15300   }
15301   return r->has_non_empty_password();
15302 }
15303 
ada_has_port(ada_url result)15304 bool ada_has_port(ada_url result) noexcept {
15305   ada::result<ada::url_aggregator>& r = get_instance(result);
15306   if (!r) {
15307     return false;
15308   }
15309   return r->has_port();
15310 }
15311 
ada_has_password(ada_url result)15312 bool ada_has_password(ada_url result) noexcept {
15313   ada::result<ada::url_aggregator>& r = get_instance(result);
15314   if (!r) {
15315     return false;
15316   }
15317   return r->has_password();
15318 }
15319 
ada_has_hash(ada_url result)15320 bool ada_has_hash(ada_url result) noexcept {
15321   ada::result<ada::url_aggregator>& r = get_instance(result);
15322   if (!r) {
15323     return false;
15324   }
15325   return r->has_hash();
15326 }
15327 
ada_has_search(ada_url result)15328 bool ada_has_search(ada_url result) noexcept {
15329   ada::result<ada::url_aggregator>& r = get_instance(result);
15330   if (!r) {
15331     return false;
15332   }
15333   return r->has_search();
15334 }
15335 
15336 // returns a pointer to the internal url_aggregator::url_components
ada_get_components(ada_url result)15337 const ada_url_components* ada_get_components(ada_url result) noexcept {
15338   static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
15339   ada::result<ada::url_aggregator>& r = get_instance(result);
15340   if (!r) {
15341     return nullptr;
15342   }
15343   return reinterpret_cast<const ada_url_components*>(&r->get_components());
15344 }
15345 
ada_idna_to_unicode(const char * input,size_t length)15346 ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
15347   std::string out = ada::idna::to_unicode(std::string_view(input, length));
15348   ada_owned_string owned{};
15349   owned.length = out.length();
15350   owned.data = new char[owned.length];
15351   memcpy((void*)owned.data, out.data(), owned.length);
15352   return owned;
15353 }
15354 
ada_idna_to_ascii(const char * input,size_t length)15355 ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
15356   std::string out = ada::idna::to_ascii(std::string_view(input, length));
15357   ada_owned_string owned{};
15358   owned.length = out.size();
15359   owned.data = new char[owned.length];
15360   memcpy((void*)owned.data, out.data(), owned.length);
15361   return owned;
15362 }
15363 
ada_parse_search_params(const char * input,size_t length)15364 ada_url_search_params ada_parse_search_params(const char* input,
15365                                               size_t length) {
15366   return new ada::result<ada::url_search_params>(
15367       ada::url_search_params(std::string_view(input, length)));
15368 }
15369 
ada_free_search_params(ada_url_search_params result)15370 void ada_free_search_params(ada_url_search_params result) {
15371   ada::result<ada::url_search_params>* r =
15372       (ada::result<ada::url_search_params>*)result;
15373   delete r;
15374 }
15375 
ada_search_params_to_string(ada_url_search_params result)15376 ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
15377   ada::result<ada::url_search_params>& r =
15378       *(ada::result<ada::url_search_params>*)result;
15379   if (!r) return ada_owned_string{NULL, 0};
15380   std::string out = r->to_string();
15381   ada_owned_string owned{};
15382   owned.length = out.size();
15383   owned.data = new char[owned.length];
15384   memcpy((void*)owned.data, out.data(), owned.length);
15385   return owned;
15386 }
15387 
ada_search_params_size(ada_url_search_params result)15388 size_t ada_search_params_size(ada_url_search_params result) {
15389   ada::result<ada::url_search_params>& r =
15390       *(ada::result<ada::url_search_params>*)result;
15391   if (!r) return 0;
15392   return r->size();
15393 }
15394 
ada_search_params_sort(ada_url_search_params result)15395 void ada_search_params_sort(ada_url_search_params result) {
15396   ada::result<ada::url_search_params>& r =
15397       *(ada::result<ada::url_search_params>*)result;
15398   if (r) r->sort();
15399 }
15400 
ada_search_params_append(ada_url_search_params result,const char * key,size_t key_length,const char * value,size_t value_length)15401 void ada_search_params_append(ada_url_search_params result, const char* key,
15402                               size_t key_length, const char* value,
15403                               size_t value_length) {
15404   ada::result<ada::url_search_params>& r =
15405       *(ada::result<ada::url_search_params>*)result;
15406   if (r) {
15407     r->append(std::string_view(key, key_length),
15408               std::string_view(value, value_length));
15409   }
15410 }
15411 
ada_search_params_set(ada_url_search_params result,const char * key,size_t key_length,const char * value,size_t value_length)15412 void ada_search_params_set(ada_url_search_params result, const char* key,
15413                            size_t key_length, const char* value,
15414                            size_t value_length) {
15415   ada::result<ada::url_search_params>& r =
15416       *(ada::result<ada::url_search_params>*)result;
15417   if (r) {
15418     r->set(std::string_view(key, key_length),
15419            std::string_view(value, value_length));
15420   }
15421 }
15422 
ada_search_params_remove(ada_url_search_params result,const char * key,size_t key_length)15423 void ada_search_params_remove(ada_url_search_params result, const char* key,
15424                               size_t key_length) {
15425   ada::result<ada::url_search_params>& r =
15426       *(ada::result<ada::url_search_params>*)result;
15427   if (r) {
15428     r->remove(std::string_view(key, key_length));
15429   }
15430 }
15431 
ada_search_params_remove_value(ada_url_search_params result,const char * key,size_t key_length,const char * value,size_t value_length)15432 void ada_search_params_remove_value(ada_url_search_params result,
15433                                     const char* key, size_t key_length,
15434                                     const char* value, size_t value_length) {
15435   ada::result<ada::url_search_params>& r =
15436       *(ada::result<ada::url_search_params>*)result;
15437   if (r) {
15438     r->remove(std::string_view(key, key_length),
15439               std::string_view(value, value_length));
15440   }
15441 }
15442 
ada_search_params_has(ada_url_search_params result,const char * key,size_t key_length)15443 bool ada_search_params_has(ada_url_search_params result, const char* key,
15444                            size_t key_length) {
15445   ada::result<ada::url_search_params>& r =
15446       *(ada::result<ada::url_search_params>*)result;
15447   if (!r) return false;
15448   return r->has(std::string_view(key, key_length));
15449 }
15450 
ada_search_params_has_value(ada_url_search_params result,const char * key,size_t key_length,const char * value,size_t value_length)15451 bool ada_search_params_has_value(ada_url_search_params result, const char* key,
15452                                  size_t key_length, const char* value,
15453                                  size_t value_length) {
15454   ada::result<ada::url_search_params>& r =
15455       *(ada::result<ada::url_search_params>*)result;
15456   if (!r) return false;
15457   return r->has(std::string_view(key, key_length),
15458                 std::string_view(value, value_length));
15459 }
15460 
ada_search_params_get(ada_url_search_params result,const char * key,size_t key_length)15461 ada_string ada_search_params_get(ada_url_search_params result, const char* key,
15462                                  size_t key_length) {
15463   ada::result<ada::url_search_params>& r =
15464       *(ada::result<ada::url_search_params>*)result;
15465   if (!r) return ada_string_create(NULL, 0);
15466   auto found = r->get(std::string_view(key, key_length));
15467   if (!found.has_value()) return ada_string_create(NULL, 0);
15468   return ada_string_create(found->data(), found->length());
15469 }
15470 
ada_search_params_get_all(ada_url_search_params result,const char * key,size_t key_length)15471 ada_strings ada_search_params_get_all(ada_url_search_params result,
15472                                       const char* key, size_t key_length) {
15473   ada::result<ada::url_search_params>& r =
15474       *(ada::result<ada::url_search_params>*)result;
15475   if (!r) {
15476     return new ada::result<std::vector<std::string>>(
15477         std::vector<std::string>());
15478   }
15479   return new ada::result<std::vector<std::string>>(
15480       r->get_all(std::string_view(key, key_length)));
15481 }
15482 
ada_search_params_get_keys(ada_url_search_params result)15483 ada_url_search_params_keys_iter ada_search_params_get_keys(
15484     ada_url_search_params result) {
15485   ada::result<ada::url_search_params>& r =
15486       *(ada::result<ada::url_search_params>*)result;
15487   if (!r) {
15488     return new ada::result<ada::url_search_params_keys_iter>(
15489         ada::url_search_params_keys_iter());
15490   }
15491   return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
15492 }
15493 
ada_search_params_get_values(ada_url_search_params result)15494 ada_url_search_params_values_iter ada_search_params_get_values(
15495     ada_url_search_params result) {
15496   ada::result<ada::url_search_params>& r =
15497       *(ada::result<ada::url_search_params>*)result;
15498   if (!r) {
15499     return new ada::result<ada::url_search_params_values_iter>(
15500         ada::url_search_params_values_iter());
15501   }
15502   return new ada::result<ada::url_search_params_values_iter>(r->get_values());
15503 }
15504 
ada_search_params_get_entries(ada_url_search_params result)15505 ada_url_search_params_entries_iter ada_search_params_get_entries(
15506     ada_url_search_params result) {
15507   ada::result<ada::url_search_params>& r =
15508       *(ada::result<ada::url_search_params>*)result;
15509   if (!r) {
15510     return new ada::result<ada::url_search_params_entries_iter>(
15511         ada::url_search_params_entries_iter());
15512   }
15513   return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
15514 }
15515 
ada_free_strings(ada_strings result)15516 void ada_free_strings(ada_strings result) {
15517   ada::result<std::vector<std::string>>* r =
15518       (ada::result<std::vector<std::string>>*)result;
15519   delete r;
15520 }
15521 
ada_strings_size(ada_strings result)15522 size_t ada_strings_size(ada_strings result) {
15523   ada::result<std::vector<std::string>>* r =
15524       (ada::result<std::vector<std::string>>*)result;
15525   if (!r) return 0;
15526   return (*r)->size();
15527 }
15528 
ada_strings_get(ada_strings result,size_t index)15529 ada_string ada_strings_get(ada_strings result, size_t index) {
15530   ada::result<std::vector<std::string>>* r =
15531       (ada::result<std::vector<std::string>>*)result;
15532   if (!r) return ada_string_create(NULL, 0);
15533   std::string_view view = (*r)->at(index);
15534   return ada_string_create(view.data(), view.length());
15535 }
15536 
ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result)15537 void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
15538   ada::result<ada::url_search_params_keys_iter>* r =
15539       (ada::result<ada::url_search_params_keys_iter>*)result;
15540   delete r;
15541 }
15542 
ada_search_params_keys_iter_next(ada_url_search_params_keys_iter result)15543 ada_string ada_search_params_keys_iter_next(
15544     ada_url_search_params_keys_iter result) {
15545   ada::result<ada::url_search_params_keys_iter>* r =
15546       (ada::result<ada::url_search_params_keys_iter>*)result;
15547   if (!r) return ada_string_create(NULL, 0);
15548   auto next = (*r)->next();
15549   if (!next.has_value()) return ada_string_create(NULL, 0);
15550   return ada_string_create(next->data(), next->length());
15551 }
15552 
ada_search_params_keys_iter_has_next(ada_url_search_params_keys_iter result)15553 bool ada_search_params_keys_iter_has_next(
15554     ada_url_search_params_keys_iter result) {
15555   ada::result<ada::url_search_params_keys_iter>* r =
15556       (ada::result<ada::url_search_params_keys_iter>*)result;
15557   if (!r) return false;
15558   return (*r)->has_next();
15559 }
15560 
ada_free_search_params_values_iter(ada_url_search_params_values_iter result)15561 void ada_free_search_params_values_iter(
15562     ada_url_search_params_values_iter result) {
15563   ada::result<ada::url_search_params_values_iter>* r =
15564       (ada::result<ada::url_search_params_values_iter>*)result;
15565   delete r;
15566 }
15567 
ada_search_params_values_iter_next(ada_url_search_params_values_iter result)15568 ada_string ada_search_params_values_iter_next(
15569     ada_url_search_params_values_iter result) {
15570   ada::result<ada::url_search_params_values_iter>* r =
15571       (ada::result<ada::url_search_params_values_iter>*)result;
15572   if (!r) return ada_string_create(NULL, 0);
15573   auto next = (*r)->next();
15574   if (!next.has_value()) return ada_string_create(NULL, 0);
15575   return ada_string_create(next->data(), next->length());
15576 }
15577 
ada_search_params_values_iter_has_next(ada_url_search_params_values_iter result)15578 bool ada_search_params_values_iter_has_next(
15579     ada_url_search_params_values_iter result) {
15580   ada::result<ada::url_search_params_values_iter>* r =
15581       (ada::result<ada::url_search_params_values_iter>*)result;
15582   if (!r) return false;
15583   return (*r)->has_next();
15584 }
15585 
ada_free_search_params_entries_iter(ada_url_search_params_entries_iter result)15586 void ada_free_search_params_entries_iter(
15587     ada_url_search_params_entries_iter result) {
15588   ada::result<ada::url_search_params_entries_iter>* r =
15589       (ada::result<ada::url_search_params_entries_iter>*)result;
15590   delete r;
15591 }
15592 
ada_search_params_entries_iter_next(ada_url_search_params_entries_iter result)15593 ada_string_pair ada_search_params_entries_iter_next(
15594     ada_url_search_params_entries_iter result) {
15595   ada::result<ada::url_search_params_entries_iter>* r =
15596       (ada::result<ada::url_search_params_entries_iter>*)result;
15597   if (!r) return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)};
15598   auto next = (*r)->next();
15599   if (!next.has_value())
15600     return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)};
15601   return ada_string_pair{
15602       ada_string_create(next->first.data(), next->first.length()),
15603       ada_string_create(next->second.data(), next->second.length())};
15604 }
15605 
ada_search_params_entries_iter_has_next(ada_url_search_params_entries_iter result)15606 bool ada_search_params_entries_iter_has_next(
15607     ada_url_search_params_entries_iter result) {
15608   ada::result<ada::url_search_params_entries_iter>* r =
15609       (ada::result<ada::url_search_params_entries_iter>*)result;
15610   if (!r) return false;
15611   return (*r)->has_next();
15612 }
15613 
15614 }  // extern "C"
15615 /* end file src/ada_c.cpp */
15616 /* end file src/ada.cpp */
15617