• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* auto-generated on 2023-07-23 15:03:22 -0400. 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   size_t last_dot = view.rfind('.');
11   if (last_dot == view.size() - 1) {
12     view.remove_suffix(1);
13     last_dot = view.rfind('.');
14   }
15   std::string_view number =
16       (last_dot == std::string_view::npos) ? view : view.substr(last_dot + 1);
17   if (number.empty()) {
18     return false;
19   }
20   /** Optimization opportunity: we have basically identified the last number of
21      the ipv4 if we return true here. We might as well parse it and have at
22      least one number parsed when we get to parse_ipv4. */
23   if (std::all_of(number.begin(), number.end(), ada::checkers::is_digit)) {
24     return true;
25   }
26   return (checkers::has_hex_prefix(number) &&
27           std::all_of(number.begin() + 2, number.end(),
28                       ada::unicode::is_lowercase_hex));
29 }
30 
31 // for use with path_signature, we include all characters that need percent
32 // encoding.
33 static constexpr uint8_t path_signature_table[256] = {
34     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
35     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
36     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
37     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
38     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39     0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
41     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
42     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
43     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
44     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
45 static_assert(path_signature_table[uint8_t('?')] == 1);
46 static_assert(path_signature_table[uint8_t('`')] == 1);
47 static_assert(path_signature_table[uint8_t('{')] == 1);
48 static_assert(path_signature_table[uint8_t('}')] == 1);
49 //
50 static_assert(path_signature_table[uint8_t(' ')] == 1);
51 static_assert(path_signature_table[uint8_t('?')] == 1);
52 static_assert(path_signature_table[uint8_t('"')] == 1);
53 static_assert(path_signature_table[uint8_t('#')] == 1);
54 static_assert(path_signature_table[uint8_t('<')] == 1);
55 static_assert(path_signature_table[uint8_t('>')] == 1);
56 static_assert(path_signature_table[uint8_t('\\')] == 2);
57 static_assert(path_signature_table[uint8_t('.')] == 4);
58 static_assert(path_signature_table[uint8_t('%')] == 8);
59 
60 //
61 static_assert(path_signature_table[0] == 1);
62 static_assert(path_signature_table[31] == 1);
63 static_assert(path_signature_table[127] == 1);
64 static_assert(path_signature_table[128] == 1);
65 static_assert(path_signature_table[255] == 1);
66 
path_signature(std::string_view input)67 ada_really_inline constexpr uint8_t path_signature(
68     std::string_view input) noexcept {
69   // The path percent-encode set is the query percent-encode set and U+003F (?),
70   // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
71   // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
72   // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
73   // controls and all code points greater than U+007E (~).
74   size_t i = 0;
75   uint8_t accumulator{};
76   for (; i + 7 < input.size(); i += 8) {
77     accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
78                            path_signature_table[uint8_t(input[i + 1])] |
79                            path_signature_table[uint8_t(input[i + 2])] |
80                            path_signature_table[uint8_t(input[i + 3])] |
81                            path_signature_table[uint8_t(input[i + 4])] |
82                            path_signature_table[uint8_t(input[i + 5])] |
83                            path_signature_table[uint8_t(input[i + 6])] |
84                            path_signature_table[uint8_t(input[i + 7])]);
85   }
86   for (; i < input.size(); i++) {
87     accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
88   }
89   return accumulator;
90 }
91 
verify_dns_length(std::string_view input)92 ada_really_inline constexpr bool verify_dns_length(
93     std::string_view input) noexcept {
94   if (input.back() == '.') {
95     if (input.size() > 254) return false;
96   } else if (input.size() > 253)
97     return false;
98 
99   size_t start = 0;
100   while (start < input.size()) {
101     auto dot_location = input.find('.', start);
102     // If not found, it's likely the end of the domain
103     if (dot_location == std::string_view::npos) dot_location = input.size();
104 
105     auto label_size = dot_location - start;
106     if (label_size > 63 || label_size == 0) return false;
107 
108     start = dot_location + 1;
109   }
110 
111   return true;
112 }
113 }  // namespace ada::checkers
114 /* end file src/checkers.cpp */
115 /* begin file src/unicode.cpp */
116 
117 ADA_PUSH_DISABLE_ALL_WARNINGS
118 /* begin file src/ada_idna.cpp */
119 /* auto-generated on 2023-05-07 19:12:14 -0400. Do not edit! */
120 /* begin file src/idna.cpp */
121 /* begin file src/unicode_transcoding.cpp */
122 
123 #include <cstdint>
124 #include <cstring>
125 
126 namespace ada::idna {
127 
utf8_to_utf32(const char * buf,size_t len,char32_t * utf32_output)128 size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
129   const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
130   size_t pos = 0;
131   char32_t* start{utf32_output};
132   while (pos < len) {
133     // try to convert the next block of 16 ASCII bytes
134     if (pos + 16 <= len) {  // if it is safe to read 16 more
135                             // bytes, check that they are ascii
136       uint64_t v1;
137       std::memcpy(&v1, data + pos, sizeof(uint64_t));
138       uint64_t v2;
139       std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
140       uint64_t v{v1 | v2};
141       if ((v & 0x8080808080808080) == 0) {
142         size_t final_pos = pos + 16;
143         while (pos < final_pos) {
144           *utf32_output++ = char32_t(buf[pos]);
145           pos++;
146         }
147         continue;
148       }
149     }
150     uint8_t leading_byte = data[pos];  // leading byte
151     if (leading_byte < 0b10000000) {
152       // converting one ASCII byte !!!
153       *utf32_output++ = char32_t(leading_byte);
154       pos++;
155     } else if ((leading_byte & 0b11100000) == 0b11000000) {
156       // We have a two-byte UTF-8
157       if (pos + 1 >= len) {
158         return 0;
159       }  // minimal bound checking
160       if ((data[pos + 1] & 0b11000000) != 0b10000000) {
161         return 0;
162       }
163       // range check
164       uint32_t code_point =
165           (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
166       if (code_point < 0x80 || 0x7ff < code_point) {
167         return 0;
168       }
169       *utf32_output++ = char32_t(code_point);
170       pos += 2;
171     } else if ((leading_byte & 0b11110000) == 0b11100000) {
172       // We have a three-byte UTF-8
173       if (pos + 2 >= len) {
174         return 0;
175       }  // minimal bound checking
176 
177       if ((data[pos + 1] & 0b11000000) != 0b10000000) {
178         return 0;
179       }
180       if ((data[pos + 2] & 0b11000000) != 0b10000000) {
181         return 0;
182       }
183       // range check
184       uint32_t code_point = (leading_byte & 0b00001111) << 12 |
185                             (data[pos + 1] & 0b00111111) << 6 |
186                             (data[pos + 2] & 0b00111111);
187       if (code_point < 0x800 || 0xffff < code_point ||
188           (0xd7ff < code_point && code_point < 0xe000)) {
189         return 0;
190       }
191       *utf32_output++ = char32_t(code_point);
192       pos += 3;
193     } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
194       // we have a 4-byte UTF-8 word.
195       if (pos + 3 >= len) {
196         return 0;
197       }  // minimal bound checking
198       if ((data[pos + 1] & 0b11000000) != 0b10000000) {
199         return 0;
200       }
201       if ((data[pos + 2] & 0b11000000) != 0b10000000) {
202         return 0;
203       }
204       if ((data[pos + 3] & 0b11000000) != 0b10000000) {
205         return 0;
206       }
207 
208       // range check
209       uint32_t code_point = (leading_byte & 0b00000111) << 18 |
210                             (data[pos + 1] & 0b00111111) << 12 |
211                             (data[pos + 2] & 0b00111111) << 6 |
212                             (data[pos + 3] & 0b00111111);
213       if (code_point <= 0xffff || 0x10ffff < code_point) {
214         return 0;
215       }
216       *utf32_output++ = char32_t(code_point);
217       pos += 4;
218     } else {
219       return 0;
220     }
221   }
222   return utf32_output - start;
223 }
224 
utf8_length_from_utf32(const char32_t * buf,size_t len)225 size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
226   // We are not BOM aware.
227   const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
228   size_t counter{0};
229   for (size_t i = 0; i < len; i++) {
230     /** ASCII **/
231     if (p[i] <= 0x7F) {
232       counter++;
233     }
234     /** two-byte **/
235     else if (p[i] <= 0x7FF) {
236       counter += 2;
237     }
238     /** three-byte **/
239     else if (p[i] <= 0xFFFF) {
240       counter += 3;
241     }
242     /** four-bytes **/
243     else {
244       counter += 4;
245     }
246   }
247   return counter;
248 }
249 
utf32_length_from_utf8(const char * buf,size_t len)250 size_t utf32_length_from_utf8(const char* buf, size_t len) {
251   const int8_t* p = reinterpret_cast<const int8_t*>(buf);
252   size_t counter{0};
253   for (size_t i = 0; i < len; i++) {
254     // -65 is 0b10111111, anything larger in two-complement's
255     // should start a new code point.
256     if (p[i] > -65) {
257       counter++;
258     }
259   }
260   return counter;
261 }
262 
utf32_to_utf8(const char32_t * buf,size_t len,char * utf8_output)263 size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
264   const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
265   size_t pos = 0;
266   char* start{utf8_output};
267   while (pos < len) {
268     // try to convert the next block of 2 ASCII characters
269     if (pos + 2 <= len) {  // if it is safe to read 8 more
270                            // bytes, check that they are ascii
271       uint64_t v;
272       std::memcpy(&v, data + pos, sizeof(uint64_t));
273       if ((v & 0xFFFFFF80FFFFFF80) == 0) {
274         *utf8_output++ = char(buf[pos]);
275         *utf8_output++ = char(buf[pos + 1]);
276         pos += 2;
277         continue;
278       }
279     }
280     uint32_t word = data[pos];
281     if ((word & 0xFFFFFF80) == 0) {
282       // will generate one UTF-8 bytes
283       *utf8_output++ = char(word);
284       pos++;
285     } else if ((word & 0xFFFFF800) == 0) {
286       // will generate two UTF-8 bytes
287       // we have 0b110XXXXX 0b10XXXXXX
288       *utf8_output++ = char((word >> 6) | 0b11000000);
289       *utf8_output++ = char((word & 0b111111) | 0b10000000);
290       pos++;
291     } else if ((word & 0xFFFF0000) == 0) {
292       // will generate three UTF-8 bytes
293       // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
294       if (word >= 0xD800 && word <= 0xDFFF) {
295         return 0;
296       }
297       *utf8_output++ = char((word >> 12) | 0b11100000);
298       *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
299       *utf8_output++ = char((word & 0b111111) | 0b10000000);
300       pos++;
301     } else {
302       // will generate four UTF-8 bytes
303       // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
304       // 0b10XXXXXX
305       if (word > 0x10FFFF) {
306         return 0;
307       }
308       *utf8_output++ = char((word >> 18) | 0b11110000);
309       *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
310       *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
311       *utf8_output++ = char((word & 0b111111) | 0b10000000);
312       pos++;
313     }
314   }
315   return utf8_output - start;
316 }
317 }  // namespace ada::idna
318 /* end file src/unicode_transcoding.cpp */
319 /* begin file src/mapping.cpp */
320 
321 #include <algorithm>
322 #include <array>
323 #include <string>
324 
325 /* begin file src/mapping_tables.cpp */
326 // IDNA  15.0.0
327 
328 // clang-format off
329 #ifndef ADA_IDNA_TABLES_H
330 #define ADA_IDNA_TABLES_H
331 #include <cstdint>
332 
333 namespace ada::idna {
334 
335 const uint32_t mappings[5164] =
336 {
337 	97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
338 	114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
339 	956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
340 	228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
341 	244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
342 	269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
343 	301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
344 	110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
345 	361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
346 	392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
347 	417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
348 	100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
349 	483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
350 	513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
351 	414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
352 	649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
353 	32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
354 	953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
355 	949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
356 	968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
357 	1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
358 	1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
359 	1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
360 	1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
361 	1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
362 	1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
363 	1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
364 	1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243, 1245,
365 	1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271, 1273,
366 	1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299, 1301,
367 	1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, 1377,
368 	1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391,
369 	1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405,
370 	1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652, 1608,
371 	1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364, 2337,
372 	2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492, 2610,
373 	2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876, 2850,
374 	2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916, 4023,
375 	3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018, 3968,
376 	4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001, 4023,
377 	4006, 4023, 4011, 4023, 3984, 4021, 11559, 11565, 4316, 5104, 5105, 5106, 5107,
378 	5108, 5109, 42571, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314,
379 	4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329,
380 	4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343,
381 	4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604, 7446, 7447, 7453, 7461,
382 	594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671, 625, 624, 627, 628, 632,
383 	642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697,
384 	7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725,
385 	7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753,
386 	7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781,
387 	7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809,
388 	7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 97, 702, 115, 115, 7841,
389 	7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869,
390 	7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897,
391 	7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925,
392 	7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952,
393 	7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984,
394 	7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017,
395 	8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 7936, 953, 7937,
396 	953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953, 7943, 953, 7968, 953,
397 	7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974, 953, 7975, 953, 8032,
398 	953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953, 8038, 953, 8039, 953,
399 	8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32, 787, 32, 834, 32, 776,
400 	834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32, 787, 768, 32, 787, 769,
401 	32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788, 769, 32, 788, 834, 944,
402 	8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969, 953, 974, 953, 8182, 953,
403 	8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, 8245, 8245,
404 	33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55, 56, 57, 43, 8722, 61, 40,
405 	41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99, 47, 117, 176, 102, 115, 109,
406 	116, 101, 108, 116, 109, 1488, 1489, 1490, 1491, 102, 97, 120, 8721, 49, 8260, 55,
407 	49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51, 50, 8260, 51, 49, 8260, 53, 50, 8260,
408 	53, 51, 8260, 53, 52, 8260, 53, 49, 8260, 54, 53, 8260, 54, 49, 8260, 56, 51, 8260,
409 	56, 53, 8260, 56, 55, 8260, 56, 105, 105, 105, 105, 105, 105, 118, 118, 105, 118,
410 	105, 105, 118, 105, 105, 105, 105, 120, 120, 105, 120, 105, 105, 48, 8260, 51, 8747,
411 	8747, 8747, 8747, 8747, 8750, 8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49,
412 	51, 49, 52, 49, 53, 49, 54, 49, 55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50,
413 	41, 40, 51, 41, 40, 52, 41, 40, 53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40,
414 	57, 41, 40, 49, 48, 41, 40, 49, 49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49,
415 	52, 41, 40, 49, 53, 41, 40, 49, 54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49,
416 	57, 41, 40, 50, 48, 41, 40, 97, 41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101,
417 	41, 40, 102, 41, 40, 103, 41, 40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41,
418 	40, 108, 41, 40, 109, 41, 40, 110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40,
419 	114, 41, 40, 115, 41, 40, 116, 41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120,
420 	41, 40, 121, 41, 40, 122, 41, 58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314,
421 	11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326,
422 	11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338,
423 	11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350,
424 	11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, 11359, 11361, 619, 7549,
425 	637, 11368, 11370, 11372, 11379, 11382, 575, 576, 11393, 11395, 11397, 11399, 11401,
426 	11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425,
427 	11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449,
428 	11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473,
429 	11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507,
430 	11617, 27597, 40863, 19968, 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154,
431 	20799, 20837, 20843, 20866, 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269,
432 	21274, 21304, 21313, 21340, 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763,
433 	22786, 22794, 22805, 22823, 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662,
434 	23665, 24027, 24037, 24049, 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339,
435 	24400, 24417, 24435, 24515, 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020,
436 	26041, 26080, 26085, 26352, 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604,
437 	27611, 27663, 27668, 27700, 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275,
438 	29356, 29572, 29577, 29916, 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326,
439 	30333, 30382, 30399, 30446, 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435,
440 	31481, 31859, 31992, 32566, 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895,
441 	32905, 33251, 33258, 33267, 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381,
442 	34411, 34880, 34892, 34915, 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960,
443 	35997, 36196, 36208, 36275, 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318,
444 	37324, 37329, 38263, 38272, 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761,
445 	38859, 38893, 38899, 38913, 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640,
446 	39647, 39717, 39727, 39730, 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643,
447 	40653, 40657, 40697, 40701, 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860,
448 	40864, 46, 12306, 21316, 21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488,
449 	4352, 4353, 4522, 4354, 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532,
450 	4533, 4378, 4358, 4359, 4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368,
451 	4369, 4370, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460,
452 	4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556,
453 	4558, 4563, 4567, 4569, 4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393,
454 	4395, 4396, 4397, 4398, 4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440,
455 	4441, 4484, 4485, 4488, 4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013,
456 	19979, 30002, 19993, 19969, 22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355,
457 	41, 40, 4357, 41, 40, 4358, 41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364,
458 	41, 40, 4366, 41, 40, 4367, 41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032,
459 	41, 40, 45208, 41, 40, 45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40,
460 	49324, 41, 40, 50500, 41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440,
461 	41, 40, 54028, 41, 40, 54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724,
462 	54980, 41, 40, 19968, 41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116,
463 	41, 40, 20845, 41, 40, 19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40,
464 	26376, 41, 40, 28779, 41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303,
465 	41, 40, 26085, 41, 40, 26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40,
466 	29305, 41, 40, 36001, 41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628,
467 	41, 40, 23398, 41, 40, 30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40,
468 	31085, 41, 40, 20241, 41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112,
469 	116, 101, 50, 50, 50, 52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51,
470 	51, 52, 51, 53, 52280, 44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360,
471 	27880, 38917, 20889, 27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51,
472 	56, 51, 57, 52, 48, 52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49,
473 	26376, 50, 26376, 51, 26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376,
474 	57, 26376, 49, 48, 26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103,
475 	101, 118, 108, 116, 100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463,
476 	12465, 12469, 12471, 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491,
477 	12492, 12493, 12494, 12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513,
478 	12514, 12516, 12518, 12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529,
479 	12530, 20196, 21644, 12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450,
480 	12531, 12506, 12450, 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531,
481 	12481, 12454, 12457, 12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459,
482 	12540, 12458, 12531, 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521,
483 	12483, 12488, 12459, 12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510,
484 	12462, 12460, 12462, 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480,
485 	12540, 12461, 12525, 12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540,
486 	12488, 12523, 12461, 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531,
487 	12463, 12523, 12476, 12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473,
488 	12467, 12523, 12490, 12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531,
489 	12481, 12540, 12512, 12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531,
490 	12488, 12480, 12540, 12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483,
491 	12488, 12495, 12452, 12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484,
492 	12496, 12540, 12524, 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523,
493 	12500, 12467, 12499, 12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540,
494 	12488, 12502, 12483, 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479,
495 	12540, 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531,
496 	12473, 12506, 12540, 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508,
497 	12523, 12488, 12507, 12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540,
498 	12531, 12510, 12452, 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510,
499 	12523, 12463, 12510, 12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511,
500 	12522, 12511, 12522, 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531,
501 	12516, 12540, 12489, 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488,
502 	12523, 12522, 12521, 12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512,
503 	12524, 12531, 12488, 12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52,
504 	28857, 53, 28857, 54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49,
505 	49, 28857, 49, 50, 28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857,
506 	49, 55, 28857, 49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50,
507 	28857, 50, 51, 28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114,
508 	111, 118, 112, 99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104,
509 	26157, 21644, 22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956,
510 	97, 109, 97, 107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108,
511 	112, 102, 110, 102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104,
512 	122, 109, 104, 122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110,
513 	109, 956, 109, 109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109,
514 	50, 109, 109, 51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50,
515 	107, 112, 97, 109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115,
516 	114, 97, 100, 8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110,
517 	118, 956, 118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107,
518 	119, 107, 969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97,
519 	105, 110, 107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108,
520 	109, 111, 108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725,
521 	109, 97, 8725, 109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085,
522 	55, 26085, 56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49,
523 	51, 26085, 49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085,
524 	49, 57, 26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52,
525 	26085, 50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085,
526 	51, 48, 26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573,
527 	42575, 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597,
528 	42599, 42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639,
529 	42641, 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797,
530 	42799, 42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823,
531 	42825, 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847,
532 	42849, 42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879,
533 	42881, 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911,
534 	42913, 42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939,
535 	42941, 42943, 42945, 42947, 42900, 7566, 42952, 42954, 42961, 42967, 42969, 42998,
536 	43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034,
537 	5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048,
538 	5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062,
539 	5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076,
540 	5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090,
541 	5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 35912,
542 	26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856, 25078, 30313, 32645, 34367,
543 	34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, 21365,
544 	27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172, 25289, 33240, 34847, 24266,
545 	26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, 34310,
546 	34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160, 33737, 37636, 35542, 22751,
547 	24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, 28431,
548 	32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260, 32190, 33777, 38517, 35712,
549 	25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, 19981,
550 	27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498, 27578, 27784, 25342, 33509,
551 	25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, 21570,
552 	24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654, 26310, 27511, 36706, 24180,
553 	24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, 36899,
554 	37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565, 25467, 27566, 31806, 29557,
555 	22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, 38936, 20363,
556 	31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, 26009, 29134, 30274, 34044,
557 	36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, 30827, 32016,
558 	39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, 24900, 26647, 38534, 21033,
559 	21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, 35041, 38626,
560 	21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, 40607, 26519, 28107, 33256,
561 	31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, 25299, 31958,
562 	23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, 22618, 26228, 20958, 29482,
563 	30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, 37117, 39151,
564 	39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, 21193, 21220, 21329, 21917,
565 	22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, 26082, 26257,
566 	26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, 31049, 31048, 31056, 31062,
567 	31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, 33401, 33879,
568 	35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, 38911, 38971, 24693, 148206,
569 	33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, 21845, 21913, 21986,
570 	22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425, 24493, 24792, 24910, 24840,
571 	24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, 28363, 28702, 30631,
572 	29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427, 30452, 30538, 30528, 30924,
573 	31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, 35519, 35531, 35565,
574 	35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923, 39698, 141386, 141380, 144341,
575 	15261, 16408, 16441, 152137, 154832, 163539, 40771, 40846, 102, 102, 102, 105, 102,
576 	108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396, 1387, 1406, 1398, 1396, 1389,
577 	1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, 1513, 1473, 1513,
578 	1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463, 1488, 1464, 1488, 1468, 1489,
579 	1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, 1494, 1468, 1496, 1468, 1497,
580 	1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468, 1504, 1468, 1505, 1468, 1507,
581 	1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468, 1514, 1468, 1493, 1465, 1489,
582 	1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659, 1662, 1664, 1658, 1663, 1657,
583 	1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678, 1672, 1688, 1681, 1705, 1711,
584 	1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, 1709, 1734, 1736, 1739, 1733,
585 	1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, 1574, 1735, 1574, 1734, 1574,
586 	1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574, 1581, 1574, 1605, 1574, 1610,
587 	1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576, 1609, 1576, 1610, 1578, 1580,
588 	1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578, 1610, 1579, 1580, 1579, 1605,
589 	1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, 1605, 1582, 1580, 1582, 1581,
590 	1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, 1605, 1589, 1581, 1589, 1605,
591 	1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591, 1581, 1591, 1605, 1592, 1605,
592 	1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601, 1580, 1601, 1581, 1601, 1582,
593 	1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602, 1605, 1602, 1609, 1602, 1610,
594 	1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, 1604, 1603, 1605, 1603, 1609,
595 	1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604, 1605, 1604, 1609, 1604, 1610,
596 	1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606, 1580, 1606, 1581, 1606, 1582,
597 	1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607, 1605, 1607, 1609, 1607, 1610,
598 	1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585, 1648, 1609, 1648, 32, 1612,
599 	1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617, 32, 1616, 1617, 32, 1617,
600 	1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585, 1576, 1586, 1576, 1606, 1578,
601 	1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586, 1579, 1606, 1605, 1575, 1606,
602 	1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586, 1574, 1582, 1574, 1607, 1576,
603 	1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607, 1607, 1648, 1579, 1607, 1587,
604 	1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600, 1615, 1617, 1600, 1616, 1617,
605 	1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594, 1609, 1594, 1610, 1587, 1609,
606 	1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580, 1609, 1580, 1610, 1582, 1609,
607 	1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588, 1580, 1588, 1581, 1588, 1582,
608 	1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575, 1611, 1578, 1580, 1605, 1578,
609 	1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578, 1605, 1580, 1578, 1605, 1581,
610 	1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609, 1587, 1581, 1580, 1587, 1580,
611 	1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605, 1580, 1587, 1605, 1605, 1589,
612 	1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588, 1580, 1610, 1588, 1605, 1582,
613 	1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, 1591, 1605, 1581, 1591, 1605,
614 	1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605, 1605, 1593, 1605, 1609, 1594,
615 	1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601, 1582, 1605, 1602, 1605, 1581,
616 	1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610, 1604, 1581, 1609, 1604, 1580,
617 	1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, 1580, 1605, 1581, 1610, 1605,
618 	1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607, 1605, 1580, 1607, 1605, 1605,
619 	1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605, 1606, 1580, 1609, 1606, 1605,
620 	1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582, 1610, 1578, 1580, 1610, 1578,
621 	1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578, 1605, 1610, 1578, 1605, 1609,
622 	1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609, 1587, 1582, 1609, 1589, 1581,
623 	1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580, 1610, 1604, 1605, 1610, 1610,
624 	1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602, 1605, 1610, 1606, 1581, 1610,
625 	1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581, 1605, 1582, 1610, 1604, 1580,
626 	1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, 1601,
627 	1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, 1580, 1610, 1589, 1604, 1746,
628 	1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, 1576, 1585, 1605, 1581, 1605,
629 	1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604, 1593, 1604, 1610, 1607, 1608,
630 	1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607,
631 	32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 1580, 1604, 32, 1580, 1604,
632 	1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289, 12310, 12311, 8212, 8211, 95,
633 	123, 125, 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, 12302, 12303,
634 	91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32, 1611, 1600, 1611, 1600, 1617,
635 	32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573, 1577, 1604, 1570, 1604, 1571,
636 	1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539, 12453, 12515, 162, 163, 172,
637 	166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, 66600, 66601, 66602, 66603,
638 	66604, 66605, 66606, 66607, 66608, 66609, 66610, 66611, 66612, 66613, 66614, 66615,
639 	66616, 66617, 66618, 66619, 66620, 66621, 66622, 66623, 66624, 66625, 66626, 66627,
640 	66628, 66629, 66630, 66631, 66632, 66633, 66634, 66635, 66636, 66637, 66638, 66639,
641 	66776, 66777, 66778, 66779, 66780, 66781, 66782, 66783, 66784, 66785, 66786, 66787,
642 	66788, 66789, 66790, 66791, 66792, 66793, 66794, 66795, 66796, 66797, 66798, 66799,
643 	66800, 66801, 66802, 66803, 66804, 66805, 66806, 66807, 66808, 66809, 66810, 66811,
644 	66967, 66968, 66969, 66970, 66971, 66972, 66973, 66974, 66975, 66976, 66977, 66979,
645 	66980, 66981, 66982, 66983, 66984, 66985, 66986, 66987, 66988, 66989, 66990, 66991,
646 	66992, 66993, 66995, 66996, 66997, 66998, 66999, 67000, 67001, 67003, 67004, 720,
647 	721, 665, 675, 43878, 677, 676, 7569, 600, 606, 681, 612, 610, 667, 668, 615, 644,
648 	682, 683, 122628, 42894, 622, 122629, 654, 122630, 630, 631, 634, 122632, 638, 680,
649 	678, 43879, 679, 11377, 655, 673, 674, 664, 448, 449, 450, 122634, 122654, 68800,
650 	68801, 68802, 68803, 68804, 68805, 68806, 68807, 68808, 68809, 68810, 68811, 68812,
651 	68813, 68814, 68815, 68816, 68817, 68818, 68819, 68820, 68821, 68822, 68823, 68824,
652 	68825, 68826, 68827, 68828, 68829, 68830, 68831, 68832, 68833, 68834, 68835, 68836,
653 	68837, 68838, 68839, 68840, 68841, 68842, 68843, 68844, 68845, 68846, 68847, 68848,
654 	68849, 68850, 71872, 71873, 71874, 71875, 71876, 71877, 71878, 71879, 71880, 71881,
655 	71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890, 71891, 71892, 71893,
656 	71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902, 71903, 93792, 93793,
657 	93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802, 93803, 93804, 93805,
658 	93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814, 93815, 93816, 93817,
659 	93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128, 119141, 119128,
660 	119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152, 119128, 119141,
661 	119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141, 119225, 119141,
662 	119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226, 119141, 119151,
663 	305, 567, 8711, 8706, 1231, 125218, 125219, 125220, 125221, 125222, 125223, 125224,
664 	125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233, 125234,
665 	125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243, 125244,
666 	125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647, 48, 44,
667 	49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44, 12308, 115,
668 	12309, 119, 122, 104, 118, 115, 100, 112, 112, 118, 119, 99, 109, 114, 100, 106,
669 	12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132, 26144, 28961, 21069,
670 	24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, 25429, 36938,
671 	25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942, 37197, 12308, 26412,
672 	12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, 12308, 28857,
673 	12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213, 12309, 12308, 25943,
674 	12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411, 20482, 20602, 20633,
675 	20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839, 132427, 20887,
676 	20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589, 21253, 21254,
677 	21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987, 21483, 21489,
678 	21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931,
679 	21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541, 22411, 22578,
680 	22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938, 23020,
681 	23067, 23079, 23000, 23142, 14062, 23304, 23358, 137672, 23491, 23512, 23539, 138008,
682 	23551, 23558, 14209, 23648, 23744, 23693, 138724, 23875, 138726, 23918, 23915, 23932,
683 	24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651, 14460, 24240, 24243,
684 	24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122, 24418, 24427, 14563,
685 	24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775, 24904, 24908, 24954,
686 	25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424, 142092, 25405, 25340,
687 	25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705, 25726, 25757, 25719,
688 	14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, 26368,
689 	26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618, 26501, 26706, 144493,
690 	26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355, 15384, 27425, 145575,
691 	27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170, 27726, 146620, 27839,
692 	27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956, 28207, 28270, 15667,
693 	28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729, 28699, 15766, 28746,
694 	28797, 28791, 28845, 132389, 28997, 148067, 29084, 29224, 29264, 149000, 29312,
695 	29333, 149301, 149524, 29562, 29579, 16044, 29605, 16056, 29767, 29788, 29829, 29898,
696 	16155, 29988, 150582, 30014, 150674, 139679, 30224, 151457, 151480, 151620, 16380,
697 	16392, 151795, 151794, 151833, 151859, 30494, 30495, 30603, 16454, 16534, 152605,
698 	30798, 16611, 153126, 153242, 153285, 31211, 16687, 31306, 31311, 153980, 154279,
699 	16898, 154539, 31686, 31689, 16935, 154752, 31954, 17056, 31976, 31971, 32000, 155526,
700 	32099, 17153, 32199, 32258, 32325, 17204, 156200, 156231, 17241, 156377, 32634,
701 	156478, 32661, 32762, 156890, 156963, 32864, 157096, 32880, 144223, 17365, 32946,
702 	33027, 17419, 33086, 23221, 157607, 157621, 144275, 144284, 33284, 36766, 17515,
703 	33425, 33419, 33437, 21171, 33457, 33459, 33469, 33510, 158524, 33565, 33635, 33709,
704 	33571, 33725, 33767, 33619, 33738, 33740, 33756, 158774, 159083, 158933, 17707,
705 	34033, 34035, 34070, 160714, 34148, 159532, 17757, 17761, 159665, 159954, 17771,
706 	34384, 34407, 34409, 34473, 34440, 34574, 34530, 34600, 34667, 34694, 34785, 34817,
707 	17913, 34912, 161383, 35031, 35038, 17973, 35066, 13499, 161966, 162150, 18110,
708 	18119, 35488, 162984, 36011, 36033, 36123, 36215, 163631, 133124, 36299, 36284,
709 	36336, 133342, 36564, 165330, 165357, 37012, 37105, 37137, 165678, 37147, 37432,
710 	37591, 37592, 37500, 37881, 37909, 166906, 38283, 18837, 38327, 167287, 18918, 38595,
711 	23986, 38691, 168261, 168474, 19054, 19062, 38880, 168970, 19122, 169110, 38953,
712 	169398, 39138, 19251, 39209, 39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662,
713 	19693, 40295, 172238, 19704, 172293, 172558, 172689, 19798, 40702, 40709, 40719,
714 	40726, 173568,
715 
716 };
717 const uint32_t table[8000][2] =
718 {
719 	{0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
720 	{68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
721 	{72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
722 	{76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
723 	{80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
724 	{84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
725 	{88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
726 	{128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
727 	{169, 1}, {170, 16777219}, {171, 1}, {173, 0},
728 	{174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
729 	{179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
730 	{184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
731 	{188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
732 	{192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
733 	{196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
734 	{200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
735 	{204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
736 	{208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
737 	{212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
738 	{216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
739 	{220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
740 	{256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
741 	{260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
742 	{264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
743 	{268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
744 	{272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
745 	{276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
746 	{280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
747 	{284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
748 	{288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
749 	{292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
750 	{296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
751 	{300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
752 	{304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
753 	{309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
754 	{314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
755 	{318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
756 	{323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
757 	{327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
758 	{331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
759 	{335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
760 	{339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
761 	{343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
762 	{347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
763 	{351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
764 	{355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
765 	{359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
766 	{363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
767 	{367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
768 	{371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
769 	{375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
770 	{379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
771 	{383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
772 	{387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
773 	{391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
774 	{395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
775 	{400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
776 	{404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
777 	{408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
778 	{414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
779 	{418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
780 	{422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
781 	{426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
782 	{431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
783 	{435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
784 	{439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
785 	{445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
786 	{461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
787 	{465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
788 	{469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
789 	{473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
790 	{478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
791 	{482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
792 	{486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
793 	{490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
794 	{494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
795 	{501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
796 	{505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
797 	{509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
798 	{513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
799 	{517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
800 	{521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
801 	{525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
802 	{529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
803 	{533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
804 	{537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
805 	{541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
806 	{545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
807 	{549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
808 	{553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
809 	{557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
810 	{561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
811 	{571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
812 	{575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
813 	{580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
814 	{584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
815 	{588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
816 	{688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
817 	{692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
818 	{696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
819 	{730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
820 	{734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
821 	{739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
822 	{833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
823 	{837, 16846851}, {838, 1}, {847, 0}, {848, 1},
824 	{880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
825 	{884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
826 	{888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
827 	{895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
828 	{902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
829 	{906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
830 	{910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
831 	{914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
832 	{918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
833 	{922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
834 	{926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
835 	{930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
836 	{934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
837 	{938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
838 	{976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
839 	{980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
840 	{984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
841 	{988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
842 	{992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
843 	{996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
844 	{1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
845 	{1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
846 	{1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
847 	{1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
848 	{1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
849 	{1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
850 	{1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
851 	{1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
852 	{1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
853 	{1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
854 	{1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
855 	{1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
856 	{1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
857 	{1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
858 	{1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
859 	{1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
860 	{1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
861 	{1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
862 	{1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
863 	{1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
864 	{1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
865 	{1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
866 	{1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
867 	{1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
868 	{1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
869 	{1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
870 	{1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
871 	{1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
872 	{1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
873 	{1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
874 	{1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
875 	{1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
876 	{1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
877 	{1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
878 	{1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
879 	{1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
880 	{1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
881 	{1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
882 	{1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
883 	{1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
884 	{1216, 2}, {1217, 16886019}, {1218, 1}, {1219, 16886275},
885 	{1220, 1}, {1221, 16886531}, {1222, 1}, {1223, 16886787},
886 	{1224, 1}, {1225, 16887043}, {1226, 1}, {1227, 16887299},
887 	{1228, 1}, {1229, 16887555}, {1230, 1}, {1232, 16887811},
888 	{1233, 1}, {1234, 16888067}, {1235, 1}, {1236, 16888323},
889 	{1237, 1}, {1238, 16888579}, {1239, 1}, {1240, 16888835},
890 	{1241, 1}, {1242, 16889091}, {1243, 1}, {1244, 16889347},
891 	{1245, 1}, {1246, 16889603}, {1247, 1}, {1248, 16889859},
892 	{1249, 1}, {1250, 16890115}, {1251, 1}, {1252, 16890371},
893 	{1253, 1}, {1254, 16890627}, {1255, 1}, {1256, 16890883},
894 	{1257, 1}, {1258, 16891139}, {1259, 1}, {1260, 16891395},
895 	{1261, 1}, {1262, 16891651}, {1263, 1}, {1264, 16891907},
896 	{1265, 1}, {1266, 16892163}, {1267, 1}, {1268, 16892419},
897 	{1269, 1}, {1270, 16892675}, {1271, 1}, {1272, 16892931},
898 	{1273, 1}, {1274, 16893187}, {1275, 1}, {1276, 16893443},
899 	{1277, 1}, {1278, 16893699}, {1279, 1}, {1280, 16893955},
900 	{1281, 1}, {1282, 16894211}, {1283, 1}, {1284, 16894467},
901 	{1285, 1}, {1286, 16894723}, {1287, 1}, {1288, 16894979},
902 	{1289, 1}, {1290, 16895235}, {1291, 1}, {1292, 16895491},
903 	{1293, 1}, {1294, 16895747}, {1295, 1}, {1296, 16896003},
904 	{1297, 1}, {1298, 16896259}, {1299, 1}, {1300, 16896515},
905 	{1301, 1}, {1302, 16896771}, {1303, 1}, {1304, 16897027},
906 	{1305, 1}, {1306, 16897283}, {1307, 1}, {1308, 16897539},
907 	{1309, 1}, {1310, 16897795}, {1311, 1}, {1312, 16898051},
908 	{1313, 1}, {1314, 16898307}, {1315, 1}, {1316, 16898563},
909 	{1317, 1}, {1318, 16898819}, {1319, 1}, {1320, 16899075},
910 	{1321, 1}, {1322, 16899331}, {1323, 1}, {1324, 16899587},
911 	{1325, 1}, {1326, 16899843}, {1327, 1}, {1328, 2},
912 	{1329, 16900099}, {1330, 16900355}, {1331, 16900611}, {1332, 16900867},
913 	{1333, 16901123}, {1334, 16901379}, {1335, 16901635}, {1336, 16901891},
914 	{1337, 16902147}, {1338, 16902403}, {1339, 16902659}, {1340, 16902915},
915 	{1341, 16903171}, {1342, 16903427}, {1343, 16903683}, {1344, 16903939},
916 	{1345, 16904195}, {1346, 16904451}, {1347, 16904707}, {1348, 16904963},
917 	{1349, 16905219}, {1350, 16905475}, {1351, 16905731}, {1352, 16905987},
918 	{1353, 16906243}, {1354, 16906499}, {1355, 16906755}, {1356, 16907011},
919 	{1357, 16907267}, {1358, 16907523}, {1359, 16907779}, {1360, 16908035},
920 	{1361, 16908291}, {1362, 16908547}, {1363, 16908803}, {1364, 16909059},
921 	{1365, 16909315}, {1366, 16909571}, {1367, 2}, {1369, 1},
922 	{1415, 33687043}, {1416, 1}, {1419, 2}, {1421, 1},
923 	{1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
924 	{1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
925 	{1564, 2}, {1565, 1}, {1653, 33687555}, {1654, 33688067},
926 	{1655, 33688579}, {1656, 33689091}, {1657, 1}, {1757, 2},
927 	{1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
928 	{1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
929 	{2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
930 	{2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
931 	{2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
932 	{2200, 1}, {2274, 2}, {2275, 1}, {2392, 33689603},
933 	{2393, 33690115}, {2394, 33690627}, {2395, 33691139}, {2396, 33691651},
934 	{2397, 33692163}, {2398, 33692675}, {2399, 33693187}, {2400, 1},
935 	{2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
936 	{2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
937 	{2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
938 	{2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
939 	{2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
940 	{2520, 2}, {2524, 33693699}, {2525, 33694211}, {2526, 2},
941 	{2527, 33694723}, {2528, 1}, {2532, 2}, {2534, 1},
942 	{2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
943 	{2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
944 	{2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
945 	{2611, 33695235}, {2612, 2}, {2613, 1}, {2614, 33695747},
946 	{2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
947 	{2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
948 	{2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
949 	{2642, 2}, {2649, 33696259}, {2650, 33696771}, {2651, 33697283},
950 	{2652, 1}, {2653, 2}, {2654, 33697795}, {2655, 2},
951 	{2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
952 	{2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
953 	{2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
954 	{2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
955 	{2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
956 	{2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
957 	{2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
958 	{2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
959 	{2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
960 	{2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
961 	{2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
962 	{2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
963 	{2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
964 	{2908, 33698307}, {2909, 33698819}, {2910, 2}, {2911, 1},
965 	{2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
966 	{2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
967 	{2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
968 	{2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
969 	{2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
970 	{2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
971 	{3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
972 	{3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
973 	{3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
974 	{3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
975 	{3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
976 	{3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
977 	{3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
978 	{3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
979 	{3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
980 	{3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
981 	{3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
982 	{3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
983 	{3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
984 	{3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
985 	{3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
986 	{3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
987 	{3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
988 	{3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
989 	{3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
990 	{3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
991 	{3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
992 	{3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
993 	{3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
994 	{3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
995 	{3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
996 	{3635, 33699331}, {3636, 1}, {3643, 2}, {3647, 1},
997 	{3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
998 	{3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
999 	{3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1000 	{3763, 33699843}, {3764, 1}, {3774, 2}, {3776, 1},
1001 	{3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1002 	{3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700355},
1003 	{3805, 33700867}, {3806, 1}, {3808, 2}, {3840, 1},
1004 	{3852, 16924163}, {3853, 1}, {3907, 33701635}, {3908, 1},
1005 	{3912, 2}, {3913, 1}, {3917, 33702147}, {3918, 1},
1006 	{3922, 33702659}, {3923, 1}, {3927, 33703171}, {3928, 1},
1007 	{3932, 33703683}, {3933, 1}, {3945, 33704195}, {3946, 1},
1008 	{3949, 2}, {3953, 1}, {3955, 33704707}, {3956, 1},
1009 	{3957, 33705219}, {3958, 33705731}, {3959, 50483459}, {3960, 33707011},
1010 	{3961, 50484739}, {3962, 1}, {3969, 33706499}, {3970, 1},
1011 	{3987, 33708291}, {3988, 1}, {3992, 2}, {3993, 1},
1012 	{3997, 33708803}, {3998, 1}, {4002, 33709315}, {4003, 1},
1013 	{4007, 33709827}, {4008, 1}, {4012, 33710339}, {4013, 1},
1014 	{4025, 33710851}, {4026, 1}, {4029, 2}, {4030, 1},
1015 	{4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1016 	{4256, 2}, {4295, 16934147}, {4296, 2}, {4301, 16934403},
1017 	{4302, 2}, {4304, 1}, {4348, 16934659}, {4349, 1},
1018 	{4447, 2}, {4449, 1}, {4681, 2}, {4682, 1},
1019 	{4686, 2}, {4688, 1}, {4695, 2}, {4696, 1},
1020 	{4697, 2}, {4698, 1}, {4702, 2}, {4704, 1},
1021 	{4745, 2}, {4746, 1}, {4750, 2}, {4752, 1},
1022 	{4785, 2}, {4786, 1}, {4790, 2}, {4792, 1},
1023 	{4799, 2}, {4800, 1}, {4801, 2}, {4802, 1},
1024 	{4806, 2}, {4808, 1}, {4823, 2}, {4824, 1},
1025 	{4881, 2}, {4882, 1}, {4886, 2}, {4888, 1},
1026 	{4955, 2}, {4957, 1}, {4989, 2}, {4992, 1},
1027 	{5018, 2}, {5024, 1}, {5110, 2}, {5112, 16934915},
1028 	{5113, 16935171}, {5114, 16935427}, {5115, 16935683}, {5116, 16935939},
1029 	{5117, 16936195}, {5118, 2}, {5120, 1}, {5760, 2},
1030 	{5761, 1}, {5789, 2}, {5792, 1}, {5881, 2},
1031 	{5888, 1}, {5910, 2}, {5919, 1}, {5943, 2},
1032 	{5952, 1}, {5972, 2}, {5984, 1}, {5997, 2},
1033 	{5998, 1}, {6001, 2}, {6002, 1}, {6004, 2},
1034 	{6016, 1}, {6068, 2}, {6070, 1}, {6110, 2},
1035 	{6112, 1}, {6122, 2}, {6128, 1}, {6138, 2},
1036 	{6144, 1}, {6150, 2}, {6151, 1}, {6155, 0},
1037 	{6158, 2}, {6159, 0}, {6160, 1}, {6170, 2},
1038 	{6176, 1}, {6265, 2}, {6272, 1}, {6315, 2},
1039 	{6320, 1}, {6390, 2}, {6400, 1}, {6431, 2},
1040 	{6432, 1}, {6444, 2}, {6448, 1}, {6460, 2},
1041 	{6464, 1}, {6465, 2}, {6468, 1}, {6510, 2},
1042 	{6512, 1}, {6517, 2}, {6528, 1}, {6572, 2},
1043 	{6576, 1}, {6602, 2}, {6608, 1}, {6619, 2},
1044 	{6622, 1}, {6684, 2}, {6686, 1}, {6751, 2},
1045 	{6752, 1}, {6781, 2}, {6783, 1}, {6794, 2},
1046 	{6800, 1}, {6810, 2}, {6816, 1}, {6830, 2},
1047 	{6832, 1}, {6863, 2}, {6912, 1}, {6989, 2},
1048 	{6992, 1}, {7039, 2}, {7040, 1}, {7156, 2},
1049 	{7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1050 	{7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1051 	{7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1052 	{7304, 16936451}, {7305, 2}, {7312, 16936707}, {7313, 16936963},
1053 	{7314, 16937219}, {7315, 16937475}, {7316, 16937731}, {7317, 16937987},
1054 	{7318, 16938243}, {7319, 16938499}, {7320, 16938755}, {7321, 16939011},
1055 	{7322, 16939267}, {7323, 16939523}, {7324, 16934659}, {7325, 16939779},
1056 	{7326, 16940035}, {7327, 16940291}, {7328, 16940547}, {7329, 16940803},
1057 	{7330, 16941059}, {7331, 16941315}, {7332, 16941571}, {7333, 16941827},
1058 	{7334, 16942083}, {7335, 16942339}, {7336, 16942595}, {7337, 16942851},
1059 	{7338, 16943107}, {7339, 16943363}, {7340, 16943619}, {7341, 16943875},
1060 	{7342, 16944131}, {7343, 16944387}, {7344, 16944643}, {7345, 16944899},
1061 	{7346, 16945155}, {7347, 16945411}, {7348, 16945667}, {7349, 16945923},
1062 	{7350, 16946179}, {7351, 16946435}, {7352, 16946691}, {7353, 16946947},
1063 	{7354, 16947203}, {7355, 2}, {7357, 16947459}, {7358, 16947715},
1064 	{7359, 16947971}, {7360, 1}, {7368, 2}, {7376, 1},
1065 	{7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043},
1066 	{7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243},
1067 	{7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267},
1068 	{7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291},
1069 	{7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843},
1070 	{7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339},
1071 	{7490, 16782851}, {7491, 16777219}, {7492, 16948227}, {7493, 16948483},
1072 	{7494, 16948739}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243},
1073 	{7498, 16816387}, {7499, 16816643}, {7500, 16948995}, {7501, 16778755},
1074 	{7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171},
1075 	{7506, 16780803}, {7507, 16814851}, {7508, 16949251}, {7509, 16949507},
1076 	{7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16949763},
1077 	{7514, 16818435}, {7515, 16782595}, {7516, 16950019}, {7517, 16851971},
1078 	{7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579},
1079 	{7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595},
1080 	{7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323},
1081 	{7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1},
1082 	{7579, 16950275}, {7580, 16777731}, {7581, 16950531}, {7582, 16793603},
1083 	{7583, 16948995}, {7584, 16778499}, {7585, 16950787}, {7586, 16951043},
1084 	{7587, 16951299}, {7588, 16817923}, {7589, 16817667}, {7590, 16951555},
1085 	{7591, 16951811}, {7592, 16952067}, {7593, 16952323}, {7594, 16952579},
1086 	{7595, 16952835}, {7596, 16953091}, {7597, 16953347}, {7598, 16818691},
1087 	{7599, 16953603}, {7600, 16953859}, {7601, 16818947}, {7602, 16954115},
1088 	{7603, 16954371}, {7604, 16820483}, {7605, 16954627}, {7606, 16839683},
1089 	{7607, 16821507}, {7608, 16954883}, {7609, 16821763}, {7610, 16839939},
1090 	{7611, 16783619}, {7612, 16955139}, {7613, 16955395}, {7614, 16822531},
1091 	{7615, 16853507}, {7616, 1}, {7680, 16955651}, {7681, 1},
1092 	{7682, 16955907}, {7683, 1}, {7684, 16956163}, {7685, 1},
1093 	{7686, 16956419}, {7687, 1}, {7688, 16956675}, {7689, 1},
1094 	{7690, 16956931}, {7691, 1}, {7692, 16957187}, {7693, 1},
1095 	{7694, 16957443}, {7695, 1}, {7696, 16957699}, {7697, 1},
1096 	{7698, 16957955}, {7699, 1}, {7700, 16958211}, {7701, 1},
1097 	{7702, 16958467}, {7703, 1}, {7704, 16958723}, {7705, 1},
1098 	{7706, 16958979}, {7707, 1}, {7708, 16959235}, {7709, 1},
1099 	{7710, 16959491}, {7711, 1}, {7712, 16959747}, {7713, 1},
1100 	{7714, 16960003}, {7715, 1}, {7716, 16960259}, {7717, 1},
1101 	{7718, 16960515}, {7719, 1}, {7720, 16960771}, {7721, 1},
1102 	{7722, 16961027}, {7723, 1}, {7724, 16961283}, {7725, 1},
1103 	{7726, 16961539}, {7727, 1}, {7728, 16961795}, {7729, 1},
1104 	{7730, 16962051}, {7731, 1}, {7732, 16962307}, {7733, 1},
1105 	{7734, 16962563}, {7735, 1}, {7736, 16962819}, {7737, 1},
1106 	{7738, 16963075}, {7739, 1}, {7740, 16963331}, {7741, 1},
1107 	{7742, 16963587}, {7743, 1}, {7744, 16963843}, {7745, 1},
1108 	{7746, 16964099}, {7747, 1}, {7748, 16964355}, {7749, 1},
1109 	{7750, 16964611}, {7751, 1}, {7752, 16964867}, {7753, 1},
1110 	{7754, 16965123}, {7755, 1}, {7756, 16965379}, {7757, 1},
1111 	{7758, 16965635}, {7759, 1}, {7760, 16965891}, {7761, 1},
1112 	{7762, 16966147}, {7763, 1}, {7764, 16966403}, {7765, 1},
1113 	{7766, 16966659}, {7767, 1}, {7768, 16966915}, {7769, 1},
1114 	{7770, 16967171}, {7771, 1}, {7772, 16967427}, {7773, 1},
1115 	{7774, 16967683}, {7775, 1}, {7776, 16967939}, {7777, 1},
1116 	{7778, 16968195}, {7779, 1}, {7780, 16968451}, {7781, 1},
1117 	{7782, 16968707}, {7783, 1}, {7784, 16968963}, {7785, 1},
1118 	{7786, 16969219}, {7787, 1}, {7788, 16969475}, {7789, 1},
1119 	{7790, 16969731}, {7791, 1}, {7792, 16969987}, {7793, 1},
1120 	{7794, 16970243}, {7795, 1}, {7796, 16970499}, {7797, 1},
1121 	{7798, 16970755}, {7799, 1}, {7800, 16971011}, {7801, 1},
1122 	{7802, 16971267}, {7803, 1}, {7804, 16971523}, {7805, 1},
1123 	{7806, 16971779}, {7807, 1}, {7808, 16972035}, {7809, 1},
1124 	{7810, 16972291}, {7811, 1}, {7812, 16972547}, {7813, 1},
1125 	{7814, 16972803}, {7815, 1}, {7816, 16973059}, {7817, 1},
1126 	{7818, 16973315}, {7819, 1}, {7820, 16973571}, {7821, 1},
1127 	{7822, 16973827}, {7823, 1}, {7824, 16974083}, {7825, 1},
1128 	{7826, 16974339}, {7827, 1}, {7828, 16974595}, {7829, 1},
1129 	{7834, 33752067}, {7835, 16967939}, {7836, 1}, {7838, 33752579},
1130 	{7839, 1}, {7840, 16975875}, {7841, 1}, {7842, 16976131},
1131 	{7843, 1}, {7844, 16976387}, {7845, 1}, {7846, 16976643},
1132 	{7847, 1}, {7848, 16976899}, {7849, 1}, {7850, 16977155},
1133 	{7851, 1}, {7852, 16977411}, {7853, 1}, {7854, 16977667},
1134 	{7855, 1}, {7856, 16977923}, {7857, 1}, {7858, 16978179},
1135 	{7859, 1}, {7860, 16978435}, {7861, 1}, {7862, 16978691},
1136 	{7863, 1}, {7864, 16978947}, {7865, 1}, {7866, 16979203},
1137 	{7867, 1}, {7868, 16979459}, {7869, 1}, {7870, 16979715},
1138 	{7871, 1}, {7872, 16979971}, {7873, 1}, {7874, 16980227},
1139 	{7875, 1}, {7876, 16980483}, {7877, 1}, {7878, 16980739},
1140 	{7879, 1}, {7880, 16980995}, {7881, 1}, {7882, 16981251},
1141 	{7883, 1}, {7884, 16981507}, {7885, 1}, {7886, 16981763},
1142 	{7887, 1}, {7888, 16982019}, {7889, 1}, {7890, 16982275},
1143 	{7891, 1}, {7892, 16982531}, {7893, 1}, {7894, 16982787},
1144 	{7895, 1}, {7896, 16983043}, {7897, 1}, {7898, 16983299},
1145 	{7899, 1}, {7900, 16983555}, {7901, 1}, {7902, 16983811},
1146 	{7903, 1}, {7904, 16984067}, {7905, 1}, {7906, 16984323},
1147 	{7907, 1}, {7908, 16984579}, {7909, 1}, {7910, 16984835},
1148 	{7911, 1}, {7912, 16985091}, {7913, 1}, {7914, 16985347},
1149 	{7915, 1}, {7916, 16985603}, {7917, 1}, {7918, 16985859},
1150 	{7919, 1}, {7920, 16986115}, {7921, 1}, {7922, 16986371},
1151 	{7923, 1}, {7924, 16986627}, {7925, 1}, {7926, 16986883},
1152 	{7927, 1}, {7928, 16987139}, {7929, 1}, {7930, 16987395},
1153 	{7931, 1}, {7932, 16987651}, {7933, 1}, {7934, 16987907},
1154 	{7935, 1}, {7944, 16988163}, {7945, 16988419}, {7946, 16988675},
1155 	{7947, 16988931}, {7948, 16989187}, {7949, 16989443}, {7950, 16989699},
1156 	{7951, 16989955}, {7952, 1}, {7958, 2}, {7960, 16990211},
1157 	{7961, 16990467}, {7962, 16990723}, {7963, 16990979}, {7964, 16991235},
1158 	{7965, 16991491}, {7966, 2}, {7968, 1}, {7976, 16991747},
1159 	{7977, 16992003}, {7978, 16992259}, {7979, 16992515}, {7980, 16992771},
1160 	{7981, 16993027}, {7982, 16993283}, {7983, 16993539}, {7984, 1},
1161 	{7992, 16993795}, {7993, 16994051}, {7994, 16994307}, {7995, 16994563},
1162 	{7996, 16994819}, {7997, 16995075}, {7998, 16995331}, {7999, 16995587},
1163 	{8000, 1}, {8006, 2}, {8008, 16995843}, {8009, 16996099},
1164 	{8010, 16996355}, {8011, 16996611}, {8012, 16996867}, {8013, 16997123},
1165 	{8014, 2}, {8016, 1}, {8024, 2}, {8025, 16997379},
1166 	{8026, 2}, {8027, 16997635}, {8028, 2}, {8029, 16997891},
1167 	{8030, 2}, {8031, 16998147}, {8032, 1}, {8040, 16998403},
1168 	{8041, 16998659}, {8042, 16998915}, {8043, 16999171}, {8044, 16999427},
1169 	{8045, 16999683}, {8046, 16999939}, {8047, 17000195}, {8048, 1},
1170 	{8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1},
1171 	{8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1},
1172 	{8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1},
1173 	{8061, 16851459}, {8062, 2}, {8064, 33777667}, {8065, 33778179},
1174 	{8066, 33778691}, {8067, 33779203}, {8068, 33779715}, {8069, 33780227},
1175 	{8070, 33780739}, {8071, 33781251}, {8072, 33777667}, {8073, 33778179},
1176 	{8074, 33778691}, {8075, 33779203}, {8076, 33779715}, {8077, 33780227},
1177 	{8078, 33780739}, {8079, 33781251}, {8080, 33781763}, {8081, 33782275},
1178 	{8082, 33782787}, {8083, 33783299}, {8084, 33783811}, {8085, 33784323},
1179 	{8086, 33784835}, {8087, 33785347}, {8088, 33781763}, {8089, 33782275},
1180 	{8090, 33782787}, {8091, 33783299}, {8092, 33783811}, {8093, 33784323},
1181 	{8094, 33784835}, {8095, 33785347}, {8096, 33785859}, {8097, 33786371},
1182 	{8098, 33786883}, {8099, 33787395}, {8100, 33787907}, {8101, 33788419},
1183 	{8102, 33788931}, {8103, 33789443}, {8104, 33785859}, {8105, 33786371},
1184 	{8106, 33786883}, {8107, 33787395}, {8108, 33787907}, {8109, 33788419},
1185 	{8110, 33788931}, {8111, 33789443}, {8112, 1}, {8114, 33789955},
1186 	{8115, 33790467}, {8116, 33790979}, {8117, 2}, {8118, 1},
1187 	{8119, 33791491}, {8120, 17014787}, {8121, 17015043}, {8122, 17012739},
1188 	{8123, 16849923}, {8124, 33790467}, {8125, 33792515}, {8126, 16846851},
1189 	{8127, 33792515}, {8128, 33793027}, {8129, 50570755}, {8130, 33794307},
1190 	{8131, 33794819}, {8132, 33795331}, {8133, 2}, {8134, 1},
1191 	{8135, 33795843}, {8136, 17019139}, {8137, 16850179}, {8138, 17017091},
1192 	{8139, 16850435}, {8140, 33794819}, {8141, 50573827}, {8142, 50574595},
1193 	{8143, 50575363}, {8144, 1}, {8147, 17021699}, {8148, 2},
1194 	{8150, 1}, {8152, 17021955}, {8153, 17022211}, {8154, 17022467},
1195 	{8155, 16850691}, {8156, 2}, {8157, 50577155}, {8158, 50577923},
1196 	{8159, 50578691}, {8160, 1}, {8163, 17025027}, {8164, 1},
1197 	{8168, 17025283}, {8169, 17025539}, {8170, 17025795}, {8171, 16851203},
1198 	{8172, 17026051}, {8173, 50580739}, {8174, 50403587}, {8175, 17027075},
1199 	{8176, 2}, {8178, 33804547}, {8179, 33805059}, {8180, 33805571},
1200 	{8181, 2}, {8182, 1}, {8183, 33806083}, {8184, 17029379},
1201 	{8185, 16850947}, {8186, 17027331}, {8187, 16851459}, {8188, 33805059},
1202 	{8189, 33562883}, {8190, 33799939}, {8191, 2}, {8192, 16783875},
1203 	{8203, 0}, {8204, 1}, {8206, 2}, {8208, 1},
1204 	{8209, 17029635}, {8210, 1}, {8215, 33807107}, {8216, 1},
1205 	{8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875},
1206 	{8240, 1}, {8243, 33807619}, {8244, 50585347}, {8245, 1},
1207 	{8246, 33808899}, {8247, 50586627}, {8248, 1}, {8252, 33810179},
1208 	{8253, 1}, {8254, 33810691}, {8255, 1}, {8263, 33811203},
1209 	{8264, 33811715}, {8265, 33812227}, {8266, 1}, {8279, 67362051},
1210 	{8280, 1}, {8287, 16783875}, {8288, 0}, {8289, 2},
1211 	{8292, 0}, {8293, 2}, {8304, 17035523}, {8305, 16779267},
1212 	{8306, 2}, {8308, 16787715}, {8309, 17035779}, {8310, 17036035},
1213 	{8311, 17036291}, {8312, 17036547}, {8313, 17036803}, {8314, 17037059},
1214 	{8315, 17037315}, {8316, 17037571}, {8317, 17037827}, {8318, 17038083},
1215 	{8319, 16780547}, {8320, 17035523}, {8321, 16786947}, {8322, 16785155},
1216 	{8323, 16785411}, {8324, 16787715}, {8325, 17035779}, {8326, 17036035},
1217 	{8327, 17036291}, {8328, 17036547}, {8329, 17036803}, {8330, 17037059},
1218 	{8331, 17037315}, {8332, 17037571}, {8333, 17037827}, {8334, 17038083},
1219 	{8335, 2}, {8336, 16777219}, {8337, 16778243}, {8338, 16780803},
1220 	{8339, 16783107}, {8340, 16816387}, {8341, 16779011}, {8342, 16779779},
1221 	{8343, 16780035}, {8344, 16780291}, {8345, 16780547}, {8346, 16781059},
1222 	{8347, 16781827}, {8348, 16782083}, {8349, 2}, {8352, 1},
1223 	{8360, 33558787}, {8361, 1}, {8385, 2}, {8400, 1},
1224 	{8433, 2}, {8448, 50592771}, {8449, 50593539}, {8450, 16777731},
1225 	{8451, 33817091}, {8452, 1}, {8453, 50594819}, {8454, 50595587},
1226 	{8455, 16816643}, {8456, 1}, {8457, 33819139}, {8458, 16778755},
1227 	{8459, 16779011}, {8463, 16802051}, {8464, 16779267}, {8466, 16780035},
1228 	{8468, 1}, {8469, 16780547}, {8470, 33557763}, {8471, 1},
1229 	{8473, 16781059}, {8474, 16781315}, {8475, 16781571}, {8478, 1},
1230 	{8480, 33819651}, {8481, 50597379}, {8482, 33820931}, {8483, 1},
1231 	{8484, 16783619}, {8485, 1}, {8486, 16857091}, {8487, 1},
1232 	{8488, 16783619}, {8489, 1}, {8490, 16779779}, {8491, 16790787},
1233 	{8492, 16777475}, {8493, 16777731}, {8494, 1}, {8495, 16778243},
1234 	{8497, 16778499}, {8498, 2}, {8499, 16780291}, {8500, 16780803},
1235 	{8501, 17044227}, {8502, 17044483}, {8503, 17044739}, {8504, 17044995},
1236 	{8505, 16779267}, {8506, 1}, {8507, 50599683}, {8508, 16855043},
1237 	{8509, 16852227}, {8511, 16855043}, {8512, 17046019}, {8513, 1},
1238 	{8517, 16777987}, {8519, 16778243}, {8520, 16779267}, {8521, 16779523},
1239 	{8522, 1}, {8528, 50600707}, {8529, 50601475}, {8530, 67379459},
1240 	{8531, 50603267}, {8532, 50604035}, {8533, 50604803}, {8534, 50605571},
1241 	{8535, 50606339}, {8536, 50607107}, {8537, 50607875}, {8538, 50608643},
1242 	{8539, 50609411}, {8540, 50610179}, {8541, 50610947}, {8542, 50611715},
1243 	{8543, 33564419}, {8544, 16779267}, {8545, 33835267}, {8546, 50612995},
1244 	{8547, 33836547}, {8548, 16782595}, {8549, 33837059}, {8550, 50614787},
1245 	{8551, 67392771}, {8552, 33839363}, {8553, 16783107}, {8554, 33839875},
1246 	{8555, 50617603}, {8556, 16780035}, {8557, 16777731}, {8558, 16777987},
1247 	{8559, 16780291}, {8560, 16779267}, {8561, 33835267}, {8562, 50612483},
1248 	{8563, 33836547}, {8564, 16782595}, {8565, 33837059}, {8566, 50614787},
1249 	{8567, 67392771}, {8568, 33839363}, {8569, 16783107}, {8570, 33839875},
1250 	{8571, 50617603}, {8572, 16780035}, {8573, 16777731}, {8574, 16777987},
1251 	{8575, 16780291}, {8576, 1}, {8579, 2}, {8580, 1},
1252 	{8585, 50618371}, {8586, 1}, {8588, 2}, {8592, 1},
1253 	{8748, 33841923}, {8749, 50619651}, {8750, 1}, {8751, 33843203},
1254 	{8752, 50620931}, {8753, 1}, {9001, 17067267}, {9002, 17067523},
1255 	{9003, 1}, {9255, 2}, {9280, 1}, {9291, 2},
1256 	{9312, 16786947}, {9313, 16785155}, {9314, 16785411}, {9315, 16787715},
1257 	{9316, 17035779}, {9317, 17036035}, {9318, 17036291}, {9319, 17036547},
1258 	{9320, 17036803}, {9321, 33825539}, {9322, 33564163}, {9323, 33844995},
1259 	{9324, 33845507}, {9325, 33846019}, {9326, 33846531}, {9327, 33847043},
1260 	{9328, 33847555}, {9329, 33848067}, {9330, 33848579}, {9331, 33849091},
1261 	{9332, 50626819}, {9333, 50627587}, {9334, 50628355}, {9335, 50629123},
1262 	{9336, 50629891}, {9337, 50630659}, {9338, 50631427}, {9339, 50632195},
1263 	{9340, 50632963}, {9341, 67410947}, {9342, 67411971}, {9343, 67412995},
1264 	{9344, 67414019}, {9345, 67415043}, {9346, 67416067}, {9347, 67417091},
1265 	{9348, 67418115}, {9349, 67419139}, {9350, 67420163}, {9351, 67421187},
1266 	{9352, 2}, {9372, 50644995}, {9373, 50645763}, {9374, 50646531},
1267 	{9375, 50647299}, {9376, 50648067}, {9377, 50648835}, {9378, 50649603},
1268 	{9379, 50650371}, {9380, 50651139}, {9381, 50651907}, {9382, 50652675},
1269 	{9383, 50653443}, {9384, 50654211}, {9385, 50654979}, {9386, 50655747},
1270 	{9387, 50656515}, {9388, 50657283}, {9389, 50658051}, {9390, 50658819},
1271 	{9391, 50659587}, {9392, 50660355}, {9393, 50661123}, {9394, 50661891},
1272 	{9395, 50662659}, {9396, 50663427}, {9397, 50664195}, {9398, 16777219},
1273 	{9399, 16777475}, {9400, 16777731}, {9401, 16777987}, {9402, 16778243},
1274 	{9403, 16778499}, {9404, 16778755}, {9405, 16779011}, {9406, 16779267},
1275 	{9407, 16779523}, {9408, 16779779}, {9409, 16780035}, {9410, 16780291},
1276 	{9411, 16780547}, {9412, 16780803}, {9413, 16781059}, {9414, 16781315},
1277 	{9415, 16781571}, {9416, 16781827}, {9417, 16782083}, {9418, 16782339},
1278 	{9419, 16782595}, {9420, 16782851}, {9421, 16783107}, {9422, 16783363},
1279 	{9423, 16783619}, {9424, 16777219}, {9425, 16777475}, {9426, 16777731},
1280 	{9427, 16777987}, {9428, 16778243}, {9429, 16778499}, {9430, 16778755},
1281 	{9431, 16779011}, {9432, 16779267}, {9433, 16779523}, {9434, 16779779},
1282 	{9435, 16780035}, {9436, 16780291}, {9437, 16780547}, {9438, 16780803},
1283 	{9439, 16781059}, {9440, 16781315}, {9441, 16781571}, {9442, 16781827},
1284 	{9443, 16782083}, {9444, 16782339}, {9445, 16782595}, {9446, 16782851},
1285 	{9447, 16783107}, {9448, 16783363}, {9449, 16783619}, {9450, 17035523},
1286 	{9451, 1}, {10764, 67396355}, {10765, 1}, {10868, 50664963},
1287 	{10869, 33888515}, {10870, 50665475}, {10871, 1}, {10972, 33889027},
1288 	{10973, 1}, {11124, 2}, {11126, 1}, {11158, 2},
1289 	{11159, 1}, {11264, 17112323}, {11265, 17112579}, {11266, 17112835},
1290 	{11267, 17113091}, {11268, 17113347}, {11269, 17113603}, {11270, 17113859},
1291 	{11271, 17114115}, {11272, 17114371}, {11273, 17114627}, {11274, 17114883},
1292 	{11275, 17115139}, {11276, 17115395}, {11277, 17115651}, {11278, 17115907},
1293 	{11279, 17116163}, {11280, 17116419}, {11281, 17116675}, {11282, 17116931},
1294 	{11283, 17117187}, {11284, 17117443}, {11285, 17117699}, {11286, 17117955},
1295 	{11287, 17118211}, {11288, 17118467}, {11289, 17118723}, {11290, 17118979},
1296 	{11291, 17119235}, {11292, 17119491}, {11293, 17119747}, {11294, 17120003},
1297 	{11295, 17120259}, {11296, 17120515}, {11297, 17120771}, {11298, 17121027},
1298 	{11299, 17121283}, {11300, 17121539}, {11301, 17121795}, {11302, 17122051},
1299 	{11303, 17122307}, {11304, 17122563}, {11305, 17122819}, {11306, 17123075},
1300 	{11307, 17123331}, {11308, 17123587}, {11309, 17123843}, {11310, 17124099},
1301 	{11311, 17124355}, {11312, 1}, {11360, 17124611}, {11361, 1},
1302 	{11362, 17124867}, {11363, 17125123}, {11364, 17125379}, {11365, 1},
1303 	{11367, 17125635}, {11368, 1}, {11369, 17125891}, {11370, 1},
1304 	{11371, 17126147}, {11372, 1}, {11373, 16948483}, {11374, 16953091},
1305 	{11375, 16948227}, {11376, 16950275}, {11377, 1}, {11378, 17126403},
1306 	{11379, 1}, {11381, 17126659}, {11382, 1}, {11388, 16779523},
1307 	{11389, 16782595}, {11390, 17126915}, {11391, 17127171}, {11392, 17127427},
1308 	{11393, 1}, {11394, 17127683}, {11395, 1}, {11396, 17127939},
1309 	{11397, 1}, {11398, 17128195}, {11399, 1}, {11400, 17128451},
1310 	{11401, 1}, {11402, 17128707}, {11403, 1}, {11404, 17128963},
1311 	{11405, 1}, {11406, 17129219}, {11407, 1}, {11408, 17129475},
1312 	{11409, 1}, {11410, 17129731}, {11411, 1}, {11412, 17129987},
1313 	{11413, 1}, {11414, 17130243}, {11415, 1}, {11416, 17130499},
1314 	{11417, 1}, {11418, 17130755}, {11419, 1}, {11420, 17131011},
1315 	{11421, 1}, {11422, 17131267}, {11423, 1}, {11424, 17131523},
1316 	{11425, 1}, {11426, 17131779}, {11427, 1}, {11428, 17132035},
1317 	{11429, 1}, {11430, 17132291}, {11431, 1}, {11432, 17132547},
1318 	{11433, 1}, {11434, 17132803}, {11435, 1}, {11436, 17133059},
1319 	{11437, 1}, {11438, 17133315}, {11439, 1}, {11440, 17133571},
1320 	{11441, 1}, {11442, 17133827}, {11443, 1}, {11444, 17134083},
1321 	{11445, 1}, {11446, 17134339}, {11447, 1}, {11448, 17134595},
1322 	{11449, 1}, {11450, 17134851}, {11451, 1}, {11452, 17135107},
1323 	{11453, 1}, {11454, 17135363}, {11455, 1}, {11456, 17135619},
1324 	{11457, 1}, {11458, 17135875}, {11459, 1}, {11460, 17136131},
1325 	{11461, 1}, {11462, 17136387}, {11463, 1}, {11464, 17136643},
1326 	{11465, 1}, {11466, 17136899}, {11467, 1}, {11468, 17137155},
1327 	{11469, 1}, {11470, 17137411}, {11471, 1}, {11472, 17137667},
1328 	{11473, 1}, {11474, 17137923}, {11475, 1}, {11476, 17138179},
1329 	{11477, 1}, {11478, 17138435}, {11479, 1}, {11480, 17138691},
1330 	{11481, 1}, {11482, 17138947}, {11483, 1}, {11484, 17139203},
1331 	{11485, 1}, {11486, 17139459}, {11487, 1}, {11488, 17139715},
1332 	{11489, 1}, {11490, 17139971}, {11491, 1}, {11499, 17140227},
1333 	{11500, 1}, {11501, 17140483}, {11502, 1}, {11506, 17140739},
1334 	{11507, 1}, {11508, 2}, {11513, 1}, {11558, 2},
1335 	{11559, 1}, {11560, 2}, {11565, 1}, {11566, 2},
1336 	{11568, 1}, {11624, 2}, {11631, 17140995}, {11632, 1},
1337 	{11633, 2}, {11647, 1}, {11671, 2}, {11680, 1},
1338 	{11687, 2}, {11688, 1}, {11695, 2}, {11696, 1},
1339 	{11703, 2}, {11704, 1}, {11711, 2}, {11712, 1},
1340 	{11719, 2}, {11720, 1}, {11727, 2}, {11728, 1},
1341 	{11735, 2}, {11736, 1}, {11743, 2}, {11744, 1},
1342 	{11870, 2}, {11904, 1}, {11930, 2}, {11931, 1},
1343 	{11935, 17141251}, {11936, 1}, {12019, 17141507}, {12020, 2},
1344 	{12032, 17141763}, {12033, 17142019}, {12034, 17142275}, {12035, 17142531},
1345 	{12036, 17142787}, {12037, 17143043}, {12038, 17143299}, {12039, 17143555},
1346 	{12040, 17143811}, {12041, 17144067}, {12042, 17144323}, {12043, 17144579},
1347 	{12044, 17144835}, {12045, 17145091}, {12046, 17145347}, {12047, 17145603},
1348 	{12048, 17145859}, {12049, 17146115}, {12050, 17146371}, {12051, 17146627},
1349 	{12052, 17146883}, {12053, 17147139}, {12054, 17147395}, {12055, 17147651},
1350 	{12056, 17147907}, {12057, 17148163}, {12058, 17148419}, {12059, 17148675},
1351 	{12060, 17148931}, {12061, 17149187}, {12062, 17149443}, {12063, 17149699},
1352 	{12064, 17149955}, {12065, 17150211}, {12066, 17150467}, {12067, 17150723},
1353 	{12068, 17150979}, {12069, 17151235}, {12070, 17151491}, {12071, 17151747},
1354 	{12072, 17152003}, {12073, 17152259}, {12074, 17152515}, {12075, 17152771},
1355 	{12076, 17153027}, {12077, 17153283}, {12078, 17153539}, {12079, 17153795},
1356 	{12080, 17154051}, {12081, 17154307}, {12082, 17154563}, {12083, 17154819},
1357 	{12084, 17155075}, {12085, 17155331}, {12086, 17155587}, {12087, 17155843},
1358 	{12088, 17156099}, {12089, 17156355}, {12090, 17156611}, {12091, 17156867},
1359 	{12092, 17157123}, {12093, 17157379}, {12094, 17157635}, {12095, 17157891},
1360 	{12096, 17158147}, {12097, 17158403}, {12098, 17158659}, {12099, 17158915},
1361 	{12100, 17159171}, {12101, 17159427}, {12102, 17159683}, {12103, 17159939},
1362 	{12104, 17160195}, {12105, 17160451}, {12106, 17160707}, {12107, 17160963},
1363 	{12108, 17161219}, {12109, 17161475}, {12110, 17161731}, {12111, 17161987},
1364 	{12112, 17162243}, {12113, 17162499}, {12114, 17162755}, {12115, 17163011},
1365 	{12116, 17163267}, {12117, 17163523}, {12118, 17163779}, {12119, 17164035},
1366 	{12120, 17164291}, {12121, 17164547}, {12122, 17164803}, {12123, 17165059},
1367 	{12124, 17165315}, {12125, 17165571}, {12126, 17165827}, {12127, 17166083},
1368 	{12128, 17166339}, {12129, 17166595}, {12130, 17166851}, {12131, 17167107},
1369 	{12132, 17167363}, {12133, 17167619}, {12134, 17167875}, {12135, 17168131},
1370 	{12136, 17168387}, {12137, 17168643}, {12138, 17168899}, {12139, 17169155},
1371 	{12140, 17169411}, {12141, 17169667}, {12142, 17169923}, {12143, 17170179},
1372 	{12144, 17170435}, {12145, 17170691}, {12146, 17170947}, {12147, 17171203},
1373 	{12148, 17171459}, {12149, 17171715}, {12150, 17171971}, {12151, 17172227},
1374 	{12152, 17172483}, {12153, 17172739}, {12154, 17172995}, {12155, 17173251},
1375 	{12156, 17173507}, {12157, 17173763}, {12158, 17174019}, {12159, 17174275},
1376 	{12160, 17174531}, {12161, 17174787}, {12162, 17175043}, {12163, 17175299},
1377 	{12164, 17175555}, {12165, 17175811}, {12166, 17176067}, {12167, 17176323},
1378 	{12168, 17176579}, {12169, 17176835}, {12170, 17177091}, {12171, 17177347},
1379 	{12172, 17177603}, {12173, 17177859}, {12174, 17178115}, {12175, 17178371},
1380 	{12176, 17178627}, {12177, 17178883}, {12178, 17179139}, {12179, 17179395},
1381 	{12180, 17179651}, {12181, 17179907}, {12182, 17180163}, {12183, 17180419},
1382 	{12184, 17180675}, {12185, 17180931}, {12186, 17181187}, {12187, 17181443},
1383 	{12188, 17181699}, {12189, 17181955}, {12190, 17182211}, {12191, 17182467},
1384 	{12192, 17182723}, {12193, 17182979}, {12194, 17183235}, {12195, 17183491},
1385 	{12196, 17183747}, {12197, 17184003}, {12198, 17184259}, {12199, 17184515},
1386 	{12200, 17184771}, {12201, 17185027}, {12202, 17185283}, {12203, 17185539},
1387 	{12204, 17185795}, {12205, 17186051}, {12206, 17186307}, {12207, 17186563},
1388 	{12208, 17186819}, {12209, 17187075}, {12210, 17187331}, {12211, 17187587},
1389 	{12212, 17187843}, {12213, 17188099}, {12214, 17188355}, {12215, 17188611},
1390 	{12216, 17188867}, {12217, 17189123}, {12218, 17189379}, {12219, 17189635},
1391 	{12220, 17189891}, {12221, 17190147}, {12222, 17190403}, {12223, 17190659},
1392 	{12224, 17190915}, {12225, 17191171}, {12226, 17191427}, {12227, 17191683},
1393 	{12228, 17191939}, {12229, 17192195}, {12230, 17192451}, {12231, 17192707},
1394 	{12232, 17192963}, {12233, 17193219}, {12234, 17193475}, {12235, 17193731},
1395 	{12236, 17193987}, {12237, 17194243}, {12238, 17194499}, {12239, 17194755},
1396 	{12240, 17195011}, {12241, 17195267}, {12242, 17195523}, {12243, 17195779},
1397 	{12244, 17196035}, {12245, 17196291}, {12246, 2}, {12288, 16783875},
1398 	{12289, 1}, {12290, 17196547}, {12291, 1}, {12342, 17196803},
1399 	{12343, 1}, {12344, 17147651}, {12345, 17197059}, {12346, 17197315},
1400 	{12347, 1}, {12352, 2}, {12353, 1}, {12439, 2},
1401 	{12441, 1}, {12443, 33974787}, {12444, 33975299}, {12445, 1},
1402 	{12447, 33975811}, {12448, 1}, {12543, 33976323}, {12544, 2},
1403 	{12549, 1}, {12592, 2}, {12593, 17199619}, {12594, 17199875},
1404 	{12595, 17200131}, {12596, 17200387}, {12597, 17200643}, {12598, 17200899},
1405 	{12599, 17201155}, {12600, 17201411}, {12601, 17201667}, {12602, 17201923},
1406 	{12603, 17202179}, {12604, 17202435}, {12605, 17202691}, {12606, 17202947},
1407 	{12607, 17203203}, {12608, 17203459}, {12609, 17203715}, {12610, 17203971},
1408 	{12611, 17204227}, {12612, 17204483}, {12613, 17204739}, {12614, 17204995},
1409 	{12615, 17205251}, {12616, 17205507}, {12617, 17205763}, {12618, 17206019},
1410 	{12619, 17206275}, {12620, 17206531}, {12621, 17206787}, {12622, 17207043},
1411 	{12623, 17207299}, {12624, 17207555}, {12625, 17207811}, {12626, 17208067},
1412 	{12627, 17208323}, {12628, 17208579}, {12629, 17208835}, {12630, 17209091},
1413 	{12631, 17209347}, {12632, 17209603}, {12633, 17209859}, {12634, 17210115},
1414 	{12635, 17210371}, {12636, 17210627}, {12637, 17210883}, {12638, 17211139},
1415 	{12639, 17211395}, {12640, 17211651}, {12641, 17211907}, {12642, 17212163},
1416 	{12643, 17212419}, {12644, 2}, {12645, 17212675}, {12646, 17212931},
1417 	{12647, 17213187}, {12648, 17213443}, {12649, 17213699}, {12650, 17213955},
1418 	{12651, 17214211}, {12652, 17214467}, {12653, 17214723}, {12654, 17214979},
1419 	{12655, 17215235}, {12656, 17215491}, {12657, 17215747}, {12658, 17216003},
1420 	{12659, 17216259}, {12660, 17216515}, {12661, 17216771}, {12662, 17217027},
1421 	{12663, 17217283}, {12664, 17217539}, {12665, 17217795}, {12666, 17218051},
1422 	{12667, 17218307}, {12668, 17218563}, {12669, 17218819}, {12670, 17219075},
1423 	{12671, 17219331}, {12672, 17219587}, {12673, 17219843}, {12674, 17220099},
1424 	{12675, 17220355}, {12676, 17220611}, {12677, 17220867}, {12678, 17221123},
1425 	{12679, 17221379}, {12680, 17221635}, {12681, 17221891}, {12682, 17222147},
1426 	{12683, 17222403}, {12684, 17222659}, {12685, 17222915}, {12686, 17223171},
1427 	{12687, 2}, {12688, 1}, {12690, 17141763}, {12691, 17143299},
1428 	{12692, 17223427}, {12693, 17223683}, {12694, 17223939}, {12695, 17224195},
1429 	{12696, 17224451}, {12697, 17224707}, {12698, 17142787}, {12699, 17224963},
1430 	{12700, 17225219}, {12701, 17225475}, {12702, 17225731}, {12703, 17143811},
1431 	{12704, 1}, {12772, 2}, {12784, 1}, {12800, 50780419},
1432 	{12801, 50781187}, {12802, 50781955}, {12803, 50782723}, {12804, 50783491},
1433 	{12805, 50784259}, {12806, 50785027}, {12807, 50785795}, {12808, 50786563},
1434 	{12809, 50787331}, {12810, 50788099}, {12811, 50788867}, {12812, 50789635},
1435 	{12813, 50790403}, {12814, 50791171}, {12815, 50791939}, {12816, 50792707},
1436 	{12817, 50793475}, {12818, 50794243}, {12819, 50795011}, {12820, 50795779},
1437 	{12821, 50796547}, {12822, 50797315}, {12823, 50798083}, {12824, 50798851},
1438 	{12825, 50799619}, {12826, 50800387}, {12827, 50801155}, {12828, 50801923},
1439 	{12829, 67579907}, {12830, 67580931}, {12831, 2}, {12832, 50804739},
1440 	{12833, 50805507}, {12834, 50806275}, {12835, 50807043}, {12836, 50807811},
1441 	{12837, 50808579}, {12838, 50809347}, {12839, 50810115}, {12840, 50810883},
1442 	{12841, 50811651}, {12842, 50812419}, {12843, 50813187}, {12844, 50813955},
1443 	{12845, 50814723}, {12846, 50815491}, {12847, 50816259}, {12848, 50817027},
1444 	{12849, 50817795}, {12850, 50818563}, {12851, 50819331}, {12852, 50820099},
1445 	{12853, 50820867}, {12854, 50821635}, {12855, 50822403}, {12856, 50823171},
1446 	{12857, 50823939}, {12858, 50824707}, {12859, 50825475}, {12860, 50826243},
1447 	{12861, 50827011}, {12862, 50827779}, {12863, 50828547}, {12864, 50829315},
1448 	{12865, 50830083}, {12866, 50830851}, {12867, 50831619}, {12868, 17277955},
1449 	{12869, 17278211}, {12870, 17158659}, {12871, 17278467}, {12872, 1},
1450 	{12880, 50833155}, {12881, 33845251}, {12882, 34056707}, {12883, 33562371},
1451 	{12884, 34057219}, {12885, 34057731}, {12886, 34058243}, {12887, 34058755},
1452 	{12888, 34059267}, {12889, 34059779}, {12890, 34060291}, {12891, 33827331},
1453 	{12892, 33826563}, {12893, 34060803}, {12894, 34061315}, {12895, 34061827},
1454 	{12896, 17199619}, {12897, 17200387}, {12898, 17201155}, {12899, 17201667},
1455 	{12900, 17203715}, {12901, 17203971}, {12902, 17204739}, {12903, 17205251},
1456 	{12904, 17205507}, {12905, 17206019}, {12906, 17206275}, {12907, 17206531},
1457 	{12908, 17206787}, {12909, 17207043}, {12910, 17236995}, {12911, 17237763},
1458 	{12912, 17238531}, {12913, 17239299}, {12914, 17240067}, {12915, 17240835},
1459 	{12916, 17241603}, {12917, 17242371}, {12918, 17243139}, {12919, 17243907},
1460 	{12920, 17244675}, {12921, 17245443}, {12922, 17246211}, {12923, 17246979},
1461 	{12924, 34062339}, {12925, 34062851}, {12926, 17286147}, {12927, 1},
1462 	{12928, 17141763}, {12929, 17143299}, {12930, 17223427}, {12931, 17223683},
1463 	{12932, 17253635}, {12933, 17254403}, {12934, 17255171}, {12935, 17144579},
1464 	{12936, 17256707}, {12937, 17147651}, {12938, 17160451}, {12939, 17163523},
1465 	{12940, 17163267}, {12941, 17160707}, {12942, 17184259}, {12943, 17149699},
1466 	{12944, 17159939}, {12945, 17263619}, {12946, 17264387}, {12947, 17265155},
1467 	{12948, 17265923}, {12949, 17266691}, {12950, 17267459}, {12951, 17268227},
1468 	{12952, 17268995}, {12953, 17286403}, {12954, 17286659}, {12955, 17151235},
1469 	{12956, 17286915}, {12957, 17287171}, {12958, 17287427}, {12959, 17287683},
1470 	{12960, 17287939}, {12961, 17275907}, {12962, 17288195}, {12963, 17288451},
1471 	{12964, 17223939}, {12965, 17224195}, {12966, 17224451}, {12967, 17288707},
1472 	{12968, 17288963}, {12969, 17289219}, {12970, 17289475}, {12971, 17271299},
1473 	{12972, 17272067}, {12973, 17272835}, {12974, 17273603}, {12975, 17274371},
1474 	{12976, 17289731}, {12977, 34067203}, {12978, 34067715}, {12979, 34068227},
1475 	{12980, 34068739}, {12981, 34069251}, {12982, 33564931}, {12983, 34057475},
1476 	{12984, 34061571}, {12985, 34069763}, {12986, 34070275}, {12987, 34070787},
1477 	{12988, 34071299}, {12989, 34071811}, {12990, 34072323}, {12991, 34072835},
1478 	{12992, 34073347}, {12993, 34073859}, {12994, 34074371}, {12995, 34074883},
1479 	{12996, 34075395}, {12997, 34075907}, {12998, 34076419}, {12999, 34076931},
1480 	{13000, 34077443}, {13001, 50855171}, {13002, 50855939}, {13003, 50856707},
1481 	{13004, 34080259}, {13005, 50857987}, {13006, 34081539}, {13007, 50859267},
1482 	{13008, 17305603}, {13009, 17305859}, {13010, 17306115}, {13011, 17306371},
1483 	{13012, 17306627}, {13013, 17306883}, {13014, 17307139}, {13015, 17307395},
1484 	{13016, 17307651}, {13017, 17199107}, {13018, 17307907}, {13019, 17308163},
1485 	{13020, 17308419}, {13021, 17308675}, {13022, 17308931}, {13023, 17309187},
1486 	{13024, 17309443}, {13025, 17309699}, {13026, 17309955}, {13027, 17199363},
1487 	{13028, 17310211}, {13029, 17310467}, {13030, 17310723}, {13031, 17310979},
1488 	{13032, 17311235}, {13033, 17311491}, {13034, 17311747}, {13035, 17312003},
1489 	{13036, 17312259}, {13037, 17312515}, {13038, 17312771}, {13039, 17313027},
1490 	{13040, 17313283}, {13041, 17313539}, {13042, 17313795}, {13043, 17314051},
1491 	{13044, 17314307}, {13045, 17314563}, {13046, 17314819}, {13047, 17315075},
1492 	{13048, 17315331}, {13049, 17315587}, {13050, 17315843}, {13051, 17316099},
1493 	{13052, 17316355}, {13053, 17316611}, {13054, 17316867}, {13055, 34094339},
1494 	{13056, 67649283}, {13057, 67650307}, {13058, 67651331}, {13059, 50875139},
1495 	{13060, 67653123}, {13061, 50876931}, {13062, 50877699}, {13063, 84432899},
1496 	{13064, 67656963}, {13065, 50880771}, {13066, 50881539}, {13067, 50882307},
1497 	{13068, 67660291}, {13069, 67661315}, {13070, 50885123}, {13071, 50885891},
1498 	{13072, 34109443}, {13073, 50887171}, {13074, 67665155}, {13075, 67666179},
1499 	{13076, 34112771}, {13077, 84444931}, {13078, 101223427}, {13079, 84447747},
1500 	{13080, 50891011}, {13081, 84449027}, {13082, 84450307}, {13083, 67674371},
1501 	{13084, 50898179}, {13085, 50898947}, {13086, 50899715}, {13087, 67677699},
1502 	{13088, 84455939}, {13089, 67680003}, {13090, 50903811}, {13091, 50904579},
1503 	{13092, 50905347}, {13093, 34128899}, {13094, 34129411}, {13095, 34118147},
1504 	{13096, 34129923}, {13097, 50907651}, {13098, 50908419}, {13099, 84463619},
1505 	{13100, 50910467}, {13101, 67688451}, {13102, 84466691}, {13103, 50913539},
1506 	{13104, 34137091}, {13105, 34137603}, {13106, 84469763}, {13107, 67693827},
1507 	{13108, 84472067}, {13109, 50918915}, {13110, 84474115}, {13111, 34143747},
1508 	{13112, 50921475}, {13113, 50922243}, {13114, 50923011}, {13115, 50923779},
1509 	{13116, 50924547}, {13117, 67702531}, {13118, 50926339}, {13119, 34149891},
1510 	{13120, 50927619}, {13121, 50928387}, {13122, 50929155}, {13123, 67707139},
1511 	{13124, 50930947}, {13125, 50931715}, {13126, 50932483}, {13127, 84487683},
1512 	{13128, 67711747}, {13129, 34158339}, {13130, 84490499}, {13131, 34160131},
1513 	{13132, 67715075}, {13133, 67669507}, {13134, 50938883}, {13135, 50939651},
1514 	{13136, 50940419}, {13137, 67718403}, {13138, 34164995}, {13139, 50942723},
1515 	{13140, 67720707}, {13141, 34167299}, {13142, 84499459}, {13143, 50893827},
1516 	{13144, 34169091}, {13145, 34169603}, {13146, 34170115}, {13147, 34170627},
1517 	{13148, 34171139}, {13149, 34171651}, {13150, 34172163}, {13151, 34172675},
1518 	{13152, 34173187}, {13153, 34173699}, {13154, 50951427}, {13155, 50952195},
1519 	{13156, 50952963}, {13157, 50953731}, {13158, 50954499}, {13159, 50955267},
1520 	{13160, 50956035}, {13161, 50956803}, {13162, 50957571}, {13163, 50958339},
1521 	{13164, 50959107}, {13165, 50959875}, {13166, 50960643}, {13167, 50961411},
1522 	{13168, 50962179}, {13169, 50962947}, {13170, 34186499}, {13171, 34187011},
1523 	{13172, 50964739}, {13173, 34188291}, {13174, 34188803}, {13175, 34189315},
1524 	{13176, 50967043}, {13177, 50967811}, {13178, 34191363}, {13179, 34191875},
1525 	{13180, 34192387}, {13181, 34192899}, {13182, 34193411}, {13183, 67748355},
1526 	{13184, 34185987}, {13185, 34194947}, {13186, 34195459}, {13187, 34195971},
1527 	{13188, 34196483}, {13189, 34196995}, {13190, 34197507}, {13191, 34198019},
1528 	{13192, 50975747}, {13193, 67753731}, {13194, 34200323}, {13195, 34200835},
1529 	{13196, 34201347}, {13197, 34201859}, {13198, 34202371}, {13199, 34202883},
1530 	{13200, 34203395}, {13201, 50981123}, {13202, 50981891}, {13203, 50980355},
1531 	{13204, 50982659}, {13205, 34206211}, {13206, 34206723}, {13207, 34207235},
1532 	{13208, 33556995}, {13209, 34207747}, {13210, 34208259}, {13211, 34208771},
1533 	{13212, 34209283}, {13213, 34209795}, {13214, 34210307}, {13215, 50988035},
1534 	{13216, 50988803}, {13217, 34190083}, {13218, 50989571}, {13219, 50990339},
1535 	{13220, 50991107}, {13221, 34190851}, {13222, 50991875}, {13223, 50992643},
1536 	{13224, 67770627}, {13225, 34185987}, {13226, 50994435}, {13227, 50995203},
1537 	{13228, 50995971}, {13229, 50996739}, {13230, 84551939}, {13231, 101330435},
1538 	{13232, 34223107}, {13233, 34223619}, {13234, 34224131}, {13235, 34224643},
1539 	{13236, 34225155}, {13237, 34225667}, {13238, 34226179}, {13239, 34226691},
1540 	{13240, 34227203}, {13241, 34226691}, {13242, 34227715}, {13243, 34228227},
1541 	{13244, 34228739}, {13245, 34229251}, {13246, 34229763}, {13247, 34229251},
1542 	{13248, 34230275}, {13249, 34230787}, {13250, 2}, {13251, 34231299},
1543 	{13252, 33817347}, {13253, 33554947}, {13254, 67786243}, {13255, 2},
1544 	{13256, 34232835}, {13257, 34233347}, {13258, 34233859}, {13259, 34185731},
1545 	{13260, 34234371}, {13261, 34234883}, {13262, 34210307}, {13263, 34235395},
1546 	{13264, 33557251}, {13265, 34235907}, {13266, 51013635}, {13267, 34237187},
1547 	{13268, 34197507}, {13269, 51014915}, {13270, 51015683}, {13271, 34239235},
1548 	{13272, 2}, {13273, 51016963}, {13274, 34240515}, {13275, 34221315},
1549 	{13276, 34241027}, {13277, 34241539}, {13278, 51019267}, {13279, 51020035},
1550 	{13280, 34243587}, {13281, 34244099}, {13282, 34244611}, {13283, 34245123},
1551 	{13284, 34245635}, {13285, 34246147}, {13286, 34246659}, {13287, 34247171},
1552 	{13288, 34247683}, {13289, 51025411}, {13290, 51026179}, {13291, 51026947},
1553 	{13292, 51027715}, {13293, 51028483}, {13294, 51029251}, {13295, 51030019},
1554 	{13296, 51030787}, {13297, 51031555}, {13298, 51032323}, {13299, 51033091},
1555 	{13300, 51033859}, {13301, 51034627}, {13302, 51035395}, {13303, 51036163},
1556 	{13304, 51036931}, {13305, 51037699}, {13306, 51038467}, {13307, 51039235},
1557 	{13308, 51040003}, {13309, 51040771}, {13310, 51041539}, {13311, 51042307},
1558 	{13312, 1}, {42125, 2}, {42128, 1}, {42183, 2},
1559 	{42192, 1}, {42540, 2}, {42560, 17488643}, {42561, 1},
1560 	{42562, 17488899}, {42563, 1}, {42564, 17489155}, {42565, 1},
1561 	{42566, 17489411}, {42567, 1}, {42568, 17489667}, {42569, 1},
1562 	{42570, 16936451}, {42571, 1}, {42572, 17489923}, {42573, 1},
1563 	{42574, 17490179}, {42575, 1}, {42576, 17490435}, {42577, 1},
1564 	{42578, 17490691}, {42579, 1}, {42580, 17490947}, {42581, 1},
1565 	{42582, 17491203}, {42583, 1}, {42584, 17491459}, {42585, 1},
1566 	{42586, 17491715}, {42587, 1}, {42588, 17491971}, {42589, 1},
1567 	{42590, 17492227}, {42591, 1}, {42592, 17492483}, {42593, 1},
1568 	{42594, 17492739}, {42595, 1}, {42596, 17492995}, {42597, 1},
1569 	{42598, 17493251}, {42599, 1}, {42600, 17493507}, {42601, 1},
1570 	{42602, 17493763}, {42603, 1}, {42604, 17494019}, {42605, 1},
1571 	{42624, 17494275}, {42625, 1}, {42626, 17494531}, {42627, 1},
1572 	{42628, 17494787}, {42629, 1}, {42630, 17495043}, {42631, 1},
1573 	{42632, 17495299}, {42633, 1}, {42634, 17495555}, {42635, 1},
1574 	{42636, 17495811}, {42637, 1}, {42638, 17496067}, {42639, 1},
1575 	{42640, 17496323}, {42641, 1}, {42642, 17496579}, {42643, 1},
1576 	{42644, 17496835}, {42645, 1}, {42646, 17497091}, {42647, 1},
1577 	{42648, 17497347}, {42649, 1}, {42650, 17497603}, {42651, 1},
1578 	{42652, 16873219}, {42653, 16873731}, {42654, 1}, {42744, 2},
1579 	{42752, 1}, {42786, 17497859}, {42787, 1}, {42788, 17498115},
1580 	{42789, 1}, {42790, 17498371}, {42791, 1}, {42792, 17498627},
1581 	{42793, 1}, {42794, 17498883}, {42795, 1}, {42796, 17499139},
1582 	{42797, 1}, {42798, 17499395}, {42799, 1}, {42802, 17499651},
1583 	{42803, 1}, {42804, 17499907}, {42805, 1}, {42806, 17500163},
1584 	{42807, 1}, {42808, 17500419}, {42809, 1}, {42810, 17500675},
1585 	{42811, 1}, {42812, 17500931}, {42813, 1}, {42814, 17501187},
1586 	{42815, 1}, {42816, 17501443}, {42817, 1}, {42818, 17501699},
1587 	{42819, 1}, {42820, 17501955}, {42821, 1}, {42822, 17502211},
1588 	{42823, 1}, {42824, 17502467}, {42825, 1}, {42826, 17502723},
1589 	{42827, 1}, {42828, 17502979}, {42829, 1}, {42830, 17503235},
1590 	{42831, 1}, {42832, 17503491}, {42833, 1}, {42834, 17503747},
1591 	{42835, 1}, {42836, 17504003}, {42837, 1}, {42838, 17504259},
1592 	{42839, 1}, {42840, 17504515}, {42841, 1}, {42842, 17504771},
1593 	{42843, 1}, {42844, 17505027}, {42845, 1}, {42846, 17505283},
1594 	{42847, 1}, {42848, 17505539}, {42849, 1}, {42850, 17505795},
1595 	{42851, 1}, {42852, 17506051}, {42853, 1}, {42854, 17506307},
1596 	{42855, 1}, {42856, 17506563}, {42857, 1}, {42858, 17506819},
1597 	{42859, 1}, {42860, 17507075}, {42861, 1}, {42862, 17507331},
1598 	{42863, 1}, {42864, 17507331}, {42865, 1}, {42873, 17507587},
1599 	{42874, 1}, {42875, 17507843}, {42876, 1}, {42877, 17508099},
1600 	{42878, 17508355}, {42879, 1}, {42880, 17508611}, {42881, 1},
1601 	{42882, 17508867}, {42883, 1}, {42884, 17509123}, {42885, 1},
1602 	{42886, 17509379}, {42887, 1}, {42891, 17509635}, {42892, 1},
1603 	{42893, 16951299}, {42894, 1}, {42896, 17509891}, {42897, 1},
1604 	{42898, 17510147}, {42899, 1}, {42902, 17510403}, {42903, 1},
1605 	{42904, 17510659}, {42905, 1}, {42906, 17510915}, {42907, 1},
1606 	{42908, 17511171}, {42909, 1}, {42910, 17511427}, {42911, 1},
1607 	{42912, 17511683}, {42913, 1}, {42914, 17511939}, {42915, 1},
1608 	{42916, 17512195}, {42917, 1}, {42918, 17512451}, {42919, 1},
1609 	{42920, 17512707}, {42921, 1}, {42922, 16841475}, {42923, 16948995},
1610 	{42924, 16951043}, {42925, 17512963}, {42926, 16951555}, {42927, 1},
1611 	{42928, 17513219}, {42929, 17513475}, {42930, 16952067}, {42931, 17513731},
1612 	{42932, 17513987}, {42933, 1}, {42934, 17514243}, {42935, 1},
1613 	{42936, 17514499}, {42937, 1}, {42938, 17514755}, {42939, 1},
1614 	{42940, 17515011}, {42941, 1}, {42942, 17515267}, {42943, 1},
1615 	{42944, 17515523}, {42945, 1}, {42946, 17515779}, {42947, 1},
1616 	{42948, 17516035}, {42949, 16954371}, {42950, 17516291}, {42951, 17516547},
1617 	{42952, 1}, {42953, 17516803}, {42954, 1}, {42955, 2},
1618 	{42960, 17517059}, {42961, 1}, {42962, 2}, {42963, 1},
1619 	{42964, 2}, {42965, 1}, {42966, 17517315}, {42967, 1},
1620 	{42968, 17517571}, {42969, 1}, {42970, 2}, {42994, 16777731},
1621 	{42995, 16778499}, {42996, 16781315}, {42997, 17517827}, {42998, 1},
1622 	{43000, 16802051}, {43001, 16808195}, {43002, 1}, {43053, 2},
1623 	{43056, 1}, {43066, 2}, {43072, 1}, {43128, 2},
1624 	{43136, 1}, {43206, 2}, {43214, 1}, {43226, 2},
1625 	{43232, 1}, {43348, 2}, {43359, 1}, {43389, 2},
1626 	{43392, 1}, {43470, 2}, {43471, 1}, {43482, 2},
1627 	{43486, 1}, {43519, 2}, {43520, 1}, {43575, 2},
1628 	{43584, 1}, {43598, 2}, {43600, 1}, {43610, 2},
1629 	{43612, 1}, {43715, 2}, {43739, 1}, {43767, 2},
1630 	{43777, 1}, {43783, 2}, {43785, 1}, {43791, 2},
1631 	{43793, 1}, {43799, 2}, {43808, 1}, {43815, 2},
1632 	{43816, 1}, {43823, 2}, {43824, 1}, {43868, 17498371},
1633 	{43869, 17518083}, {43870, 17124867}, {43871, 17518339}, {43872, 1},
1634 	{43881, 17518595}, {43882, 1}, {43884, 2}, {43888, 17518851},
1635 	{43889, 17519107}, {43890, 17519363}, {43891, 17519619}, {43892, 17519875},
1636 	{43893, 17520131}, {43894, 17520387}, {43895, 17520643}, {43896, 17520899},
1637 	{43897, 17521155}, {43898, 17521411}, {43899, 17521667}, {43900, 17521923},
1638 	{43901, 17522179}, {43902, 17522435}, {43903, 17522691}, {43904, 17522947},
1639 	{43905, 17523203}, {43906, 17523459}, {43907, 17523715}, {43908, 17523971},
1640 	{43909, 17524227}, {43910, 17524483}, {43911, 17524739}, {43912, 17524995},
1641 	{43913, 17525251}, {43914, 17525507}, {43915, 17525763}, {43916, 17526019},
1642 	{43917, 17526275}, {43918, 17526531}, {43919, 17526787}, {43920, 17527043},
1643 	{43921, 17527299}, {43922, 17527555}, {43923, 17527811}, {43924, 17528067},
1644 	{43925, 17528323}, {43926, 17528579}, {43927, 17528835}, {43928, 17529091},
1645 	{43929, 17529347}, {43930, 17529603}, {43931, 17529859}, {43932, 17530115},
1646 	{43933, 17530371}, {43934, 17530627}, {43935, 17530883}, {43936, 17531139},
1647 	{43937, 17531395}, {43938, 17531651}, {43939, 17531907}, {43940, 17532163},
1648 	{43941, 17532419}, {43942, 17532675}, {43943, 17532931}, {43944, 17533187},
1649 	{43945, 17533443}, {43946, 17533699}, {43947, 17533955}, {43948, 17534211},
1650 	{43949, 17534467}, {43950, 17534723}, {43951, 17534979}, {43952, 17535235},
1651 	{43953, 17535491}, {43954, 17535747}, {43955, 17536003}, {43956, 17536259},
1652 	{43957, 17536515}, {43958, 17536771}, {43959, 17537027}, {43960, 17537283},
1653 	{43961, 17537539}, {43962, 17537795}, {43963, 17538051}, {43964, 17538307},
1654 	{43965, 17538563}, {43966, 17538819}, {43967, 17539075}, {43968, 1},
1655 	{44014, 2}, {44016, 1}, {44026, 2}, {44032, 1},
1656 	{55204, 2}, {55216, 1}, {55239, 2}, {55243, 1},
1657 	{55292, 2}, {63744, 17539331}, {63745, 17539587}, {63746, 17182211},
1658 	{63747, 17539843}, {63748, 17540099}, {63749, 17540355}, {63750, 17540611},
1659 	{63751, 17196035}, {63753, 17540867}, {63754, 17184259}, {63755, 17541123},
1660 	{63756, 17541379}, {63757, 17541635}, {63758, 17541891}, {63759, 17542147},
1661 	{63760, 17542403}, {63761, 17542659}, {63762, 17542915}, {63763, 17543171},
1662 	{63764, 17543427}, {63765, 17543683}, {63766, 17543939}, {63767, 17544195},
1663 	{63768, 17544451}, {63769, 17544707}, {63770, 17544963}, {63771, 17545219},
1664 	{63772, 17545475}, {63773, 17545731}, {63774, 17545987}, {63775, 17546243},
1665 	{63776, 17546499}, {63777, 17546755}, {63778, 17547011}, {63779, 17547267},
1666 	{63780, 17547523}, {63781, 17547779}, {63782, 17548035}, {63783, 17548291},
1667 	{63784, 17548547}, {63785, 17548803}, {63786, 17549059}, {63787, 17549315},
1668 	{63788, 17549571}, {63789, 17549827}, {63790, 17550083}, {63791, 17550339},
1669 	{63792, 17550595}, {63793, 17550851}, {63794, 17551107}, {63795, 17551363},
1670 	{63796, 17173507}, {63797, 17551619}, {63798, 17551875}, {63799, 17552131},
1671 	{63800, 17552387}, {63801, 17552643}, {63802, 17552899}, {63803, 17553155},
1672 	{63804, 17553411}, {63805, 17553667}, {63806, 17553923}, {63807, 17554179},
1673 	{63808, 17192195}, {63809, 17554435}, {63810, 17554691}, {63811, 17554947},
1674 	{63812, 17555203}, {63813, 17555459}, {63814, 17555715}, {63815, 17555971},
1675 	{63816, 17556227}, {63817, 17556483}, {63818, 17556739}, {63819, 17556995},
1676 	{63820, 17557251}, {63821, 17557507}, {63822, 17557763}, {63823, 17558019},
1677 	{63824, 17558275}, {63825, 17558531}, {63826, 17558787}, {63827, 17559043},
1678 	{63828, 17559299}, {63829, 17559555}, {63830, 17559811}, {63831, 17560067},
1679 	{63832, 17560323}, {63833, 17560579}, {63834, 17560835}, {63835, 17561091},
1680 	{63836, 17543427}, {63837, 17561347}, {63838, 17561603}, {63839, 17561859},
1681 	{63840, 17562115}, {63841, 17562371}, {63842, 17562627}, {63843, 17562883},
1682 	{63844, 17563139}, {63845, 17563395}, {63846, 17563651}, {63847, 17563907},
1683 	{63848, 17564163}, {63849, 17564419}, {63850, 17564675}, {63851, 17564931},
1684 	{63852, 17565187}, {63853, 17565443}, {63854, 17565699}, {63855, 17565955},
1685 	{63856, 17566211}, {63857, 17182723}, {63858, 17566467}, {63859, 17566723},
1686 	{63860, 17566979}, {63861, 17567235}, {63862, 17567491}, {63863, 17567747},
1687 	{63864, 17568003}, {63865, 17568259}, {63866, 17568515}, {63867, 17568771},
1688 	{63868, 17569027}, {63869, 17569283}, {63870, 17569539}, {63871, 17569795},
1689 	{63872, 17570051}, {63873, 17151235}, {63874, 17570307}, {63875, 17570563},
1690 	{63876, 17570819}, {63877, 17571075}, {63878, 17571331}, {63879, 17571587},
1691 	{63880, 17571843}, {63881, 17572099}, {63882, 17146371}, {63883, 17572355},
1692 	{63884, 17572611}, {63885, 17572867}, {63886, 17573123}, {63887, 17573379},
1693 	{63888, 17573635}, {63889, 17573891}, {63890, 17574147}, {63891, 17574403},
1694 	{63892, 17574659}, {63893, 17574915}, {63894, 17575171}, {63895, 17575427},
1695 	{63896, 17575683}, {63897, 17575939}, {63898, 17576195}, {63899, 17576451},
1696 	{63900, 17576707}, {63901, 17576963}, {63902, 17577219}, {63903, 17577475},
1697 	{63904, 17577731}, {63905, 17565955}, {63906, 17577987}, {63907, 17578243},
1698 	{63908, 17578499}, {63909, 17578755}, {63910, 17579011}, {63911, 17579267},
1699 	{63912, 17317123}, {63913, 17579523}, {63914, 17561859}, {63915, 17579779},
1700 	{63916, 17580035}, {63917, 17580291}, {63918, 17580547}, {63919, 17580803},
1701 	{63920, 17581059}, {63921, 17581315}, {63922, 17581571}, {63923, 17581827},
1702 	{63924, 17582083}, {63925, 17582339}, {63926, 17582595}, {63927, 17582851},
1703 	{63928, 17583107}, {63929, 17583363}, {63930, 17583619}, {63931, 17583875},
1704 	{63932, 17584131}, {63933, 17584387}, {63934, 17584643}, {63935, 17543427},
1705 	{63936, 17584899}, {63937, 17585155}, {63938, 17585411}, {63939, 17585667},
1706 	{63940, 17195779}, {63941, 17585923}, {63942, 17586179}, {63943, 17586435},
1707 	{63944, 17586691}, {63945, 17586947}, {63946, 17587203}, {63947, 17587459},
1708 	{63948, 17587715}, {63949, 17587971}, {63950, 17588227}, {63951, 17588483},
1709 	{63952, 17588739}, {63953, 17254403}, {63954, 17588995}, {63955, 17589251},
1710 	{63956, 17589507}, {63957, 17589763}, {63958, 17590019}, {63959, 17590275},
1711 	{63960, 17590531}, {63961, 17590787}, {63962, 17591043}, {63963, 17562371},
1712 	{63964, 17591299}, {63965, 17591555}, {63966, 17591811}, {63967, 17592067},
1713 	{63968, 17592323}, {63969, 17592579}, {63970, 17592835}, {63971, 17593091},
1714 	{63972, 17593347}, {63973, 17593603}, {63974, 17593859}, {63975, 17594115},
1715 	{63976, 17594371}, {63977, 17184003}, {63978, 17594627}, {63979, 17594883},
1716 	{63980, 17595139}, {63981, 17595395}, {63982, 17595651}, {63983, 17595907},
1717 	{63984, 17596163}, {63985, 17596419}, {63986, 17596675}, {63987, 17596931},
1718 	{63988, 17597187}, {63989, 17597443}, {63990, 17597699}, {63991, 17171459},
1719 	{63992, 17597955}, {63993, 17598211}, {63994, 17598467}, {63995, 17598723},
1720 	{63996, 17598979}, {63997, 17599235}, {63998, 17599491}, {63999, 17599747},
1721 	{64000, 17600003}, {64001, 17600259}, {64002, 17600515}, {64003, 17600771},
1722 	{64004, 17601027}, {64005, 17601283}, {64006, 17601539}, {64007, 17601795},
1723 	{64008, 17178371}, {64009, 17602051}, {64010, 17179139}, {64011, 17602307},
1724 	{64012, 17602563}, {64013, 17602819}, {64014, 1}, {64016, 17603075},
1725 	{64017, 1}, {64018, 17603331}, {64019, 1}, {64021, 17603587},
1726 	{64022, 17603843}, {64023, 17604099}, {64024, 17604355}, {64025, 17604611},
1727 	{64026, 17604867}, {64027, 17605123}, {64028, 17605379}, {64029, 17605635},
1728 	{64030, 17173251}, {64031, 1}, {64032, 17605891}, {64033, 1},
1729 	{64034, 17606147}, {64035, 1}, {64037, 17606403}, {64038, 17606659},
1730 	{64039, 1}, {64042, 17606915}, {64043, 17607171}, {64044, 17607427},
1731 	{64045, 17607683}, {64046, 17607939}, {64047, 17608195}, {64048, 17608451},
1732 	{64049, 17608707}, {64050, 17608963}, {64051, 17609219}, {64052, 17609475},
1733 	{64053, 17609731}, {64054, 17609987}, {64055, 17610243}, {64056, 17610499},
1734 	{64057, 17610755}, {64058, 17611011}, {64059, 17611267}, {64060, 17153027},
1735 	{64061, 17611523}, {64062, 17611779}, {64063, 17612035}, {64064, 17612291},
1736 	{64065, 17612547}, {64066, 17612803}, {64067, 17613059}, {64068, 17613315},
1737 	{64069, 17613571}, {64070, 17613827}, {64071, 17614083}, {64072, 17614339},
1738 	{64073, 17614595}, {64074, 17614851}, {64075, 17615107}, {64076, 17265155},
1739 	{64077, 17615363}, {64078, 17615619}, {64079, 17615875}, {64080, 17616131},
1740 	{64081, 17268227}, {64082, 17616387}, {64083, 17616643}, {64084, 17616899},
1741 	{64085, 17617155}, {64086, 17617411}, {64087, 17575171}, {64088, 17617667},
1742 	{64089, 17617923}, {64090, 17618179}, {64091, 17618435}, {64092, 17618691},
1743 	{64093, 17618947}, {64095, 17619203}, {64096, 17619459}, {64097, 17619715},
1744 	{64098, 17619971}, {64099, 17620227}, {64100, 17620483}, {64101, 17620739},
1745 	{64102, 17620995}, {64103, 17606403}, {64104, 17621251}, {64105, 17621507},
1746 	{64106, 17621763}, {64107, 17622019}, {64108, 17622275}, {64109, 17622531},
1747 	{64110, 2}, {64112, 17622787}, {64113, 17623043}, {64114, 17623299},
1748 	{64115, 17623555}, {64116, 17623811}, {64117, 17624067}, {64118, 17624323},
1749 	{64119, 17624579}, {64120, 17609987}, {64121, 17624835}, {64122, 17625091},
1750 	{64123, 17625347}, {64124, 17603075}, {64125, 17625603}, {64126, 17625859},
1751 	{64127, 17626115}, {64128, 17626371}, {64129, 17626627}, {64130, 17626883},
1752 	{64131, 17627139}, {64132, 17627395}, {64133, 17627651}, {64134, 17627907},
1753 	{64135, 17628163}, {64136, 17628419}, {64137, 17612035}, {64138, 17628675},
1754 	{64139, 17612291}, {64140, 17628931}, {64141, 17629187}, {64142, 17629443},
1755 	{64143, 17629699}, {64144, 17629955}, {64145, 17603331}, {64146, 17548803},
1756 	{64147, 17630211}, {64148, 17630467}, {64149, 17161475}, {64150, 17566211},
1757 	{64151, 17587203}, {64152, 17630723}, {64153, 17630979}, {64154, 17614083},
1758 	{64155, 17631235}, {64156, 17614339}, {64157, 17631491}, {64158, 17631747},
1759 	{64159, 17632003}, {64160, 17603843}, {64161, 17632259}, {64162, 17632515},
1760 	{64163, 17632771}, {64164, 17633027}, {64165, 17633283}, {64166, 17604099},
1761 	{64167, 17633539}, {64168, 17633795}, {64169, 17634051}, {64170, 17634307},
1762 	{64171, 17634563}, {64172, 17634819}, {64173, 17617411}, {64174, 17635075},
1763 	{64175, 17635331}, {64176, 17575171}, {64177, 17635587}, {64178, 17618435},
1764 	{64179, 17635843}, {64180, 17636099}, {64181, 17636355}, {64182, 17636611},
1765 	{64183, 17636867}, {64184, 17619715}, {64185, 17637123}, {64186, 17606147},
1766 	{64187, 17637379}, {64188, 17619971}, {64189, 17561347}, {64190, 17637635},
1767 	{64191, 17620227}, {64192, 17637891}, {64193, 17620739}, {64194, 17638147},
1768 	{64195, 17638403}, {64196, 17638659}, {64197, 17638915}, {64198, 17639171},
1769 	{64199, 17621251}, {64200, 17605379}, {64201, 17639427}, {64202, 17621507},
1770 	{64203, 17639683}, {64204, 17621763}, {64205, 17639939}, {64206, 17196035},
1771 	{64207, 17640195}, {64208, 17640451}, {64209, 17640707}, {64210, 17640963},
1772 	{64211, 17641219}, {64212, 17641475}, {64213, 17641731}, {64214, 17641987},
1773 	{64215, 17642243}, {64216, 17642499}, {64217, 17642755}, {64218, 2},
1774 	{64256, 34420227}, {64257, 34420739}, {64258, 34421251}, {64259, 51197699},
1775 	{64260, 51198979}, {64261, 33559043}, {64263, 2}, {64275, 34422531},
1776 	{64276, 34423043}, {64277, 34423555}, {64278, 34424067}, {64279, 34424579},
1777 	{64280, 2}, {64285, 34425091}, {64286, 1}, {64287, 34425603},
1778 	{64288, 17648899}, {64289, 17044227}, {64290, 17044995}, {64291, 17649155},
1779 	{64292, 17649411}, {64293, 17649667}, {64294, 17649923}, {64295, 17650179},
1780 	{64296, 17650435}, {64297, 17037059}, {64298, 34427907}, {64299, 34428419},
1781 	{64300, 51206147}, {64301, 51206915}, {64302, 34430467}, {64303, 34430979},
1782 	{64304, 34431491}, {64305, 34432003}, {64306, 34432515}, {64307, 34433027},
1783 	{64308, 34433539}, {64309, 34434051}, {64310, 34434563}, {64311, 2},
1784 	{64312, 34435075}, {64313, 34435587}, {64314, 34436099}, {64315, 34436611},
1785 	{64316, 34437123}, {64317, 2}, {64318, 34437635}, {64319, 2},
1786 	{64320, 34438147}, {64321, 34438659}, {64322, 2}, {64323, 34439171},
1787 	{64324, 34439683}, {64325, 2}, {64326, 34440195}, {64327, 34440707},
1788 	{64328, 34441219}, {64329, 34428931}, {64330, 34441731}, {64331, 34442243},
1789 	{64332, 34442755}, {64333, 34443267}, {64334, 34443779}, {64335, 34444291},
1790 	{64336, 17667587}, {64338, 17667843}, {64342, 17668099}, {64346, 17668355},
1791 	{64350, 17668611}, {64354, 17668867}, {64358, 17669123}, {64362, 17669379},
1792 	{64366, 17669635}, {64370, 17669891}, {64374, 17670147}, {64378, 17670403},
1793 	{64382, 17670659}, {64386, 17670915}, {64388, 17671171}, {64390, 17671427},
1794 	{64392, 17671683}, {64394, 17671939}, {64396, 17672195}, {64398, 17672451},
1795 	{64402, 17672707}, {64406, 17672963}, {64410, 17673219}, {64414, 17673475},
1796 	{64416, 17673731}, {64420, 17673987}, {64422, 17674243}, {64426, 17674499},
1797 	{64430, 17674755}, {64432, 17675011}, {64434, 1}, {64451, 2},
1798 	{64467, 17675267}, {64471, 16911363}, {64473, 17675523}, {64475, 17675779},
1799 	{64477, 33688579}, {64478, 17676035}, {64480, 17676291}, {64482, 17676547},
1800 	{64484, 17676803}, {64488, 17677059}, {64490, 34454531}, {64492, 34455043},
1801 	{64494, 34455555}, {64496, 34456067}, {64498, 34456579}, {64500, 34457091},
1802 	{64502, 34457603}, {64505, 34458115}, {64508, 17681411}, {64512, 34458883},
1803 	{64513, 34459395}, {64514, 34459907}, {64515, 34458115}, {64516, 34460419},
1804 	{64517, 34460931}, {64518, 34461443}, {64519, 34461955}, {64520, 34462467},
1805 	{64521, 34462979}, {64522, 34463491}, {64523, 34464003}, {64524, 34464515},
1806 	{64525, 34465027}, {64526, 34465539}, {64527, 34466051}, {64528, 34466563},
1807 	{64529, 34467075}, {64530, 34467587}, {64531, 34468099}, {64532, 34468611},
1808 	{64533, 34469123}, {64534, 34469635}, {64535, 34469379}, {64536, 34470147},
1809 	{64537, 34470659}, {64538, 34471171}, {64539, 34471683}, {64540, 34472195},
1810 	{64541, 34472707}, {64542, 34473219}, {64543, 34473731}, {64544, 34474243},
1811 	{64545, 34474755}, {64546, 34475267}, {64547, 34475779}, {64548, 34476291},
1812 	{64549, 34476803}, {64550, 34477315}, {64551, 34477827}, {64552, 34478339},
1813 	{64553, 34478851}, {64554, 34479363}, {64555, 34479875}, {64556, 34480387},
1814 	{64557, 34480899}, {64558, 34481411}, {64559, 34481923}, {64560, 34482435},
1815 	{64561, 34482947}, {64562, 34483459}, {64563, 34483971}, {64564, 34484483},
1816 	{64565, 34484995}, {64566, 34485507}, {64567, 34486019}, {64568, 34486531},
1817 	{64569, 34487043}, {64570, 34487555}, {64571, 34488067}, {64572, 34488579},
1818 	{64573, 34489091}, {64574, 34489603}, {64575, 34490115}, {64576, 34490627},
1819 	{64577, 34491139}, {64578, 34491651}, {64579, 34492163}, {64580, 34492675},
1820 	{64581, 34493187}, {64582, 34469891}, {64583, 34470403}, {64584, 34493699},
1821 	{64585, 34494211}, {64586, 34494723}, {64587, 34495235}, {64588, 34495747},
1822 	{64589, 34496259}, {64590, 34496771}, {64591, 34497283}, {64592, 34497795},
1823 	{64593, 34498307}, {64594, 34498819}, {64595, 34499331}, {64596, 34499843},
1824 	{64597, 34468867}, {64598, 34500355}, {64599, 34500867}, {64600, 34492931},
1825 	{64601, 34501379}, {64602, 34500099}, {64603, 34501891}, {64604, 34502403},
1826 	{64605, 34502915}, {64606, 51280643}, {64607, 51281411}, {64608, 51282179},
1827 	{64609, 51282947}, {64610, 51283715}, {64611, 51284483}, {64612, 34508035},
1828 	{64613, 34508547}, {64614, 34459907}, {64615, 34509059}, {64616, 34458115},
1829 	{64617, 34460419}, {64618, 34509571}, {64619, 34510083}, {64620, 34462467},
1830 	{64621, 34510595}, {64622, 34462979}, {64623, 34463491}, {64624, 34511107},
1831 	{64625, 34511619}, {64626, 34465539}, {64627, 34512131}, {64628, 34466051},
1832 	{64629, 34466563}, {64630, 34512643}, {64631, 34513155}, {64632, 34467587},
1833 	{64633, 34513667}, {64634, 34468099}, {64635, 34468611}, {64636, 34482947},
1834 	{64637, 34483459}, {64638, 34484995}, {64639, 34485507}, {64640, 34486019},
1835 	{64641, 34488067}, {64642, 34488579}, {64643, 34489091}, {64644, 34489603},
1836 	{64645, 34491651}, {64646, 34492163}, {64647, 34492675}, {64648, 34514179},
1837 	{64649, 34493699}, {64650, 34514691}, {64651, 34515203}, {64652, 34496771},
1838 	{64653, 34515715}, {64654, 34497283}, {64655, 34497795}, {64656, 34502915},
1839 	{64657, 34516227}, {64658, 34516739}, {64659, 34492931}, {64660, 34494979},
1840 	{64661, 34501379}, {64662, 34500099}, {64663, 34458883}, {64664, 34459395},
1841 	{64665, 34517251}, {64666, 34459907}, {64667, 34517763}, {64668, 34460931},
1842 	{64669, 34461443}, {64670, 34461955}, {64671, 34462467}, {64672, 34518275},
1843 	{64673, 34464003}, {64674, 34464515}, {64675, 34465027}, {64676, 34465539},
1844 	{64677, 34518787}, {64678, 34467587}, {64679, 34469123}, {64680, 34469635},
1845 	{64681, 34469379}, {64682, 34470147}, {64683, 34470659}, {64684, 34471683},
1846 	{64685, 34472195}, {64686, 34472707}, {64687, 34473219}, {64688, 34473731},
1847 	{64689, 34474243}, {64690, 34519299}, {64691, 34474755}, {64692, 34475267},
1848 	{64693, 34475779}, {64694, 34476291}, {64695, 34476803}, {64696, 34477315},
1849 	{64697, 34478339}, {64698, 34478851}, {64699, 34479363}, {64700, 34479875},
1850 	{64701, 34480387}, {64702, 34480899}, {64703, 34481411}, {64704, 34481923},
1851 	{64705, 34482435}, {64706, 34483971}, {64707, 34484483}, {64708, 34486531},
1852 	{64709, 34487043}, {64710, 34487555}, {64711, 34488067}, {64712, 34488579},
1853 	{64713, 34490115}, {64714, 34490627}, {64715, 34491139}, {64716, 34491651},
1854 	{64717, 34519811}, {64718, 34493187}, {64719, 34469891}, {64720, 34470403},
1855 	{64721, 34493699}, {64722, 34495235}, {64723, 34495747}, {64724, 34496259},
1856 	{64725, 34496771}, {64726, 34520323}, {64727, 34498307}, {64728, 34498819},
1857 	{64729, 34520835}, {64730, 34468867}, {64731, 34500355}, {64732, 34500867},
1858 	{64733, 34492931}, {64734, 34498051}, {64735, 34459907}, {64736, 34517763},
1859 	{64737, 34462467}, {64738, 34518275}, {64739, 34465539}, {64740, 34518787},
1860 	{64741, 34467587}, {64742, 34521347}, {64743, 34473731}, {64744, 34521859},
1861 	{64745, 34522371}, {64746, 34522883}, {64747, 34488067}, {64748, 34488579},
1862 	{64749, 34491651}, {64750, 34496771}, {64751, 34520323}, {64752, 34492931},
1863 	{64753, 34498051}, {64754, 51300611}, {64755, 51301379}, {64756, 51302147},
1864 	{64757, 34525699}, {64758, 34526211}, {64759, 34526723}, {64760, 34527235},
1865 	{64761, 34527747}, {64762, 34528259}, {64763, 34528771}, {64764, 34529283},
1866 	{64765, 34529795}, {64766, 34530307}, {64767, 34530819}, {64768, 34500611},
1867 	{64769, 34531331}, {64770, 34531843}, {64771, 34532355}, {64772, 34501123},
1868 	{64773, 34532867}, {64774, 34533379}, {64775, 34533891}, {64776, 34534403},
1869 	{64777, 34534915}, {64778, 34535427}, {64779, 34535939}, {64780, 34522371},
1870 	{64781, 34536451}, {64782, 34536963}, {64783, 34537475}, {64784, 34537987},
1871 	{64785, 34525699}, {64786, 34526211}, {64787, 34526723}, {64788, 34527235},
1872 	{64789, 34527747}, {64790, 34528259}, {64791, 34528771}, {64792, 34529283},
1873 	{64793, 34529795}, {64794, 34530307}, {64795, 34530819}, {64796, 34500611},
1874 	{64797, 34531331}, {64798, 34531843}, {64799, 34532355}, {64800, 34501123},
1875 	{64801, 34532867}, {64802, 34533379}, {64803, 34533891}, {64804, 34534403},
1876 	{64805, 34534915}, {64806, 34535427}, {64807, 34535939}, {64808, 34522371},
1877 	{64809, 34536451}, {64810, 34536963}, {64811, 34537475}, {64812, 34537987},
1878 	{64813, 34534915}, {64814, 34535427}, {64815, 34535939}, {64816, 34522371},
1879 	{64817, 34521859}, {64818, 34522883}, {64819, 34477827}, {64820, 34472195},
1880 	{64821, 34472707}, {64822, 34473219}, {64823, 34534915}, {64824, 34535427},
1881 	{64825, 34535939}, {64826, 34477827}, {64827, 34478339}, {64828, 34538499},
1882 	{64830, 1}, {64848, 51316227}, {64849, 51316995}, {64851, 51317763},
1883 	{64852, 51318531}, {64853, 51319299}, {64854, 51320067}, {64855, 51320835},
1884 	{64856, 51246851}, {64858, 51321603}, {64859, 51322371}, {64860, 51323139},
1885 	{64861, 51323907}, {64862, 51324675}, {64863, 51325443}, {64865, 51326211},
1886 	{64866, 51326979}, {64868, 51327747}, {64870, 51328515}, {64871, 51329283},
1887 	{64873, 51330051}, {64874, 51330819}, {64876, 51331587}, {64878, 51332355},
1888 	{64879, 51333123}, {64881, 51333891}, {64883, 51334659}, {64884, 51335427},
1889 	{64885, 51336195}, {64886, 51336963}, {64888, 51337731}, {64889, 51338499},
1890 	{64890, 51339267}, {64891, 51340035}, {64892, 51340803}, {64894, 51341571},
1891 	{64895, 51342339}, {64896, 51343107}, {64897, 51343875}, {64898, 51344643},
1892 	{64899, 51345411}, {64901, 51346179}, {64903, 51346947}, {64905, 51347715},
1893 	{64906, 51247107}, {64907, 51348483}, {64908, 51349251}, {64909, 51270403},
1894 	{64910, 51247619}, {64911, 51350019}, {64912, 2}, {64914, 51350787},
1895 	{64915, 51351555}, {64916, 51352323}, {64917, 51353091}, {64918, 51353859},
1896 	{64919, 51354627}, {64921, 51355395}, {64922, 51356163}, {64923, 51356931},
1897 	{64924, 51357699}, {64926, 51358467}, {64927, 51359235}, {64928, 51360003},
1898 	{64929, 51360771}, {64930, 51361539}, {64931, 51362307}, {64932, 51363075},
1899 	{64933, 51363843}, {64934, 51364611}, {64935, 51365379}, {64936, 51366147},
1900 	{64937, 51366915}, {64938, 51367683}, {64939, 51368451}, {64940, 51369219},
1901 	{64941, 51369987}, {64942, 51277571}, {64943, 51370755}, {64944, 51371523},
1902 	{64945, 51372291}, {64946, 51373059}, {64947, 51373827}, {64948, 51341571},
1903 	{64949, 51343107}, {64950, 51374595}, {64951, 51375363}, {64952, 51376131},
1904 	{64953, 51376899}, {64954, 51377667}, {64955, 51378435}, {64956, 51377667},
1905 	{64957, 51376131}, {64958, 51379203}, {64959, 51379971}, {64960, 51380739},
1906 	{64961, 51381507}, {64962, 51382275}, {64963, 51378435}, {64964, 51336195},
1907 	{64965, 51328515}, {64966, 51383043}, {64967, 51383811}, {64968, 2},
1908 	{64975, 1}, {64976, 2}, {65008, 51384579}, {65009, 51385347},
1909 	{65010, 68163331}, {65011, 68164355}, {65012, 68165379}, {65013, 68166403},
1910 	{65014, 68167427}, {65015, 68168451}, {65016, 68169475}, {65017, 51393283},
1911 	{65018, 303052291}, {65019, 135284739}, {65020, 68177923}, {65021, 1},
1912 	{65024, 0}, {65040, 17847299}, {65041, 17847555}, {65042, 2},
1913 	{65043, 17110531}, {65044, 16848643}, {65045, 17032963}, {65046, 17033987},
1914 	{65047, 17847811}, {65048, 17848067}, {65049, 2}, {65056, 1},
1915 	{65072, 2}, {65073, 17848323}, {65074, 17848579}, {65075, 17848835},
1916 	{65077, 17037827}, {65078, 17038083}, {65079, 17849091}, {65080, 17849347},
1917 	{65081, 17849603}, {65082, 17849859}, {65083, 17850115}, {65084, 17850371},
1918 	{65085, 17850627}, {65086, 17850883}, {65087, 17067267}, {65088, 17067523},
1919 	{65089, 17851139}, {65090, 17851395}, {65091, 17851651}, {65092, 17851907},
1920 	{65093, 1}, {65095, 17852163}, {65096, 17852419}, {65097, 33810691},
1921 	{65101, 17848835}, {65104, 17847299}, {65105, 17847555}, {65106, 2},
1922 	{65108, 16848643}, {65109, 17110531}, {65110, 17033987}, {65111, 17032963},
1923 	{65112, 17848323}, {65113, 17037827}, {65114, 17038083}, {65115, 17849091},
1924 	{65116, 17849347}, {65117, 17849603}, {65118, 17849859}, {65119, 17852675},
1925 	{65120, 17852931}, {65121, 17853187}, {65122, 17037059}, {65123, 17853443},
1926 	{65124, 17853699}, {65125, 17853955}, {65126, 17037571}, {65127, 2},
1927 	{65128, 17854211}, {65129, 17854467}, {65130, 17854723}, {65131, 17854979},
1928 	{65132, 2}, {65136, 34632451}, {65137, 34632963}, {65138, 34503427},
1929 	{65139, 1}, {65140, 34504195}, {65141, 2}, {65142, 34504963},
1930 	{65143, 34523395}, {65144, 34505731}, {65145, 34524163}, {65146, 34506499},
1931 	{65147, 34524931}, {65148, 34507267}, {65149, 34633475}, {65150, 34633987},
1932 	{65151, 34634499}, {65152, 17857795}, {65153, 17858051}, {65155, 17858307},
1933 	{65157, 17858563}, {65159, 17858819}, {65161, 17677315}, {65165, 16910339},
1934 	{65167, 17683715}, {65171, 17859075}, {65173, 17686787}, {65177, 17689859},
1935 	{65181, 17681923}, {65185, 17682435}, {65189, 17684995}, {65193, 17834499},
1936 	{65195, 17724675}, {65197, 17725187}, {65199, 17731587}, {65201, 17694979},
1937 	{65205, 17745155}, {65209, 17697027}, {65213, 17698051}, {65217, 17700099},
1938 	{65221, 17701123}, {65225, 17701635}, {65229, 17702659}, {65233, 17703683},
1939 	{65237, 17706755}, {65241, 17708803}, {65245, 17711107}, {65249, 17682947},
1940 	{65253, 17718019}, {65257, 17721091}, {65261, 16910851}, {65263, 17677059},
1941 	{65265, 16911875}, {65269, 34636547}, {65271, 34637059}, {65273, 34637571},
1942 	{65275, 34622467}, {65277, 2}, {65279, 0}, {65280, 2},
1943 	{65281, 17032963}, {65282, 17860867}, {65283, 17852675}, {65284, 17854467},
1944 	{65285, 17854723}, {65286, 17852931}, {65287, 17861123}, {65288, 17037827},
1945 	{65289, 17038083}, {65290, 17853187}, {65291, 17037059}, {65292, 17847299},
1946 	{65293, 17853443}, {65294, 17196547}, {65295, 17038595}, {65296, 17035523},
1947 	{65297, 16786947}, {65298, 16785155}, {65299, 16785411}, {65300, 16787715},
1948 	{65301, 17035779}, {65302, 17036035}, {65303, 17036291}, {65304, 17036547},
1949 	{65305, 17036803}, {65306, 17110531}, {65307, 16848643}, {65308, 17853699},
1950 	{65309, 17037571}, {65310, 17853955}, {65311, 17033987}, {65312, 17854979},
1951 	{65313, 16777219}, {65314, 16777475}, {65315, 16777731}, {65316, 16777987},
1952 	{65317, 16778243}, {65318, 16778499}, {65319, 16778755}, {65320, 16779011},
1953 	{65321, 16779267}, {65322, 16779523}, {65323, 16779779}, {65324, 16780035},
1954 	{65325, 16780291}, {65326, 16780547}, {65327, 16780803}, {65328, 16781059},
1955 	{65329, 16781315}, {65330, 16781571}, {65331, 16781827}, {65332, 16782083},
1956 	{65333, 16782339}, {65334, 16782595}, {65335, 16782851}, {65336, 16783107},
1957 	{65337, 16783363}, {65338, 16783619}, {65339, 17852163}, {65340, 17854211},
1958 	{65341, 17852419}, {65342, 17861379}, {65343, 17848835}, {65344, 17027075},
1959 	{65345, 16777219}, {65346, 16777475}, {65347, 16777731}, {65348, 16777987},
1960 	{65349, 16778243}, {65350, 16778499}, {65351, 16778755}, {65352, 16779011},
1961 	{65353, 16779267}, {65354, 16779523}, {65355, 16779779}, {65356, 16780035},
1962 	{65357, 16780291}, {65358, 16780547}, {65359, 16780803}, {65360, 16781059},
1963 	{65361, 16781315}, {65362, 16781571}, {65363, 16781827}, {65364, 16782083},
1964 	{65365, 16782339}, {65366, 16782595}, {65367, 16782851}, {65368, 16783107},
1965 	{65369, 16783363}, {65370, 16783619}, {65371, 17849091}, {65372, 17861635},
1966 	{65373, 17849347}, {65374, 17861891}, {65375, 17862147}, {65376, 17862403},
1967 	{65377, 17196547}, {65378, 17851139}, {65379, 17851395}, {65380, 17847555},
1968 	{65381, 17862659}, {65382, 17316867}, {65383, 17319427}, {65384, 17362435},
1969 	{65385, 17862915}, {65386, 17363971}, {65387, 17323523}, {65388, 17863171},
1970 	{65389, 17333763}, {65390, 17379587}, {65391, 17329155}, {65392, 17318147},
1971 	{65393, 17305603}, {65394, 17305859}, {65395, 17306115}, {65396, 17306371},
1972 	{65397, 17306627}, {65398, 17306883}, {65399, 17307139}, {65400, 17307395},
1973 	{65401, 17307651}, {65402, 17199107}, {65403, 17307907}, {65404, 17308163},
1974 	{65405, 17308419}, {65406, 17308675}, {65407, 17308931}, {65408, 17309187},
1975 	{65409, 17309443}, {65410, 17309699}, {65411, 17309955}, {65412, 17199363},
1976 	{65413, 17310211}, {65414, 17310467}, {65415, 17310723}, {65416, 17310979},
1977 	{65417, 17311235}, {65418, 17311491}, {65419, 17311747}, {65420, 17312003},
1978 	{65421, 17312259}, {65422, 17312515}, {65423, 17312771}, {65424, 17313027},
1979 	{65425, 17313283}, {65426, 17313539}, {65427, 17313795}, {65428, 17314051},
1980 	{65429, 17314307}, {65430, 17314563}, {65431, 17314819}, {65432, 17315075},
1981 	{65433, 17315331}, {65434, 17315587}, {65435, 17315843}, {65436, 17316099},
1982 	{65437, 17319939}, {65438, 17197827}, {65439, 17198339}, {65440, 2},
1983 	{65441, 17199619}, {65442, 17199875}, {65443, 17200131}, {65444, 17200387},
1984 	{65445, 17200643}, {65446, 17200899}, {65447, 17201155}, {65448, 17201411},
1985 	{65449, 17201667}, {65450, 17201923}, {65451, 17202179}, {65452, 17202435},
1986 	{65453, 17202691}, {65454, 17202947}, {65455, 17203203}, {65456, 17203459},
1987 	{65457, 17203715}, {65458, 17203971}, {65459, 17204227}, {65460, 17204483},
1988 	{65461, 17204739}, {65462, 17204995}, {65463, 17205251}, {65464, 17205507},
1989 	{65465, 17205763}, {65466, 17206019}, {65467, 17206275}, {65468, 17206531},
1990 	{65469, 17206787}, {65470, 17207043}, {65471, 2}, {65474, 17207299},
1991 	{65475, 17207555}, {65476, 17207811}, {65477, 17208067}, {65478, 17208323},
1992 	{65479, 17208579}, {65480, 2}, {65482, 17208835}, {65483, 17209091},
1993 	{65484, 17209347}, {65485, 17209603}, {65486, 17209859}, {65487, 17210115},
1994 	{65488, 2}, {65490, 17210371}, {65491, 17210627}, {65492, 17210883},
1995 	{65493, 17211139}, {65494, 17211395}, {65495, 17211651}, {65496, 2},
1996 	{65498, 17211907}, {65499, 17212163}, {65500, 17212419}, {65501, 2},
1997 	{65504, 17863427}, {65505, 17863683}, {65506, 17863939}, {65507, 33561859},
1998 	{65508, 17864195}, {65509, 17864451}, {65510, 17864707}, {65511, 2},
1999 	{65512, 17864963}, {65513, 17865219}, {65514, 17865475}, {65515, 17865731},
2000 	{65516, 17865987}, {65517, 17866243}, {65518, 17866499}, {65519, 2},
2001 	{65536, 1}, {65548, 2}, {65549, 1}, {65575, 2},
2002 	{65576, 1}, {65595, 2}, {65596, 1}, {65598, 2},
2003 	{65599, 1}, {65614, 2}, {65616, 1}, {65630, 2},
2004 	{65664, 1}, {65787, 2}, {65792, 1}, {65795, 2},
2005 	{65799, 1}, {65844, 2}, {65847, 1}, {65935, 2},
2006 	{65936, 1}, {65949, 2}, {65952, 1}, {65953, 2},
2007 	{66000, 1}, {66046, 2}, {66176, 1}, {66205, 2},
2008 	{66208, 1}, {66257, 2}, {66272, 1}, {66300, 2},
2009 	{66304, 1}, {66340, 2}, {66349, 1}, {66379, 2},
2010 	{66384, 1}, {66427, 2}, {66432, 1}, {66462, 2},
2011 	{66463, 1}, {66500, 2}, {66504, 1}, {66518, 2},
2012 	{66560, 17866755}, {66561, 17867011}, {66562, 17867267}, {66563, 17867523},
2013 	{66564, 17867779}, {66565, 17868035}, {66566, 17868291}, {66567, 17868547},
2014 	{66568, 17868803}, {66569, 17869059}, {66570, 17869315}, {66571, 17869571},
2015 	{66572, 17869827}, {66573, 17870083}, {66574, 17870339}, {66575, 17870595},
2016 	{66576, 17870851}, {66577, 17871107}, {66578, 17871363}, {66579, 17871619},
2017 	{66580, 17871875}, {66581, 17872131}, {66582, 17872387}, {66583, 17872643},
2018 	{66584, 17872899}, {66585, 17873155}, {66586, 17873411}, {66587, 17873667},
2019 	{66588, 17873923}, {66589, 17874179}, {66590, 17874435}, {66591, 17874691},
2020 	{66592, 17874947}, {66593, 17875203}, {66594, 17875459}, {66595, 17875715},
2021 	{66596, 17875971}, {66597, 17876227}, {66598, 17876483}, {66599, 17876739},
2022 	{66600, 1}, {66718, 2}, {66720, 1}, {66730, 2},
2023 	{66736, 17876995}, {66737, 17877251}, {66738, 17877507}, {66739, 17877763},
2024 	{66740, 17878019}, {66741, 17878275}, {66742, 17878531}, {66743, 17878787},
2025 	{66744, 17879043}, {66745, 17879299}, {66746, 17879555}, {66747, 17879811},
2026 	{66748, 17880067}, {66749, 17880323}, {66750, 17880579}, {66751, 17880835},
2027 	{66752, 17881091}, {66753, 17881347}, {66754, 17881603}, {66755, 17881859},
2028 	{66756, 17882115}, {66757, 17882371}, {66758, 17882627}, {66759, 17882883},
2029 	{66760, 17883139}, {66761, 17883395}, {66762, 17883651}, {66763, 17883907},
2030 	{66764, 17884163}, {66765, 17884419}, {66766, 17884675}, {66767, 17884931},
2031 	{66768, 17885187}, {66769, 17885443}, {66770, 17885699}, {66771, 17885955},
2032 	{66772, 2}, {66776, 1}, {66812, 2}, {66816, 1},
2033 	{66856, 2}, {66864, 1}, {66916, 2}, {66927, 1},
2034 	{66928, 17886211}, {66929, 17886467}, {66930, 17886723}, {66931, 17886979},
2035 	{66932, 17887235}, {66933, 17887491}, {66934, 17887747}, {66935, 17888003},
2036 	{66936, 17888259}, {66937, 17888515}, {66938, 17888771}, {66939, 2},
2037 	{66940, 17889027}, {66941, 17889283}, {66942, 17889539}, {66943, 17889795},
2038 	{66944, 17890051}, {66945, 17890307}, {66946, 17890563}, {66947, 17890819},
2039 	{66948, 17891075}, {66949, 17891331}, {66950, 17891587}, {66951, 17891843},
2040 	{66952, 17892099}, {66953, 17892355}, {66954, 17892611}, {66955, 2},
2041 	{66956, 17892867}, {66957, 17893123}, {66958, 17893379}, {66959, 17893635},
2042 	{66960, 17893891}, {66961, 17894147}, {66962, 17894403}, {66963, 2},
2043 	{66964, 17894659}, {66965, 17894915}, {66966, 2}, {66967, 1},
2044 	{66978, 2}, {66979, 1}, {66994, 2}, {66995, 1},
2045 	{67002, 2}, {67003, 1}, {67005, 2}, {67072, 1},
2046 	{67383, 2}, {67392, 1}, {67414, 2}, {67424, 1},
2047 	{67432, 2}, {67456, 1}, {67457, 17895171}, {67458, 17895427},
2048 	{67459, 16791043}, {67460, 17895683}, {67461, 16814083}, {67462, 2},
2049 	{67463, 17895939}, {67464, 17896195}, {67465, 17896451}, {67466, 17896707},
2050 	{67467, 16815363}, {67468, 16815619}, {67469, 17896963}, {67470, 17897219},
2051 	{67471, 17897475}, {67472, 17897731}, {67473, 17897987}, {67474, 17898243},
2052 	{67475, 16817155}, {67476, 17898499}, {67477, 16802051}, {67478, 17898755},
2053 	{67479, 17899011}, {67480, 17899267}, {67481, 17899523}, {67482, 17899779},
2054 	{67483, 17512963}, {67484, 17900035}, {67485, 17900291}, {67486, 17900547},
2055 	{67487, 17900803}, {67488, 17901059}, {67489, 17901315}, {67490, 16795395},
2056 	{67491, 17901571}, {67492, 17901827}, {67493, 16781315}, {67494, 17902083},
2057 	{67495, 17902339}, {67496, 17125379}, {67497, 17902595}, {67498, 16819971},
2058 	{67499, 17902851}, {67500, 17903107}, {67501, 17903363}, {67502, 17903619},
2059 	{67503, 16820995}, {67504, 17903875}, {67505, 2}, {67506, 17904131},
2060 	{67507, 17904387}, {67508, 17904643}, {67509, 17904899}, {67510, 17905155},
2061 	{67511, 17905411}, {67512, 17905667}, {67513, 17905923}, {67514, 17906179},
2062 	{67515, 2}, {67584, 1}, {67590, 2}, {67592, 1},
2063 	{67593, 2}, {67594, 1}, {67638, 2}, {67639, 1},
2064 	{67641, 2}, {67644, 1}, {67645, 2}, {67647, 1},
2065 	{67670, 2}, {67671, 1}, {67743, 2}, {67751, 1},
2066 	{67760, 2}, {67808, 1}, {67827, 2}, {67828, 1},
2067 	{67830, 2}, {67835, 1}, {67868, 2}, {67871, 1},
2068 	{67898, 2}, {67903, 1}, {67904, 2}, {67968, 1},
2069 	{68024, 2}, {68028, 1}, {68048, 2}, {68050, 1},
2070 	{68100, 2}, {68101, 1}, {68103, 2}, {68108, 1},
2071 	{68116, 2}, {68117, 1}, {68120, 2}, {68121, 1},
2072 	{68150, 2}, {68152, 1}, {68155, 2}, {68159, 1},
2073 	{68169, 2}, {68176, 1}, {68185, 2}, {68192, 1},
2074 	{68256, 2}, {68288, 1}, {68327, 2}, {68331, 1},
2075 	{68343, 2}, {68352, 1}, {68406, 2}, {68409, 1},
2076 	{68438, 2}, {68440, 1}, {68467, 2}, {68472, 1},
2077 	{68498, 2}, {68505, 1}, {68509, 2}, {68521, 1},
2078 	{68528, 2}, {68608, 1}, {68681, 2}, {68736, 17906435},
2079 	{68737, 17906691}, {68738, 17906947}, {68739, 17907203}, {68740, 17907459},
2080 	{68741, 17907715}, {68742, 17907971}, {68743, 17908227}, {68744, 17908483},
2081 	{68745, 17908739}, {68746, 17908995}, {68747, 17909251}, {68748, 17909507},
2082 	{68749, 17909763}, {68750, 17910019}, {68751, 17910275}, {68752, 17910531},
2083 	{68753, 17910787}, {68754, 17911043}, {68755, 17911299}, {68756, 17911555},
2084 	{68757, 17911811}, {68758, 17912067}, {68759, 17912323}, {68760, 17912579},
2085 	{68761, 17912835}, {68762, 17913091}, {68763, 17913347}, {68764, 17913603},
2086 	{68765, 17913859}, {68766, 17914115}, {68767, 17914371}, {68768, 17914627},
2087 	{68769, 17914883}, {68770, 17915139}, {68771, 17915395}, {68772, 17915651},
2088 	{68773, 17915907}, {68774, 17916163}, {68775, 17916419}, {68776, 17916675},
2089 	{68777, 17916931}, {68778, 17917187}, {68779, 17917443}, {68780, 17917699},
2090 	{68781, 17917955}, {68782, 17918211}, {68783, 17918467}, {68784, 17918723},
2091 	{68785, 17918979}, {68786, 17919235}, {68787, 2}, {68800, 1},
2092 	{68851, 2}, {68858, 1}, {68904, 2}, {68912, 1},
2093 	{68922, 2}, {69216, 1}, {69247, 2}, {69248, 1},
2094 	{69290, 2}, {69291, 1}, {69294, 2}, {69296, 1},
2095 	{69298, 2}, {69373, 1}, {69416, 2}, {69424, 1},
2096 	{69466, 2}, {69488, 1}, {69514, 2}, {69552, 1},
2097 	{69580, 2}, {69600, 1}, {69623, 2}, {69632, 1},
2098 	{69710, 2}, {69714, 1}, {69750, 2}, {69759, 1},
2099 	{69821, 2}, {69822, 1}, {69827, 2}, {69840, 1},
2100 	{69865, 2}, {69872, 1}, {69882, 2}, {69888, 1},
2101 	{69941, 2}, {69942, 1}, {69960, 2}, {69968, 1},
2102 	{70007, 2}, {70016, 1}, {70112, 2}, {70113, 1},
2103 	{70133, 2}, {70144, 1}, {70162, 2}, {70163, 1},
2104 	{70210, 2}, {70272, 1}, {70279, 2}, {70280, 1},
2105 	{70281, 2}, {70282, 1}, {70286, 2}, {70287, 1},
2106 	{70302, 2}, {70303, 1}, {70314, 2}, {70320, 1},
2107 	{70379, 2}, {70384, 1}, {70394, 2}, {70400, 1},
2108 	{70404, 2}, {70405, 1}, {70413, 2}, {70415, 1},
2109 	{70417, 2}, {70419, 1}, {70441, 2}, {70442, 1},
2110 	{70449, 2}, {70450, 1}, {70452, 2}, {70453, 1},
2111 	{70458, 2}, {70459, 1}, {70469, 2}, {70471, 1},
2112 	{70473, 2}, {70475, 1}, {70478, 2}, {70480, 1},
2113 	{70481, 2}, {70487, 1}, {70488, 2}, {70493, 1},
2114 	{70500, 2}, {70502, 1}, {70509, 2}, {70512, 1},
2115 	{70517, 2}, {70656, 1}, {70748, 2}, {70749, 1},
2116 	{70754, 2}, {70784, 1}, {70856, 2}, {70864, 1},
2117 	{70874, 2}, {71040, 1}, {71094, 2}, {71096, 1},
2118 	{71134, 2}, {71168, 1}, {71237, 2}, {71248, 1},
2119 	{71258, 2}, {71264, 1}, {71277, 2}, {71296, 1},
2120 	{71354, 2}, {71360, 1}, {71370, 2}, {71424, 1},
2121 	{71451, 2}, {71453, 1}, {71468, 2}, {71472, 1},
2122 	{71495, 2}, {71680, 1}, {71740, 2}, {71840, 17919491},
2123 	{71841, 17919747}, {71842, 17920003}, {71843, 17920259}, {71844, 17920515},
2124 	{71845, 17920771}, {71846, 17921027}, {71847, 17921283}, {71848, 17921539},
2125 	{71849, 17921795}, {71850, 17922051}, {71851, 17922307}, {71852, 17922563},
2126 	{71853, 17922819}, {71854, 17923075}, {71855, 17923331}, {71856, 17923587},
2127 	{71857, 17923843}, {71858, 17924099}, {71859, 17924355}, {71860, 17924611},
2128 	{71861, 17924867}, {71862, 17925123}, {71863, 17925379}, {71864, 17925635},
2129 	{71865, 17925891}, {71866, 17926147}, {71867, 17926403}, {71868, 17926659},
2130 	{71869, 17926915}, {71870, 17927171}, {71871, 17927427}, {71872, 1},
2131 	{71923, 2}, {71935, 1}, {71943, 2}, {71945, 1},
2132 	{71946, 2}, {71948, 1}, {71956, 2}, {71957, 1},
2133 	{71959, 2}, {71960, 1}, {71990, 2}, {71991, 1},
2134 	{71993, 2}, {71995, 1}, {72007, 2}, {72016, 1},
2135 	{72026, 2}, {72096, 1}, {72104, 2}, {72106, 1},
2136 	{72152, 2}, {72154, 1}, {72165, 2}, {72192, 1},
2137 	{72264, 2}, {72272, 1}, {72355, 2}, {72368, 1},
2138 	{72441, 2}, {72448, 1}, {72458, 2}, {72704, 1},
2139 	{72713, 2}, {72714, 1}, {72759, 2}, {72760, 1},
2140 	{72774, 2}, {72784, 1}, {72813, 2}, {72816, 1},
2141 	{72848, 2}, {72850, 1}, {72872, 2}, {72873, 1},
2142 	{72887, 2}, {72960, 1}, {72967, 2}, {72968, 1},
2143 	{72970, 2}, {72971, 1}, {73015, 2}, {73018, 1},
2144 	{73019, 2}, {73020, 1}, {73022, 2}, {73023, 1},
2145 	{73032, 2}, {73040, 1}, {73050, 2}, {73056, 1},
2146 	{73062, 2}, {73063, 1}, {73065, 2}, {73066, 1},
2147 	{73103, 2}, {73104, 1}, {73106, 2}, {73107, 1},
2148 	{73113, 2}, {73120, 1}, {73130, 2}, {73440, 1},
2149 	{73465, 2}, {73472, 1}, {73489, 2}, {73490, 1},
2150 	{73531, 2}, {73534, 1}, {73562, 2}, {73648, 1},
2151 	{73649, 2}, {73664, 1}, {73714, 2}, {73727, 1},
2152 	{74650, 2}, {74752, 1}, {74863, 2}, {74864, 1},
2153 	{74869, 2}, {74880, 1}, {75076, 2}, {77712, 1},
2154 	{77811, 2}, {77824, 1}, {78896, 2}, {78912, 1},
2155 	{78934, 2}, {82944, 1}, {83527, 2}, {92160, 1},
2156 	{92729, 2}, {92736, 1}, {92767, 2}, {92768, 1},
2157 	{92778, 2}, {92782, 1}, {92863, 2}, {92864, 1},
2158 	{92874, 2}, {92880, 1}, {92910, 2}, {92912, 1},
2159 	{92918, 2}, {92928, 1}, {92998, 2}, {93008, 1},
2160 	{93018, 2}, {93019, 1}, {93026, 2}, {93027, 1},
2161 	{93048, 2}, {93053, 1}, {93072, 2}, {93760, 17927683},
2162 	{93761, 17927939}, {93762, 17928195}, {93763, 17928451}, {93764, 17928707},
2163 	{93765, 17928963}, {93766, 17929219}, {93767, 17929475}, {93768, 17929731},
2164 	{93769, 17929987}, {93770, 17930243}, {93771, 17930499}, {93772, 17930755},
2165 	{93773, 17931011}, {93774, 17931267}, {93775, 17931523}, {93776, 17931779},
2166 	{93777, 17932035}, {93778, 17932291}, {93779, 17932547}, {93780, 17932803},
2167 	{93781, 17933059}, {93782, 17933315}, {93783, 17933571}, {93784, 17933827},
2168 	{93785, 17934083}, {93786, 17934339}, {93787, 17934595}, {93788, 17934851},
2169 	{93789, 17935107}, {93790, 17935363}, {93791, 17935619}, {93792, 1},
2170 	{93851, 2}, {93952, 1}, {94027, 2}, {94031, 1},
2171 	{94088, 2}, {94095, 1}, {94112, 2}, {94176, 1},
2172 	{94181, 2}, {94192, 1}, {94194, 2}, {94208, 1},
2173 	{100344, 2}, {100352, 1}, {101590, 2}, {101632, 1},
2174 	{101641, 2}, {110576, 1}, {110580, 2}, {110581, 1},
2175 	{110588, 2}, {110589, 1}, {110591, 2}, {110592, 1},
2176 	{110883, 2}, {110898, 1}, {110899, 2}, {110928, 1},
2177 	{110931, 2}, {110933, 1}, {110934, 2}, {110948, 1},
2178 	{110952, 2}, {110960, 1}, {111356, 2}, {113664, 1},
2179 	{113771, 2}, {113776, 1}, {113789, 2}, {113792, 1},
2180 	{113801, 2}, {113808, 1}, {113818, 2}, {113820, 1},
2181 	{113824, 0}, {113828, 2}, {118528, 1}, {118574, 2},
2182 	{118576, 1}, {118599, 2}, {118608, 1}, {118724, 2},
2183 	{118784, 1}, {119030, 2}, {119040, 1}, {119079, 2},
2184 	{119081, 1}, {119134, 34713091}, {119135, 34713603}, {119136, 51491331},
2185 	{119137, 51492099}, {119138, 51492867}, {119139, 51493635}, {119140, 51494403},
2186 	{119141, 1}, {119155, 2}, {119163, 1}, {119227, 34717955},
2187 	{119228, 34718467}, {119229, 51496195}, {119230, 51496963}, {119231, 51497731},
2188 	{119232, 51498499}, {119233, 1}, {119275, 2}, {119296, 1},
2189 	{119366, 2}, {119488, 1}, {119508, 2}, {119520, 1},
2190 	{119540, 2}, {119552, 1}, {119639, 2}, {119648, 1},
2191 	{119673, 2}, {119808, 16777219}, {119809, 16777475}, {119810, 16777731},
2192 	{119811, 16777987}, {119812, 16778243}, {119813, 16778499}, {119814, 16778755},
2193 	{119815, 16779011}, {119816, 16779267}, {119817, 16779523}, {119818, 16779779},
2194 	{119819, 16780035}, {119820, 16780291}, {119821, 16780547}, {119822, 16780803},
2195 	{119823, 16781059}, {119824, 16781315}, {119825, 16781571}, {119826, 16781827},
2196 	{119827, 16782083}, {119828, 16782339}, {119829, 16782595}, {119830, 16782851},
2197 	{119831, 16783107}, {119832, 16783363}, {119833, 16783619}, {119834, 16777219},
2198 	{119835, 16777475}, {119836, 16777731}, {119837, 16777987}, {119838, 16778243},
2199 	{119839, 16778499}, {119840, 16778755}, {119841, 16779011}, {119842, 16779267},
2200 	{119843, 16779523}, {119844, 16779779}, {119845, 16780035}, {119846, 16780291},
2201 	{119847, 16780547}, {119848, 16780803}, {119849, 16781059}, {119850, 16781315},
2202 	{119851, 16781571}, {119852, 16781827}, {119853, 16782083}, {119854, 16782339},
2203 	{119855, 16782595}, {119856, 16782851}, {119857, 16783107}, {119858, 16783363},
2204 	{119859, 16783619}, {119860, 16777219}, {119861, 16777475}, {119862, 16777731},
2205 	{119863, 16777987}, {119864, 16778243}, {119865, 16778499}, {119866, 16778755},
2206 	{119867, 16779011}, {119868, 16779267}, {119869, 16779523}, {119870, 16779779},
2207 	{119871, 16780035}, {119872, 16780291}, {119873, 16780547}, {119874, 16780803},
2208 	{119875, 16781059}, {119876, 16781315}, {119877, 16781571}, {119878, 16781827},
2209 	{119879, 16782083}, {119880, 16782339}, {119881, 16782595}, {119882, 16782851},
2210 	{119883, 16783107}, {119884, 16783363}, {119885, 16783619}, {119886, 16777219},
2211 	{119887, 16777475}, {119888, 16777731}, {119889, 16777987}, {119890, 16778243},
2212 	{119891, 16778499}, {119892, 16778755}, {119893, 2}, {119894, 16779267},
2213 	{119895, 16779523}, {119896, 16779779}, {119897, 16780035}, {119898, 16780291},
2214 	{119899, 16780547}, {119900, 16780803}, {119901, 16781059}, {119902, 16781315},
2215 	{119903, 16781571}, {119904, 16781827}, {119905, 16782083}, {119906, 16782339},
2216 	{119907, 16782595}, {119908, 16782851}, {119909, 16783107}, {119910, 16783363},
2217 	{119911, 16783619}, {119912, 16777219}, {119913, 16777475}, {119914, 16777731},
2218 	{119915, 16777987}, {119916, 16778243}, {119917, 16778499}, {119918, 16778755},
2219 	{119919, 16779011}, {119920, 16779267}, {119921, 16779523}, {119922, 16779779},
2220 	{119923, 16780035}, {119924, 16780291}, {119925, 16780547}, {119926, 16780803},
2221 	{119927, 16781059}, {119928, 16781315}, {119929, 16781571}, {119930, 16781827},
2222 	{119931, 16782083}, {119932, 16782339}, {119933, 16782595}, {119934, 16782851},
2223 	{119935, 16783107}, {119936, 16783363}, {119937, 16783619}, {119938, 16777219},
2224 	{119939, 16777475}, {119940, 16777731}, {119941, 16777987}, {119942, 16778243},
2225 	{119943, 16778499}, {119944, 16778755}, {119945, 16779011}, {119946, 16779267},
2226 	{119947, 16779523}, {119948, 16779779}, {119949, 16780035}, {119950, 16780291},
2227 	{119951, 16780547}, {119952, 16780803}, {119953, 16781059}, {119954, 16781315},
2228 	{119955, 16781571}, {119956, 16781827}, {119957, 16782083}, {119958, 16782339},
2229 	{119959, 16782595}, {119960, 16782851}, {119961, 16783107}, {119962, 16783363},
2230 	{119963, 16783619}, {119964, 16777219}, {119965, 2}, {119966, 16777731},
2231 	{119967, 16777987}, {119968, 2}, {119970, 16778755}, {119971, 2},
2232 	{119973, 16779523}, {119974, 16779779}, {119975, 2}, {119977, 16780547},
2233 	{119978, 16780803}, {119979, 16781059}, {119980, 16781315}, {119981, 2},
2234 	{119982, 16781827}, {119983, 16782083}, {119984, 16782339}, {119985, 16782595},
2235 	{119986, 16782851}, {119987, 16783107}, {119988, 16783363}, {119989, 16783619},
2236 	{119990, 16777219}, {119991, 16777475}, {119992, 16777731}, {119993, 16777987},
2237 	{119994, 2}, {119995, 16778499}, {119996, 2}, {119997, 16779011},
2238 	{119998, 16779267}, {119999, 16779523}, {120000, 16779779}, {120001, 16780035},
2239 	{120002, 16780291}, {120003, 16780547}, {120004, 2}, {120005, 16781059},
2240 	{120006, 16781315}, {120007, 16781571}, {120008, 16781827}, {120009, 16782083},
2241 	{120010, 16782339}, {120011, 16782595}, {120012, 16782851}, {120013, 16783107},
2242 	{120014, 16783363}, {120015, 16783619}, {120016, 16777219}, {120017, 16777475},
2243 	{120018, 16777731}, {120019, 16777987}, {120020, 16778243}, {120021, 16778499},
2244 	{120022, 16778755}, {120023, 16779011}, {120024, 16779267}, {120025, 16779523},
2245 	{120026, 16779779}, {120027, 16780035}, {120028, 16780291}, {120029, 16780547},
2246 	{120030, 16780803}, {120031, 16781059}, {120032, 16781315}, {120033, 16781571},
2247 	{120034, 16781827}, {120035, 16782083}, {120036, 16782339}, {120037, 16782595},
2248 	{120038, 16782851}, {120039, 16783107}, {120040, 16783363}, {120041, 16783619},
2249 	{120042, 16777219}, {120043, 16777475}, {120044, 16777731}, {120045, 16777987},
2250 	{120046, 16778243}, {120047, 16778499}, {120048, 16778755}, {120049, 16779011},
2251 	{120050, 16779267}, {120051, 16779523}, {120052, 16779779}, {120053, 16780035},
2252 	{120054, 16780291}, {120055, 16780547}, {120056, 16780803}, {120057, 16781059},
2253 	{120058, 16781315}, {120059, 16781571}, {120060, 16781827}, {120061, 16782083},
2254 	{120062, 16782339}, {120063, 16782595}, {120064, 16782851}, {120065, 16783107},
2255 	{120066, 16783363}, {120067, 16783619}, {120068, 16777219}, {120069, 16777475},
2256 	{120070, 2}, {120071, 16777987}, {120072, 16778243}, {120073, 16778499},
2257 	{120074, 16778755}, {120075, 2}, {120077, 16779523}, {120078, 16779779},
2258 	{120079, 16780035}, {120080, 16780291}, {120081, 16780547}, {120082, 16780803},
2259 	{120083, 16781059}, {120084, 16781315}, {120085, 2}, {120086, 16781827},
2260 	{120087, 16782083}, {120088, 16782339}, {120089, 16782595}, {120090, 16782851},
2261 	{120091, 16783107}, {120092, 16783363}, {120093, 2}, {120094, 16777219},
2262 	{120095, 16777475}, {120096, 16777731}, {120097, 16777987}, {120098, 16778243},
2263 	{120099, 16778499}, {120100, 16778755}, {120101, 16779011}, {120102, 16779267},
2264 	{120103, 16779523}, {120104, 16779779}, {120105, 16780035}, {120106, 16780291},
2265 	{120107, 16780547}, {120108, 16780803}, {120109, 16781059}, {120110, 16781315},
2266 	{120111, 16781571}, {120112, 16781827}, {120113, 16782083}, {120114, 16782339},
2267 	{120115, 16782595}, {120116, 16782851}, {120117, 16783107}, {120118, 16783363},
2268 	{120119, 16783619}, {120120, 16777219}, {120121, 16777475}, {120122, 2},
2269 	{120123, 16777987}, {120124, 16778243}, {120125, 16778499}, {120126, 16778755},
2270 	{120127, 2}, {120128, 16779267}, {120129, 16779523}, {120130, 16779779},
2271 	{120131, 16780035}, {120132, 16780291}, {120133, 2}, {120134, 16780803},
2272 	{120135, 2}, {120138, 16781827}, {120139, 16782083}, {120140, 16782339},
2273 	{120141, 16782595}, {120142, 16782851}, {120143, 16783107}, {120144, 16783363},
2274 	{120145, 2}, {120146, 16777219}, {120147, 16777475}, {120148, 16777731},
2275 	{120149, 16777987}, {120150, 16778243}, {120151, 16778499}, {120152, 16778755},
2276 	{120153, 16779011}, {120154, 16779267}, {120155, 16779523}, {120156, 16779779},
2277 	{120157, 16780035}, {120158, 16780291}, {120159, 16780547}, {120160, 16780803},
2278 	{120161, 16781059}, {120162, 16781315}, {120163, 16781571}, {120164, 16781827},
2279 	{120165, 16782083}, {120166, 16782339}, {120167, 16782595}, {120168, 16782851},
2280 	{120169, 16783107}, {120170, 16783363}, {120171, 16783619}, {120172, 16777219},
2281 	{120173, 16777475}, {120174, 16777731}, {120175, 16777987}, {120176, 16778243},
2282 	{120177, 16778499}, {120178, 16778755}, {120179, 16779011}, {120180, 16779267},
2283 	{120181, 16779523}, {120182, 16779779}, {120183, 16780035}, {120184, 16780291},
2284 	{120185, 16780547}, {120186, 16780803}, {120187, 16781059}, {120188, 16781315},
2285 	{120189, 16781571}, {120190, 16781827}, {120191, 16782083}, {120192, 16782339},
2286 	{120193, 16782595}, {120194, 16782851}, {120195, 16783107}, {120196, 16783363},
2287 	{120197, 16783619}, {120198, 16777219}, {120199, 16777475}, {120200, 16777731},
2288 	{120201, 16777987}, {120202, 16778243}, {120203, 16778499}, {120204, 16778755},
2289 	{120205, 16779011}, {120206, 16779267}, {120207, 16779523}, {120208, 16779779},
2290 	{120209, 16780035}, {120210, 16780291}, {120211, 16780547}, {120212, 16780803},
2291 	{120213, 16781059}, {120214, 16781315}, {120215, 16781571}, {120216, 16781827},
2292 	{120217, 16782083}, {120218, 16782339}, {120219, 16782595}, {120220, 16782851},
2293 	{120221, 16783107}, {120222, 16783363}, {120223, 16783619}, {120224, 16777219},
2294 	{120225, 16777475}, {120226, 16777731}, {120227, 16777987}, {120228, 16778243},
2295 	{120229, 16778499}, {120230, 16778755}, {120231, 16779011}, {120232, 16779267},
2296 	{120233, 16779523}, {120234, 16779779}, {120235, 16780035}, {120236, 16780291},
2297 	{120237, 16780547}, {120238, 16780803}, {120239, 16781059}, {120240, 16781315},
2298 	{120241, 16781571}, {120242, 16781827}, {120243, 16782083}, {120244, 16782339},
2299 	{120245, 16782595}, {120246, 16782851}, {120247, 16783107}, {120248, 16783363},
2300 	{120249, 16783619}, {120250, 16777219}, {120251, 16777475}, {120252, 16777731},
2301 	{120253, 16777987}, {120254, 16778243}, {120255, 16778499}, {120256, 16778755},
2302 	{120257, 16779011}, {120258, 16779267}, {120259, 16779523}, {120260, 16779779},
2303 	{120261, 16780035}, {120262, 16780291}, {120263, 16780547}, {120264, 16780803},
2304 	{120265, 16781059}, {120266, 16781315}, {120267, 16781571}, {120268, 16781827},
2305 	{120269, 16782083}, {120270, 16782339}, {120271, 16782595}, {120272, 16782851},
2306 	{120273, 16783107}, {120274, 16783363}, {120275, 16783619}, {120276, 16777219},
2307 	{120277, 16777475}, {120278, 16777731}, {120279, 16777987}, {120280, 16778243},
2308 	{120281, 16778499}, {120282, 16778755}, {120283, 16779011}, {120284, 16779267},
2309 	{120285, 16779523}, {120286, 16779779}, {120287, 16780035}, {120288, 16780291},
2310 	{120289, 16780547}, {120290, 16780803}, {120291, 16781059}, {120292, 16781315},
2311 	{120293, 16781571}, {120294, 16781827}, {120295, 16782083}, {120296, 16782339},
2312 	{120297, 16782595}, {120298, 16782851}, {120299, 16783107}, {120300, 16783363},
2313 	{120301, 16783619}, {120302, 16777219}, {120303, 16777475}, {120304, 16777731},
2314 	{120305, 16777987}, {120306, 16778243}, {120307, 16778499}, {120308, 16778755},
2315 	{120309, 16779011}, {120310, 16779267}, {120311, 16779523}, {120312, 16779779},
2316 	{120313, 16780035}, {120314, 16780291}, {120315, 16780547}, {120316, 16780803},
2317 	{120317, 16781059}, {120318, 16781315}, {120319, 16781571}, {120320, 16781827},
2318 	{120321, 16782083}, {120322, 16782339}, {120323, 16782595}, {120324, 16782851},
2319 	{120325, 16783107}, {120326, 16783363}, {120327, 16783619}, {120328, 16777219},
2320 	{120329, 16777475}, {120330, 16777731}, {120331, 16777987}, {120332, 16778243},
2321 	{120333, 16778499}, {120334, 16778755}, {120335, 16779011}, {120336, 16779267},
2322 	{120337, 16779523}, {120338, 16779779}, {120339, 16780035}, {120340, 16780291},
2323 	{120341, 16780547}, {120342, 16780803}, {120343, 16781059}, {120344, 16781315},
2324 	{120345, 16781571}, {120346, 16781827}, {120347, 16782083}, {120348, 16782339},
2325 	{120349, 16782595}, {120350, 16782851}, {120351, 16783107}, {120352, 16783363},
2326 	{120353, 16783619}, {120354, 16777219}, {120355, 16777475}, {120356, 16777731},
2327 	{120357, 16777987}, {120358, 16778243}, {120359, 16778499}, {120360, 16778755},
2328 	{120361, 16779011}, {120362, 16779267}, {120363, 16779523}, {120364, 16779779},
2329 	{120365, 16780035}, {120366, 16780291}, {120367, 16780547}, {120368, 16780803},
2330 	{120369, 16781059}, {120370, 16781315}, {120371, 16781571}, {120372, 16781827},
2331 	{120373, 16782083}, {120374, 16782339}, {120375, 16782595}, {120376, 16782851},
2332 	{120377, 16783107}, {120378, 16783363}, {120379, 16783619}, {120380, 16777219},
2333 	{120381, 16777475}, {120382, 16777731}, {120383, 16777987}, {120384, 16778243},
2334 	{120385, 16778499}, {120386, 16778755}, {120387, 16779011}, {120388, 16779267},
2335 	{120389, 16779523}, {120390, 16779779}, {120391, 16780035}, {120392, 16780291},
2336 	{120393, 16780547}, {120394, 16780803}, {120395, 16781059}, {120396, 16781315},
2337 	{120397, 16781571}, {120398, 16781827}, {120399, 16782083}, {120400, 16782339},
2338 	{120401, 16782595}, {120402, 16782851}, {120403, 16783107}, {120404, 16783363},
2339 	{120405, 16783619}, {120406, 16777219}, {120407, 16777475}, {120408, 16777731},
2340 	{120409, 16777987}, {120410, 16778243}, {120411, 16778499}, {120412, 16778755},
2341 	{120413, 16779011}, {120414, 16779267}, {120415, 16779523}, {120416, 16779779},
2342 	{120417, 16780035}, {120418, 16780291}, {120419, 16780547}, {120420, 16780803},
2343 	{120421, 16781059}, {120422, 16781315}, {120423, 16781571}, {120424, 16781827},
2344 	{120425, 16782083}, {120426, 16782339}, {120427, 16782595}, {120428, 16782851},
2345 	{120429, 16783107}, {120430, 16783363}, {120431, 16783619}, {120432, 16777219},
2346 	{120433, 16777475}, {120434, 16777731}, {120435, 16777987}, {120436, 16778243},
2347 	{120437, 16778499}, {120438, 16778755}, {120439, 16779011}, {120440, 16779267},
2348 	{120441, 16779523}, {120442, 16779779}, {120443, 16780035}, {120444, 16780291},
2349 	{120445, 16780547}, {120446, 16780803}, {120447, 16781059}, {120448, 16781315},
2350 	{120449, 16781571}, {120450, 16781827}, {120451, 16782083}, {120452, 16782339},
2351 	{120453, 16782595}, {120454, 16782851}, {120455, 16783107}, {120456, 16783363},
2352 	{120457, 16783619}, {120458, 16777219}, {120459, 16777475}, {120460, 16777731},
2353 	{120461, 16777987}, {120462, 16778243}, {120463, 16778499}, {120464, 16778755},
2354 	{120465, 16779011}, {120466, 16779267}, {120467, 16779523}, {120468, 16779779},
2355 	{120469, 16780035}, {120470, 16780291}, {120471, 16780547}, {120472, 16780803},
2356 	{120473, 16781059}, {120474, 16781315}, {120475, 16781571}, {120476, 16781827},
2357 	{120477, 16782083}, {120478, 16782339}, {120479, 16782595}, {120480, 16782851},
2358 	{120481, 16783107}, {120482, 16783363}, {120483, 16783619}, {120484, 17944835},
2359 	{120485, 17945091}, {120486, 2}, {120488, 16851715}, {120489, 16851971},
2360 	{120490, 16852227}, {120491, 16852483}, {120492, 16852739}, {120493, 16852995},
2361 	{120494, 16853251}, {120495, 16853507}, {120496, 16846851}, {120497, 16853763},
2362 	{120498, 16854019}, {120499, 16786179}, {120500, 16854275}, {120501, 16854531},
2363 	{120502, 16854787}, {120503, 16855043}, {120504, 16855299}, {120505, 16853507},
2364 	{120506, 16855555}, {120507, 16855811}, {120508, 16856067}, {120509, 16856323},
2365 	{120510, 16856579}, {120511, 16856835}, {120512, 16857091}, {120513, 17945347},
2366 	{120514, 16851715}, {120515, 16851971}, {120516, 16852227}, {120517, 16852483},
2367 	{120518, 16852739}, {120519, 16852995}, {120520, 16853251}, {120521, 16853507},
2368 	{120522, 16846851}, {120523, 16853763}, {120524, 16854019}, {120525, 16786179},
2369 	{120526, 16854275}, {120527, 16854531}, {120528, 16854787}, {120529, 16855043},
2370 	{120530, 16855299}, {120531, 16855555}, {120533, 16855811}, {120534, 16856067},
2371 	{120535, 16856323}, {120536, 16856579}, {120537, 16856835}, {120538, 16857091},
2372 	{120539, 17945603}, {120540, 16852739}, {120541, 16853507}, {120542, 16853763},
2373 	{120543, 16856323}, {120544, 16855299}, {120545, 16855043}, {120546, 16851715},
2374 	{120547, 16851971}, {120548, 16852227}, {120549, 16852483}, {120550, 16852739},
2375 	{120551, 16852995}, {120552, 16853251}, {120553, 16853507}, {120554, 16846851},
2376 	{120555, 16853763}, {120556, 16854019}, {120557, 16786179}, {120558, 16854275},
2377 	{120559, 16854531}, {120560, 16854787}, {120561, 16855043}, {120562, 16855299},
2378 	{120563, 16853507}, {120564, 16855555}, {120565, 16855811}, {120566, 16856067},
2379 	{120567, 16856323}, {120568, 16856579}, {120569, 16856835}, {120570, 16857091},
2380 	{120571, 17945347}, {120572, 16851715}, {120573, 16851971}, {120574, 16852227},
2381 	{120575, 16852483}, {120576, 16852739}, {120577, 16852995}, {120578, 16853251},
2382 	{120579, 16853507}, {120580, 16846851}, {120581, 16853763}, {120582, 16854019},
2383 	{120583, 16786179}, {120584, 16854275}, {120585, 16854531}, {120586, 16854787},
2384 	{120587, 16855043}, {120588, 16855299}, {120589, 16855555}, {120591, 16855811},
2385 	{120592, 16856067}, {120593, 16856323}, {120594, 16856579}, {120595, 16856835},
2386 	{120596, 16857091}, {120597, 17945603}, {120598, 16852739}, {120599, 16853507},
2387 	{120600, 16853763}, {120601, 16856323}, {120602, 16855299}, {120603, 16855043},
2388 	{120604, 16851715}, {120605, 16851971}, {120606, 16852227}, {120607, 16852483},
2389 	{120608, 16852739}, {120609, 16852995}, {120610, 16853251}, {120611, 16853507},
2390 	{120612, 16846851}, {120613, 16853763}, {120614, 16854019}, {120615, 16786179},
2391 	{120616, 16854275}, {120617, 16854531}, {120618, 16854787}, {120619, 16855043},
2392 	{120620, 16855299}, {120621, 16853507}, {120622, 16855555}, {120623, 16855811},
2393 	{120624, 16856067}, {120625, 16856323}, {120626, 16856579}, {120627, 16856835},
2394 	{120628, 16857091}, {120629, 17945347}, {120630, 16851715}, {120631, 16851971},
2395 	{120632, 16852227}, {120633, 16852483}, {120634, 16852739}, {120635, 16852995},
2396 	{120636, 16853251}, {120637, 16853507}, {120638, 16846851}, {120639, 16853763},
2397 	{120640, 16854019}, {120641, 16786179}, {120642, 16854275}, {120643, 16854531},
2398 	{120644, 16854787}, {120645, 16855043}, {120646, 16855299}, {120647, 16855555},
2399 	{120649, 16855811}, {120650, 16856067}, {120651, 16856323}, {120652, 16856579},
2400 	{120653, 16856835}, {120654, 16857091}, {120655, 17945603}, {120656, 16852739},
2401 	{120657, 16853507}, {120658, 16853763}, {120659, 16856323}, {120660, 16855299},
2402 	{120661, 16855043}, {120662, 16851715}, {120663, 16851971}, {120664, 16852227},
2403 	{120665, 16852483}, {120666, 16852739}, {120667, 16852995}, {120668, 16853251},
2404 	{120669, 16853507}, {120670, 16846851}, {120671, 16853763}, {120672, 16854019},
2405 	{120673, 16786179}, {120674, 16854275}, {120675, 16854531}, {120676, 16854787},
2406 	{120677, 16855043}, {120678, 16855299}, {120679, 16853507}, {120680, 16855555},
2407 	{120681, 16855811}, {120682, 16856067}, {120683, 16856323}, {120684, 16856579},
2408 	{120685, 16856835}, {120686, 16857091}, {120687, 17945347}, {120688, 16851715},
2409 	{120689, 16851971}, {120690, 16852227}, {120691, 16852483}, {120692, 16852739},
2410 	{120693, 16852995}, {120694, 16853251}, {120695, 16853507}, {120696, 16846851},
2411 	{120697, 16853763}, {120698, 16854019}, {120699, 16786179}, {120700, 16854275},
2412 	{120701, 16854531}, {120702, 16854787}, {120703, 16855043}, {120704, 16855299},
2413 	{120705, 16855555}, {120707, 16855811}, {120708, 16856067}, {120709, 16856323},
2414 	{120710, 16856579}, {120711, 16856835}, {120712, 16857091}, {120713, 17945603},
2415 	{120714, 16852739}, {120715, 16853507}, {120716, 16853763}, {120717, 16856323},
2416 	{120718, 16855299}, {120719, 16855043}, {120720, 16851715}, {120721, 16851971},
2417 	{120722, 16852227}, {120723, 16852483}, {120724, 16852739}, {120725, 16852995},
2418 	{120726, 16853251}, {120727, 16853507}, {120728, 16846851}, {120729, 16853763},
2419 	{120730, 16854019}, {120731, 16786179}, {120732, 16854275}, {120733, 16854531},
2420 	{120734, 16854787}, {120735, 16855043}, {120736, 16855299}, {120737, 16853507},
2421 	{120738, 16855555}, {120739, 16855811}, {120740, 16856067}, {120741, 16856323},
2422 	{120742, 16856579}, {120743, 16856835}, {120744, 16857091}, {120745, 17945347},
2423 	{120746, 16851715}, {120747, 16851971}, {120748, 16852227}, {120749, 16852483},
2424 	{120750, 16852739}, {120751, 16852995}, {120752, 16853251}, {120753, 16853507},
2425 	{120754, 16846851}, {120755, 16853763}, {120756, 16854019}, {120757, 16786179},
2426 	{120758, 16854275}, {120759, 16854531}, {120760, 16854787}, {120761, 16855043},
2427 	{120762, 16855299}, {120763, 16855555}, {120765, 16855811}, {120766, 16856067},
2428 	{120767, 16856323}, {120768, 16856579}, {120769, 16856835}, {120770, 16857091},
2429 	{120771, 17945603}, {120772, 16852739}, {120773, 16853507}, {120774, 16853763},
2430 	{120775, 16856323}, {120776, 16855299}, {120777, 16855043}, {120778, 16858627},
2431 	{120780, 2}, {120782, 17035523}, {120783, 16786947}, {120784, 16785155},
2432 	{120785, 16785411}, {120786, 16787715}, {120787, 17035779}, {120788, 17036035},
2433 	{120789, 17036291}, {120790, 17036547}, {120791, 17036803}, {120792, 17035523},
2434 	{120793, 16786947}, {120794, 16785155}, {120795, 16785411}, {120796, 16787715},
2435 	{120797, 17035779}, {120798, 17036035}, {120799, 17036291}, {120800, 17036547},
2436 	{120801, 17036803}, {120802, 17035523}, {120803, 16786947}, {120804, 16785155},
2437 	{120805, 16785411}, {120806, 16787715}, {120807, 17035779}, {120808, 17036035},
2438 	{120809, 17036291}, {120810, 17036547}, {120811, 17036803}, {120812, 17035523},
2439 	{120813, 16786947}, {120814, 16785155}, {120815, 16785411}, {120816, 16787715},
2440 	{120817, 17035779}, {120818, 17036035}, {120819, 17036291}, {120820, 17036547},
2441 	{120821, 17036803}, {120822, 17035523}, {120823, 16786947}, {120824, 16785155},
2442 	{120825, 16785411}, {120826, 16787715}, {120827, 17035779}, {120828, 17036035},
2443 	{120829, 17036291}, {120830, 17036547}, {120831, 17036803}, {120832, 1},
2444 	{121484, 2}, {121499, 1}, {121504, 2}, {121505, 1},
2445 	{121520, 2}, {122624, 1}, {122655, 2}, {122661, 1},
2446 	{122667, 2}, {122880, 1}, {122887, 2}, {122888, 1},
2447 	{122905, 2}, {122907, 1}, {122914, 2}, {122915, 1},
2448 	{122917, 2}, {122918, 1}, {122923, 2}, {122928, 16866563},
2449 	{122929, 16866819}, {122930, 16867075}, {122931, 16867331}, {122932, 16867587},
2450 	{122933, 16867843}, {122934, 16868099}, {122935, 16868355}, {122936, 16868611},
2451 	{122937, 16869123}, {122938, 16869379}, {122939, 16869635}, {122940, 16870147},
2452 	{122941, 16870403}, {122942, 16870659}, {122943, 16870915}, {122944, 16871171},
2453 	{122945, 16871427}, {122946, 16871683}, {122947, 16871939}, {122948, 16872195},
2454 	{122949, 16872451}, {122950, 16872707}, {122951, 16873475}, {122952, 16873987},
2455 	{122953, 16874243}, {122954, 17495299}, {122955, 16888835}, {122956, 16864003},
2456 	{122957, 16864515}, {122958, 16890883}, {122959, 16883715}, {122960, 17945859},
2457 	{122961, 16866563}, {122962, 16866819}, {122963, 16867075}, {122964, 16867331},
2458 	{122965, 16867587}, {122966, 16867843}, {122967, 16868099}, {122968, 16868355},
2459 	{122969, 16868611}, {122970, 16869123}, {122971, 16869379}, {122972, 16870147},
2460 	{122973, 16870403}, {122974, 16870915}, {122975, 16871427}, {122976, 16871683},
2461 	{122977, 16871939}, {122978, 16872195}, {122979, 16872451}, {122980, 16872707},
2462 	{122981, 16873219}, {122982, 16873475}, {122983, 16879875}, {122984, 16864003},
2463 	{122985, 16863747}, {122986, 16866307}, {122987, 16883203}, {122988, 17490435},
2464 	{122989, 16883971}, {122990, 2}, {123023, 1}, {123024, 2},
2465 	{123136, 1}, {123181, 2}, {123184, 1}, {123198, 2},
2466 	{123200, 1}, {123210, 2}, {123214, 1}, {123216, 2},
2467 	{123536, 1}, {123567, 2}, {123584, 1}, {123642, 2},
2468 	{123647, 1}, {123648, 2}, {124112, 1}, {124154, 2},
2469 	{124896, 1}, {124903, 2}, {124904, 1}, {124908, 2},
2470 	{124909, 1}, {124911, 2}, {124912, 1}, {124927, 2},
2471 	{124928, 1}, {125125, 2}, {125127, 1}, {125143, 2},
2472 	{125184, 17946115}, {125185, 17946371}, {125186, 17946627}, {125187, 17946883},
2473 	{125188, 17947139}, {125189, 17947395}, {125190, 17947651}, {125191, 17947907},
2474 	{125192, 17948163}, {125193, 17948419}, {125194, 17948675}, {125195, 17948931},
2475 	{125196, 17949187}, {125197, 17949443}, {125198, 17949699}, {125199, 17949955},
2476 	{125200, 17950211}, {125201, 17950467}, {125202, 17950723}, {125203, 17950979},
2477 	{125204, 17951235}, {125205, 17951491}, {125206, 17951747}, {125207, 17952003},
2478 	{125208, 17952259}, {125209, 17952515}, {125210, 17952771}, {125211, 17953027},
2479 	{125212, 17953283}, {125213, 17953539}, {125214, 17953795}, {125215, 17954051},
2480 	{125216, 17954307}, {125217, 17954563}, {125218, 1}, {125260, 2},
2481 	{125264, 1}, {125274, 2}, {125278, 1}, {125280, 2},
2482 	{126065, 1}, {126133, 2}, {126209, 1}, {126270, 2},
2483 	{126464, 16910339}, {126465, 17683715}, {126466, 17681923}, {126467, 17834499},
2484 	{126468, 2}, {126469, 16910851}, {126470, 17731587}, {126471, 17682435},
2485 	{126472, 17700099}, {126473, 16911875}, {126474, 17708803}, {126475, 17711107},
2486 	{126476, 17682947}, {126477, 17718019}, {126478, 17694979}, {126479, 17701635},
2487 	{126480, 17703683}, {126481, 17697027}, {126482, 17706755}, {126483, 17725187},
2488 	{126484, 17745155}, {126485, 17686787}, {126486, 17689859}, {126487, 17684995},
2489 	{126488, 17724675}, {126489, 17698051}, {126490, 17701123}, {126491, 17702659},
2490 	{126492, 17954819}, {126493, 17673475}, {126494, 17955075}, {126495, 17955331},
2491 	{126496, 2}, {126497, 17683715}, {126498, 17681923}, {126499, 2},
2492 	{126500, 17721091}, {126501, 2}, {126503, 17682435}, {126504, 2},
2493 	{126505, 16911875}, {126506, 17708803}, {126507, 17711107}, {126508, 17682947},
2494 	{126509, 17718019}, {126510, 17694979}, {126511, 17701635}, {126512, 17703683},
2495 	{126513, 17697027}, {126514, 17706755}, {126515, 2}, {126516, 17745155},
2496 	{126517, 17686787}, {126518, 17689859}, {126519, 17684995}, {126520, 2},
2497 	{126521, 17698051}, {126522, 2}, {126523, 17702659}, {126524, 2},
2498 	{126530, 17681923}, {126531, 2}, {126535, 17682435}, {126536, 2},
2499 	{126537, 16911875}, {126538, 2}, {126539, 17711107}, {126540, 2},
2500 	{126541, 17718019}, {126542, 17694979}, {126543, 17701635}, {126544, 2},
2501 	{126545, 17697027}, {126546, 17706755}, {126547, 2}, {126548, 17745155},
2502 	{126549, 2}, {126551, 17684995}, {126552, 2}, {126553, 17698051},
2503 	{126554, 2}, {126555, 17702659}, {126556, 2}, {126557, 17673475},
2504 	{126558, 2}, {126559, 17955331}, {126560, 2}, {126561, 17683715},
2505 	{126562, 17681923}, {126563, 2}, {126564, 17721091}, {126565, 2},
2506 	{126567, 17682435}, {126568, 17700099}, {126569, 16911875}, {126570, 17708803},
2507 	{126571, 2}, {126572, 17682947}, {126573, 17718019}, {126574, 17694979},
2508 	{126575, 17701635}, {126576, 17703683}, {126577, 17697027}, {126578, 17706755},
2509 	{126579, 2}, {126580, 17745155}, {126581, 17686787}, {126582, 17689859},
2510 	{126583, 17684995}, {126584, 2}, {126585, 17698051}, {126586, 17701123},
2511 	{126587, 17702659}, {126588, 17954819}, {126589, 2}, {126590, 17955075},
2512 	{126591, 2}, {126592, 16910339}, {126593, 17683715}, {126594, 17681923},
2513 	{126595, 17834499}, {126596, 17721091}, {126597, 16910851}, {126598, 17731587},
2514 	{126599, 17682435}, {126600, 17700099}, {126601, 16911875}, {126602, 2},
2515 	{126603, 17711107}, {126604, 17682947}, {126605, 17718019}, {126606, 17694979},
2516 	{126607, 17701635}, {126608, 17703683}, {126609, 17697027}, {126610, 17706755},
2517 	{126611, 17725187}, {126612, 17745155}, {126613, 17686787}, {126614, 17689859},
2518 	{126615, 17684995}, {126616, 17724675}, {126617, 17698051}, {126618, 17701123},
2519 	{126619, 17702659}, {126620, 2}, {126625, 17683715}, {126626, 17681923},
2520 	{126627, 17834499}, {126628, 2}, {126629, 16910851}, {126630, 17731587},
2521 	{126631, 17682435}, {126632, 17700099}, {126633, 16911875}, {126634, 2},
2522 	{126635, 17711107}, {126636, 17682947}, {126637, 17718019}, {126638, 17694979},
2523 	{126639, 17701635}, {126640, 17703683}, {126641, 17697027}, {126642, 17706755},
2524 	{126643, 17725187}, {126644, 17745155}, {126645, 17686787}, {126646, 17689859},
2525 	{126647, 17684995}, {126648, 17724675}, {126649, 17698051}, {126650, 17701123},
2526 	{126651, 17702659}, {126652, 2}, {126704, 1}, {126706, 2},
2527 	{126976, 1}, {127020, 2}, {127024, 1}, {127124, 2},
2528 	{127136, 1}, {127151, 2}, {127153, 1}, {127168, 2},
2529 	{127169, 1}, {127184, 2}, {127185, 1}, {127222, 2},
2530 	{127233, 34732803}, {127234, 34733315}, {127235, 34733827}, {127236, 34734339},
2531 	{127237, 34734851}, {127238, 34735363}, {127239, 34735875}, {127240, 34736387},
2532 	{127241, 34736899}, {127242, 34737411}, {127243, 1}, {127248, 50644995},
2533 	{127249, 50645763}, {127250, 50646531}, {127251, 50647299}, {127252, 50648067},
2534 	{127253, 50648835}, {127254, 50649603}, {127255, 50650371}, {127256, 50651139},
2535 	{127257, 50651907}, {127258, 50652675}, {127259, 50653443}, {127260, 50654211},
2536 	{127261, 50654979}, {127262, 50655747}, {127263, 50656515}, {127264, 50657283},
2537 	{127265, 50658051}, {127266, 50658819}, {127267, 50659587}, {127268, 50660355},
2538 	{127269, 50661123}, {127270, 50661891}, {127271, 50662659}, {127272, 50663427},
2539 	{127273, 50664195}, {127274, 51515139}, {127275, 16777731}, {127276, 16781571},
2540 	{127277, 33554947}, {127278, 34738691}, {127279, 1}, {127280, 16777219},
2541 	{127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243},
2542 	{127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267},
2543 	{127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291},
2544 	{127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315},
2545 	{127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339},
2546 	{127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363},
2547 	{127305, 16783619}, {127306, 34739203}, {127307, 34226691}, {127308, 34739715},
2548 	{127309, 33752579}, {127310, 51517443}, {127311, 34740995}, {127312, 1},
2549 	{127338, 34209539}, {127339, 34189571}, {127340, 34741507}, {127341, 1},
2550 	{127376, 34742019}, {127377, 1}, {127406, 2}, {127462, 1},
2551 	{127488, 34742531}, {127489, 34743043}, {127490, 17307907}, {127491, 2},
2552 	{127504, 17157891}, {127505, 17966339}, {127506, 17966595}, {127507, 17351683},
2553 	{127508, 17143299}, {127509, 17966851}, {127510, 17967107}, {127511, 17225475},
2554 	{127512, 17967363}, {127513, 17967619}, {127514, 17967875}, {127515, 17584643},
2555 	{127516, 17968131}, {127517, 17968387}, {127518, 17968643}, {127519, 17968899},
2556 	{127520, 17969155}, {127521, 17969411}, {127522, 17167107}, {127523, 17969667},
2557 	{127524, 17969923}, {127525, 17970179}, {127526, 17970435}, {127527, 17970691},
2558 	{127528, 17970947}, {127529, 17141763}, {127530, 17223427}, {127531, 17971203},
2559 	{127532, 17288707}, {127533, 17224195}, {127534, 17288963}, {127535, 17971459},
2560 	{127536, 17181443}, {127537, 17971715}, {127538, 17971971}, {127539, 17972227},
2561 	{127540, 17972483}, {127541, 17972739}, {127542, 17264387}, {127543, 17160451},
2562 	{127544, 17972995}, {127545, 17973251}, {127546, 17973507}, {127547, 17973763},
2563 	{127548, 2}, {127552, 51528451}, {127553, 51529219}, {127554, 51529987},
2564 	{127555, 51530755}, {127556, 51531523}, {127557, 51532291}, {127558, 51533059},
2565 	{127559, 51533827}, {127560, 51534595}, {127561, 2}, {127568, 17980931},
2566 	{127569, 17981187}, {127570, 2}, {127584, 1}, {127590, 2},
2567 	{127744, 1}, {128728, 2}, {128732, 1}, {128749, 2},
2568 	{128752, 1}, {128765, 2}, {128768, 1}, {128887, 2},
2569 	{128891, 1}, {128986, 2}, {128992, 1}, {129004, 2},
2570 	{129008, 1}, {129009, 2}, {129024, 1}, {129036, 2},
2571 	{129040, 1}, {129096, 2}, {129104, 1}, {129114, 2},
2572 	{129120, 1}, {129160, 2}, {129168, 1}, {129198, 2},
2573 	{129200, 1}, {129202, 2}, {129280, 1}, {129620, 2},
2574 	{129632, 1}, {129646, 2}, {129648, 1}, {129661, 2},
2575 	{129664, 1}, {129673, 2}, {129680, 1}, {129726, 2},
2576 	{129727, 1}, {129734, 2}, {129742, 1}, {129756, 2},
2577 	{129760, 1}, {129769, 2}, {129776, 1}, {129785, 2},
2578 	{129792, 1}, {129939, 2}, {129940, 1}, {129995, 2},
2579 	{130032, 17035523}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2580 	{130036, 16787715}, {130037, 17035779}, {130038, 17036035}, {130039, 17036291},
2581 	{130040, 17036547}, {130041, 17036803}, {130042, 2}, {131072, 1},
2582 	{173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2583 	{178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2584 	{191457, 2}, {194560, 17981443}, {194561, 17981699}, {194562, 17981955},
2585 	{194563, 17982211}, {194564, 17982467}, {194565, 17608451}, {194566, 17982723},
2586 	{194567, 17982979}, {194568, 17983235}, {194569, 17983491}, {194570, 17608707},
2587 	{194571, 17983747}, {194572, 17984003}, {194573, 17984259}, {194574, 17608963},
2588 	{194575, 17984515}, {194576, 17984771}, {194577, 17985027}, {194578, 17985283},
2589 	{194579, 17985539}, {194580, 17985795}, {194581, 17968643}, {194582, 17986051},
2590 	{194583, 17986307}, {194584, 17986563}, {194585, 17986819}, {194586, 17987075},
2591 	{194587, 17623043}, {194588, 17987331}, {194589, 17145859}, {194590, 17987587},
2592 	{194591, 17987843}, {194592, 17988099}, {194593, 17988355}, {194594, 17973251},
2593 	{194595, 17988611}, {194596, 17988867}, {194597, 17624323}, {194598, 17609219},
2594 	{194599, 17609475}, {194600, 17624579}, {194601, 17989123}, {194602, 17989379},
2595 	{194603, 17562883}, {194604, 17989635}, {194605, 17609731}, {194606, 17989891},
2596 	{194607, 17990147}, {194608, 17990403}, {194609, 17990659}, {194612, 17990915},
2597 	{194613, 17991171}, {194614, 17991427}, {194615, 17991683}, {194616, 17991939},
2598 	{194617, 17992195}, {194618, 17992451}, {194619, 17992707}, {194620, 17992963},
2599 	{194621, 17993219}, {194622, 17993475}, {194623, 17993731}, {194624, 17993987},
2600 	{194625, 17994243}, {194626, 17994499}, {194627, 17994755}, {194628, 17995011},
2601 	{194629, 17995267}, {194631, 17625091}, {194632, 17995523}, {194633, 17995779},
2602 	{194634, 17996035}, {194635, 17996291}, {194636, 17610243}, {194637, 17996547},
2603 	{194638, 17996803}, {194639, 17997059}, {194640, 17600003}, {194641, 17997315},
2604 	{194642, 17997571}, {194643, 17997827}, {194644, 17998083}, {194645, 17998339},
2605 	{194646, 17998595}, {194647, 17998851}, {194648, 17999107}, {194649, 17999363},
2606 	{194650, 17999619}, {194651, 17999875}, {194652, 18000131}, {194653, 17966851},
2607 	{194654, 18000387}, {194655, 18000643}, {194656, 18000899}, {194657, 18001155},
2608 	{194658, 18001411}, {194659, 18001667}, {194660, 18001923}, {194661, 18002179},
2609 	{194662, 18002435}, {194663, 18002691}, {194664, 2}, {194665, 18002947},
2610 	{194666, 18003203}, {194668, 18003459}, {194669, 18003715}, {194670, 18003971},
2611 	{194671, 17561859}, {194672, 18004227}, {194673, 18004483}, {194674, 18004739},
2612 	{194675, 18004995}, {194676, 2}, {194677, 17152515}, {194678, 18005251},
2613 	{194679, 18005507}, {194680, 17153027}, {194681, 18005763}, {194682, 18006019},
2614 	{194683, 18006275}, {194684, 18006531}, {194685, 18006787}, {194686, 18007043},
2615 	{194687, 18007299}, {194688, 18007555}, {194689, 18007811}, {194690, 18008067},
2616 	{194691, 18008323}, {194692, 18008579}, {194693, 18008835}, {194694, 18009091},
2617 	{194695, 18009347}, {194696, 18009603}, {194697, 18009859}, {194698, 18010115},
2618 	{194699, 18010371}, {194700, 18010627}, {194701, 18010883}, {194702, 17548547},
2619 	{194703, 18011139}, {194704, 17155587}, {194705, 18011395}, {194707, 18011651},
2620 	{194708, 18011907}, {194710, 18012163}, {194711, 18012419}, {194712, 18012675},
2621 	{194713, 18012931}, {194714, 18013187}, {194715, 18013443}, {194716, 18013699},
2622 	{194717, 18013955}, {194718, 18014211}, {194719, 18014467}, {194720, 18014723},
2623 	{194721, 18014979}, {194722, 18015235}, {194723, 17611523}, {194724, 18015491},
2624 	{194725, 18015747}, {194726, 18016003}, {194727, 18016259}, {194728, 17628163},
2625 	{194729, 18016259}, {194730, 18016515}, {194731, 17612035}, {194732, 18016771},
2626 	{194733, 18017027}, {194734, 18017283}, {194735, 18017539}, {194736, 17612291},
2627 	{194737, 17541635}, {194738, 17414915}, {194739, 18017795}, {194740, 18018051},
2628 	{194741, 18018307}, {194742, 18018563}, {194743, 18018819}, {194744, 18019075},
2629 	{194745, 18019331}, {194746, 18019587}, {194747, 18019843}, {194748, 18020099},
2630 	{194749, 18020355}, {194750, 18020611}, {194751, 18020867}, {194752, 18021123},
2631 	{194753, 18021379}, {194754, 18021635}, {194755, 18021891}, {194756, 18022147},
2632 	{194757, 18022403}, {194758, 18022659}, {194759, 18022915}, {194760, 17612547},
2633 	{194761, 18023171}, {194762, 18023427}, {194763, 18023683}, {194764, 18023939},
2634 	{194765, 18024195}, {194766, 18024451}, {194767, 17613059}, {194768, 18024707},
2635 	{194769, 18024963}, {194770, 18025219}, {194771, 18025475}, {194772, 18025731},
2636 	{194773, 18025987}, {194774, 18026243}, {194775, 18026499}, {194776, 17548803},
2637 	{194777, 17630211}, {194778, 18026755}, {194779, 18027011}, {194780, 18027267},
2638 	{194781, 18027523}, {194782, 18027779}, {194783, 18028035}, {194784, 18028291},
2639 	{194785, 18028547}, {194786, 17613315}, {194787, 18028803}, {194788, 18029059},
2640 	{194789, 18029315}, {194790, 18029571}, {194791, 17640963}, {194792, 18029827},
2641 	{194793, 18030083}, {194794, 18030339}, {194795, 18030595}, {194796, 18030851},
2642 	{194797, 18031107}, {194798, 18031363}, {194799, 18031619}, {194800, 18031875},
2643 	{194801, 18032131}, {194802, 18032387}, {194803, 18032643}, {194804, 18032899},
2644 	{194805, 17566211}, {194806, 18033155}, {194807, 18033411}, {194808, 18033667},
2645 	{194809, 18033923}, {194810, 18034179}, {194811, 18034435}, {194812, 18034691},
2646 	{194813, 18034947}, {194814, 18035203}, {194815, 18035459}, {194816, 18035715},
2647 	{194817, 17613571}, {194818, 17587203}, {194819, 18035971}, {194820, 18036227},
2648 	{194821, 18036483}, {194822, 18036739}, {194823, 18036995}, {194824, 18037251},
2649 	{194825, 18037507}, {194826, 18037763}, {194827, 17630979}, {194828, 18038019},
2650 	{194829, 18038275}, {194830, 18038531}, {194831, 18038787}, {194832, 18039043},
2651 	{194833, 18039299}, {194834, 18039555}, {194835, 18039811}, {194836, 17631235},
2652 	{194837, 18040067}, {194838, 18040323}, {194839, 18040579}, {194840, 18040835},
2653 	{194841, 18041091}, {194842, 18041347}, {194843, 18041603}, {194844, 18041859},
2654 	{194845, 18042115}, {194846, 18042371}, {194847, 2}, {194848, 18042627},
2655 	{194849, 17631747}, {194850, 18042883}, {194851, 18043139}, {194852, 18043395},
2656 	{194853, 18043651}, {194854, 18043907}, {194855, 18044163}, {194856, 18044419},
2657 	{194857, 18044675}, {194858, 18044931}, {194859, 18045187}, {194860, 18045443},
2658 	{194862, 18045699}, {194863, 18045955}, {194864, 17632259}, {194865, 18046211},
2659 	{194866, 18046467}, {194867, 18046723}, {194868, 18046979}, {194869, 18047235},
2660 	{194870, 18047491}, {194871, 18047747}, {194872, 17562627}, {194873, 18048003},
2661 	{194874, 18048259}, {194875, 18048515}, {194876, 18048771}, {194877, 18049027},
2662 	{194878, 18049283}, {194879, 18049539}, {194880, 17633795}, {194881, 18049795},
2663 	{194882, 18050051}, {194883, 18050307}, {194884, 18050563}, {194885, 18050819},
2664 	{194886, 18051075}, {194888, 17634051}, {194889, 17641475}, {194890, 18051331},
2665 	{194891, 18051587}, {194892, 18051843}, {194893, 18052099}, {194894, 18052355},
2666 	{194895, 17553155}, {194896, 17634563}, {194897, 18052611}, {194898, 18052867},
2667 	{194899, 17616131}, {194900, 18053123}, {194901, 18053379}, {194902, 17605123},
2668 	{194903, 18053635}, {194904, 18053891}, {194905, 17616899}, {194906, 18054147},
2669 	{194907, 18054403}, {194908, 18054659}, {194909, 18054915}, {194911, 2},
2670 	{194912, 18055171}, {194913, 18055427}, {194914, 18055683}, {194915, 18055939},
2671 	{194916, 18056195}, {194917, 18056451}, {194918, 18056707}, {194919, 18056963},
2672 	{194920, 18057219}, {194921, 18057475}, {194922, 18057731}, {194923, 18057987},
2673 	{194924, 18058243}, {194925, 18058499}, {194926, 18058755}, {194927, 18059011},
2674 	{194928, 18059267}, {194929, 18059523}, {194930, 18059779}, {194931, 18060035},
2675 	{194932, 18060291}, {194933, 18060547}, {194934, 18060803}, {194935, 18061059},
2676 	{194936, 18061315}, {194937, 18061571}, {194938, 17618435}, {194939, 18061827},
2677 	{194940, 18062083}, {194941, 18062339}, {194942, 18062595}, {194943, 18062851},
2678 	{194944, 18063107}, {194945, 18063363}, {194946, 18063619}, {194947, 18063875},
2679 	{194948, 18064131}, {194949, 18064387}, {194950, 18064643}, {194951, 18064899},
2680 	{194952, 18065155}, {194953, 18065411}, {194954, 18065667}, {194955, 18011651},
2681 	{194956, 18065923}, {194957, 18066179}, {194958, 18066435}, {194959, 18066691},
2682 	{194960, 18066947}, {194961, 18067203}, {194962, 18067459}, {194963, 18067715},
2683 	{194964, 18067971}, {194965, 18068227}, {194966, 18068483}, {194967, 18068739},
2684 	{194968, 17566979}, {194969, 18068995}, {194970, 18069251}, {194971, 18069507},
2685 	{194972, 18069763}, {194973, 18070019}, {194974, 18070275}, {194975, 17619203},
2686 	{194976, 18070531}, {194977, 18070787}, {194978, 18071043}, {194979, 18071299},
2687 	{194980, 18071555}, {194981, 18071811}, {194982, 18072067}, {194983, 18072323},
2688 	{194984, 18072579}, {194985, 18072835}, {194986, 18073091}, {194987, 18073347},
2689 	{194988, 18073603}, {194989, 18073859}, {194990, 18074115}, {194991, 18074371},
2690 	{194992, 18074627}, {194993, 18074883}, {194994, 18075139}, {194995, 18075395},
2691 	{194996, 17551875}, {194997, 18075651}, {194998, 18075907}, {194999, 18076163},
2692 	{195000, 18076419}, {195001, 18076675}, {195002, 18076931}, {195003, 17636355},
2693 	{195004, 18077187}, {195005, 18077443}, {195006, 18077699}, {195007, 2},
2694 	{195008, 18077955}, {195009, 18078211}, {195010, 18078467}, {195011, 18078723},
2695 	{195012, 17178627}, {195013, 18078979}, {195014, 18079235}, {195015, 18079491},
2696 	{195016, 18079747}, {195017, 18080003}, {195018, 18080259}, {195019, 18080515},
2697 	{195020, 18080771}, {195021, 18081027}, {195022, 18081283}, {195023, 18081539},
2698 	{195024, 17637635}, {195025, 17637891}, {195026, 17180419}, {195027, 18081795},
2699 	{195028, 18082051}, {195029, 18082307}, {195030, 18082563}, {195031, 18082819},
2700 	{195032, 18083075}, {195033, 18083331}, {195034, 18083587}, {195035, 18083843},
2701 	{195036, 18084099}, {195037, 18084355}, {195038, 18084611}, {195039, 17638147},
2702 	{195040, 18084867}, {195041, 18085123}, {195042, 18085379}, {195043, 18085635},
2703 	{195044, 18085891}, {195045, 18086147}, {195046, 18086403}, {195047, 18086659},
2704 	{195048, 18086915}, {195049, 18087171}, {195050, 18087427}, {195051, 18087683},
2705 	{195052, 18087939}, {195053, 18088195}, {195054, 18088451}, {195055, 18088707},
2706 	{195056, 18088963}, {195057, 18089219}, {195058, 18089475}, {195059, 18089731},
2707 	{195060, 18089987}, {195061, 18090243}, {195062, 18090499}, {195063, 18090755},
2708 	{195064, 18091011}, {195065, 18091267}, {195066, 18091523}, {195067, 18091779},
2709 	{195068, 18092035}, {195069, 18092291}, {195070, 17639683}, {195072, 18092547},
2710 	{195073, 18092803}, {195074, 18093059}, {195075, 18093315}, {195076, 18093571},
2711 	{195077, 18093827}, {195078, 18094083}, {195079, 18094339}, {195080, 18094595},
2712 	{195081, 18094851}, {195082, 17639939}, {195083, 18095107}, {195084, 18095363},
2713 	{195085, 18095619}, {195086, 18095875}, {195087, 18096131}, {195088, 18096387},
2714 	{195089, 18096643}, {195090, 18096899}, {195091, 18097155}, {195092, 18097411},
2715 	{195093, 17192707}, {195094, 18097667}, {195095, 17193731}, {195096, 18097923},
2716 	{195097, 18098179}, {195098, 18098435}, {195099, 18098691}, {195100, 17195011},
2717 	{195101, 18098947}, {195102, 2}, {196608, 1}, {201547, 2},
2718 	{201552, 1}, {205744, 2}, {917760, 0}, {918000, 2}
2719 };
2720 
2721 
2722 } // namespace ada::idna
2723 #endif // ADA_IDNA_TABLES_H
2724 
2725 /* end file src/mapping_tables.cpp */
2726 
2727 namespace ada::idna {
2728 
2729 // This can be greatly accelerated. For now we just use a simply
2730 // binary search. In practice, you should *not* do that.
find_range_index(uint32_t key)2731 uint32_t find_range_index(uint32_t key) {
2732   ////////////////
2733   // This could be implemented with std::lower_bound, but we roll our own
2734   // because we want to allow further optimizations in the future.
2735   ////////////////
2736   uint32_t len = std::size(table);
2737   uint32_t low = 0;
2738   uint32_t high = len - 1;
2739   while (low <= high) {
2740     uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2741     uint32_t middle_value = table[middle_index][0];
2742     if (middle_value < key) {
2743       low = middle_index + 1;
2744     } else if (middle_value > key) {
2745       high = middle_index - 1;
2746     } else {
2747       return middle_index;  // perfect match
2748     }
2749   }
2750   return low == 0 ? 0 : low - 1;
2751 }
2752 
ascii_has_upper_case(char * input,size_t length)2753 bool ascii_has_upper_case(char* input, size_t length) {
2754   auto broadcast = [](uint8_t v) -> uint64_t {
2755     return 0x101010101010101ull * v;
2756   };
2757   uint64_t broadcast_80 = broadcast(0x80);
2758   uint64_t broadcast_Ap = broadcast(128 - 'A');
2759   uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2760   size_t i = 0;
2761 
2762   uint64_t runner{0};
2763 
2764   for (; i + 7 < length; i += 8) {
2765     uint64_t word{};
2766     memcpy(&word, input + i, sizeof(word));
2767     runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2768   }
2769   if (i < length) {
2770     uint64_t word{};
2771     memcpy(&word, input + i, length - i);
2772     runner |= (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80);
2773   }
2774   return runner != 0;
2775 }
2776 
ascii_map(char * input,size_t length)2777 void ascii_map(char* input, size_t length) {
2778   auto broadcast = [](uint8_t v) -> uint64_t {
2779     return 0x101010101010101ull * v;
2780   };
2781   uint64_t broadcast_80 = broadcast(0x80);
2782   uint64_t broadcast_Ap = broadcast(128 - 'A');
2783   uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2784   size_t i = 0;
2785 
2786   for (; i + 7 < length; i += 8) {
2787     uint64_t word{};
2788     memcpy(&word, input + i, sizeof(word));
2789     word ^=
2790         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2791     memcpy(input + i, &word, sizeof(word));
2792   }
2793   if (i < length) {
2794     uint64_t word{};
2795     memcpy(&word, input + i, length - i);
2796     word ^=
2797         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2798     memcpy(input + i, &word, length - i);
2799   }
2800 }
2801 
2802 // Map the characters according to IDNA, returning the empty string on error.
map(std::u32string_view input)2803 std::u32string map(std::u32string_view input) {
2804   //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2805   //  For each code point in the domain_name string, look up the status
2806   //  value in Section 5, [IDNA Mapping
2807   //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2808   //  and take the following actions:
2809   //    * disallowed: Leave the code point unchanged in the string, and
2810   //    record that there was an error.
2811   //    * ignored: Remove the code point from the string. This is
2812   //    equivalent to mapping the code point to an empty string.
2813   //    * mapped: Replace the code point in the string by the value for
2814   //    the mapping in Section 5, [IDNA Mapping
2815   //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2816   //    * valid: Leave the code point unchanged in the string.
2817   static std::u32string error = U"";
2818   std::u32string answer;
2819   answer.reserve(input.size());
2820   for (char32_t x : input) {
2821     size_t index = find_range_index(x);
2822     uint32_t descriptor = table[index][1];
2823     uint8_t code = uint8_t(descriptor);
2824     switch (code) {
2825       case 0:
2826         break;  // nothing to do, ignored
2827       case 1:
2828         answer.push_back(x);  // valid, we just copy it to output
2829         break;
2830       case 2:
2831         return error;  // disallowed
2832       // case 3 :
2833       default:
2834         // We have a mapping
2835         {
2836           size_t char_count = (descriptor >> 24);
2837           uint16_t char_index = uint16_t(descriptor >> 8);
2838           for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2839             answer.push_back(mappings[idx]);
2840           }
2841         }
2842     }
2843   }
2844   return answer;
2845 }
2846 }  // namespace ada::idna
2847 /* end file src/mapping.cpp */
2848 /* begin file src/normalization.cpp */
2849 /* begin file src/normalization_tables.cpp */
2850 // IDNA  15.0.0
2851 
2852 // clang-format off
2853 #ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2854 #define ADA_IDNA_NORMALIZATION_TABLES_H
2855 #include <cstdint>
2856 
2857 /**
2858  * Unicode Standard Annex #15
2859  *
2860  * UNICODE NORMALIZATION FORMS
2861  * https://www.unicode.org/reports/tr15/
2862  *
2863  * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2864  */
2865 
2866 namespace ada::idna {
2867 
2868 const uint8_t decomposition_index[4352] = {
2869     0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2870     7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2871     7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2872     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2873     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  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,  34, 35, 7,  7,  7,
2878     36, 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,  7,  7,  7,  7,  7,
2880     7,  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,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2883     7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2884     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2885     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  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,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2894     7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2895     59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2896     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2897     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  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     64, 65, 66, 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     7,  7,  7,  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};
3099 
3100 const uint16_t decomposition_block[67][257] = {
3101     {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3102      4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
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,   5,   8,   8,   8,   8,
3112      8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3113      37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3114      124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3115      228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3116      316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3117      428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3118      516, 524},
3119     {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3120      620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3121      700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3122      796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3123      876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3124      956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3125      1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3126      1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3127      1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3128      1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3129      1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3130      1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3131      1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3132      1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3133      1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3134      1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3135      1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3136      1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3137      1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3138      1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3139      1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3140      1948, 1956, 1964, 1972, 1980},
3141     {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3142      2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3143      2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3144      2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3145      2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3146      2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3147      2356, 2356, 2356, 2356, 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, 2357, 2361, 2365, 2369,
3156      2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3157      2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3158      2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3159      2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3160      2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3161      2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3162      2460, 2460, 2460, 2460, 2460},
3163     {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3164      2460, 2460, 2460, 2460, 2460, 2460, 2460, 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, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3169      2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3170      2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 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, 2484, 2484, 2484,
3173      2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3174      2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3175      2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3176      2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3177      2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3178      2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3179      2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3180      2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3181      2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3182      2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3183      2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3184      2744, 2744, 2744, 2744, 2744},
3185     {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3186      2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3187      2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3188      2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3189      2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3190      2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3191      2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3192      2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3193      2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3194      2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3195      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3196      2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
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, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3202      2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3203      2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3204      3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3205      3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3206      3160, 3160, 3160, 3160, 3160},
3207     {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3208      3160, 3160, 3160, 3160, 3160, 3160, 3160, 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, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3219      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3220      3168, 3168, 3168, 3168, 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},
3229     {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3230      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3231      3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3232      3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3233      3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3234      3208, 3208, 3208, 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, 3209, 3217, 3225,
3239      3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3240      3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3241      3240, 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, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3246      3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3247      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3248      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3249      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3250      3264, 3264, 3264, 3264, 3264},
3251     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3252      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
3262     {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3263      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3264      3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3265      3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3266      3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3267      3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3268      3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3269      3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3270      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3271      3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
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      3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3280      3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3281      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3282      3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3283      3392, 3392, 3392, 3392, 3392},
3284     {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3285      3392, 3392, 3392, 3392, 3392, 3392, 3392, 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, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3289      3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3290      3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3291      3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3292      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3293      3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 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},
3306     {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3307      3440, 3440, 3440, 3440, 3440, 3440, 3440, 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, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3313      3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3314      3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3315      3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 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, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3319      3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3320      3488, 3488, 3488, 3488, 3488, 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, 3496,
3323      3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3324      3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3325      3512, 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},
3328     {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3329      3512, 3512, 3512, 3512, 3512, 3512, 3512, 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, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3335      3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3336      3520, 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, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3345      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3346      3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
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},
3350     {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3351      3564, 3564, 3564, 3564, 3564, 3564, 3564, 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, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3357      3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3358      3588, 3588, 3588, 3588, 3588, 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, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3369      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3370      3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3371      3624, 3624, 3624, 3624, 3624},
3372     {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3373      3624, 3624, 3624, 3624, 3624, 3624, 3624, 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, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3377      3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3378      3632, 3632, 3632, 3632, 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, 3633,
3387      3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3388      3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3389      3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3390      3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3391      3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3392      3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3393      3656, 3656, 3656, 3656, 3656},
3394     {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3395      3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3396      3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3397      3660, 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, 3668, 3668, 3668, 3668,
3400      3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3401      3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3402      3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3403      3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3404      3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3405      3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3406      3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3407      3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3408      3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3409      3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3410      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3411      3820, 3820, 3820, 3820, 3820, 3820, 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},
3416     {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3417      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3418      3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3419      3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3420      3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3421      3828, 3828, 3828, 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      3829, 3832, 3832, 3832, 3832},
3438     {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3439      3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3440      3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3441      3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3442      3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3443      3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3444      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3445      3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 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},
3460     {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3461      3920, 3920, 3920, 3920, 3920, 3920, 3920, 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, 3921, 3925, 3929, 3932,
3464      3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3465      3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3466      4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3467      4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3468      4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3469      4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3470      4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3471      4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3472      4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3473      4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3474      4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3475      4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3476      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3477      4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
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},
3482     {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3483      4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3484      4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3485      4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3486      4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3487      4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3488      4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3489      5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3490      5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3491      5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3492      5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3493      5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3494      5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3495      5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3496      5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3497      5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3498      6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3499      6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3500      6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3501      6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3502      6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3503      6648, 6648, 6648, 6648, 6648},
3504     {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3505      6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3506      6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3507      6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3508      7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3509      7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3510      7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3511      7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3512      7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3513      7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3514      7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3515      7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3516      8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3517      8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3518      8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3519      8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3520      8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3521      8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3522      8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3523      8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3524      9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3525      9168, 9178, 9181, 9188, 9190},
3526     {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3527      9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3528      9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3529      9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3530      9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3531      9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3532      9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3533      9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3534      9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3535      9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3536      9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3537      9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3538      9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3539      9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3540      9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3541      9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3542      9548, 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, 9549},
3548     {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3549      9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3550      9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3551      9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3552      9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3553      9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3554      9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3555      9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3556      9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3557      9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3558      10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3559      10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3560      10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3561      10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3562      10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3563      10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3564      10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3565      10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3566      10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3567      10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3568      10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3569      10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3570      10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 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},
3574     {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3575      10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3576      10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3577      10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3578      10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3579      10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3580      10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3581      10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3582      10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3583      10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3584      10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3585      10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3586      10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3587      10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3588      10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3589      10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3590      10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3591      10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3592      10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3593      10616, 10616, 10616, 10616, 10616, 10616, 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, 10624, 10632, 10640, 10648, 10648,
3597      10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3598      10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3599      10680, 10680, 10680, 10680, 10680, 10680, 10680},
3600     {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3601      10680, 10680, 10680, 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, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3605      10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3606      10688, 10688, 10688, 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},
3626     {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3627      10688, 10688, 10688, 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, 10689, 10693, 10697, 10701,
3636      10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3637      10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3638      10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3639      11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3640      11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3641      11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3642      11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3643      11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3644      11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3645      11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3646      11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3647      11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3648      11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3649      11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3650      11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3651      11824, 11824, 11824, 11824, 11824, 11824, 11824},
3652     {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3653      11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3654      11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3655      11840, 11840, 11840, 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, 11841, 11853, 11861, 11872,
3664      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3665      11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 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, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3675      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3676      11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3677      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, 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, 11881, 11885, 11888, 11888, 11888, 11888,
3691      11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3692      11888, 11888, 11888, 11888, 11888, 11888, 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},
3704     {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3705      11888, 11888, 11888, 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, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3716      11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3717      11892, 11892, 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},
3730     {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3731      11892, 11892, 11892, 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, 11893,
3746      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3747      11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
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, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3755      11900, 11900, 11900, 11900, 11900, 11900, 11901},
3756     {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3757      11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3758      11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3759      12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3760      12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3761      12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3762      12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3763      12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3764      12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3765      12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3766      12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3767      12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3768      12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3769      12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3770      12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3771      12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3772      12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3773      12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3774      12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3775      12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3776      12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3777      12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3778      12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3779      12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3780      12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3781      12756, 12756, 12756, 12756, 12756, 12756, 12757},
3782     {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3783      12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3784      12760, 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, 12761, 12764, 12765, 12769, 12773, 12776,
3788      12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3789      12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3790      12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3791      12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3792      12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3793      12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3794      12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3795      12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3796      12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3797      12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3798      13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3799      13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3800      13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3801      13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3802      13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3803      13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3804      13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3805      13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3806      13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3807      13248, 13256, 13256, 13256, 13256, 13265, 13272},
3808     {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3809      13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 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, 13273,
3813      13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3814      13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3815      13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3816      13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3817      13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3818      13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3819      13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3820      13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3821      13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3822      13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3823      13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3824      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3825      13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
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, 13705},
3834     {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3835      13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3836      13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3837      14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3838      14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3839      14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3840      14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3841      14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3842      14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3843      14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3844      14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3845      14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3846      14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3847      14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3848      15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3849      15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3850      15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3851      15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3852      15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3853      15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3854      15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3855      15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3856      15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3857      15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3858      15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3859      15589, 15593, 15597, 15601, 15605, 15609, 15617},
3860     {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3861      15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3862      15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3863      16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3864      16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3865      16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3866      16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3867      16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3868      16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3869      17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3870      17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3871      17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3872      17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3873      17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3874      17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3875      17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3876      17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3877      17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3878      17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3879      18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3880      18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3881      18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3882      18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3883      18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3884      18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3885      18617, 18629, 18641, 18653, 18665, 18677, 18688},
3886     {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3887      18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 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, 18689, 18693, 18696, 18696,
3902      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3903      18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 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},
3912     {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3913      18696, 18696, 18696, 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, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3924      18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3925      18700, 18700, 18700, 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, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3937      18720, 18720, 18720, 18720, 18720, 18720, 18720},
3938     {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3939      18720, 18720, 18720, 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, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3948      18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3949      18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3950      18740, 18740, 18740, 18740, 18740, 18740, 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},
3964     {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3965      18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3966      18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3967      18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3968      18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3969      18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3970      18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3971      19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3972      19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3973      19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3974      19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3975      19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
3976      19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
3977      19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
3978      19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
3979      19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
3980      19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
3981      19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
3982      19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
3983      19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
3984      19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
3985      19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
3986      19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
3987      19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
3988      19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
3989      19740, 19744, 19748, 19752, 19756, 19760, 19764},
3990     {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
3991      19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
3992      19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
3993      19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
3994      19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
3995      19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
3996      19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
3997      19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
3998      20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
3999      20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4000      20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4001      20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4002      20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4003      20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4004      20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4005      20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4006      20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4007      20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4008      20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4009      20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4010      20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4011      20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4012      20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4013      20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4014      20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4015      20580, 20580, 20580, 20580, 20580, 20580, 20581},
4016     {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4017      20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4018      20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4019      20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4020      20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4021      20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4022      20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4023      20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4024      21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4025      21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4026      21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4027      21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4028      21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4029      21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4030      21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4031      21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4032      21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4033      21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4034      21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4035      21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4036      21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4037      21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4038      21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4039      21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4040      21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4041      21709, 21721, 21733, 21737, 21741, 21745, 21749},
4042     {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4043      21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4044      21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4045      22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4046      22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4047      22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4048      22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4049      22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4050      22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4051      22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4052      22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4053      22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4054      22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4055      22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4056      22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4057      23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4058      23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4059      23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4060      23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4061      23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4062      23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4063      23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4064      23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4065      23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4066      23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4067      23857, 23865, 23873, 23881, 23889, 23897, 23905},
4068     {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4069      23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4070      24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4071      24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4072      24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4073      24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4074      24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4075      24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4076      24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4077      24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4078      24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4079      24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4080      24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4081      25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4082      25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4083      25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4084      25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4085      25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4086      25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4087      25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4088      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4089      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4090      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4091      25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4092      25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4093      25965, 26037, 26069, 26084, 26084, 26084, 26084},
4094     {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4095      26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4096      26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4097      26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4098      26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4099      26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4100      26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4101      26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4102      26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4103      26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4104      26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4105      26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4106      26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4107      26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4108      26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4109      26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4110      26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4111      26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4112      26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4113      26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4114      26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4115      26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4116      26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4117      26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4118      26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4119      27065, 27077, 27085, 27092, 27092, 27092, 27092},
4120     {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4121      27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4122      27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4123      27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4124      27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4125      27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4126      27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4127      27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4128      27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4129      27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4130      27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4131      27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4132      27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4133      27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4134      27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4135      27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4136      27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4137      27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4138      27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4139      27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4140      27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4141      27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4142      27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4143      27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4144      27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4145      27996, 27996, 27996, 27996, 27996, 27996, 27996},
4146     {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4147      27996, 27996, 27996, 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, 27997,
4159      28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4160      28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4161      28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4162      28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4163      28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4164      28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4165      28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4166      28220, 28220, 28220, 28220, 28220, 28220, 28220, 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},
4172     {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4173      28220, 28220, 28220, 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, 28228, 28228, 28236, 28236, 28236,
4188      28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4189      28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4190      28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4191      28244, 28244, 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},
4198     {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4199      28244, 28244, 28244, 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, 28252, 28260, 28260,
4203      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4204      28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 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},
4224     {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4225      28260, 28260, 28260, 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, 28268, 28276, 28276, 28276,
4232      28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4233      28276, 28276, 28276, 28276, 28276, 28276, 28276, 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},
4250     {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4251      28276, 28276, 28276, 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, 28284, 28292,
4269      28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4270      28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4271      28300, 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},
4276     {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4277      28300, 28300, 28300, 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, 28308, 28316, 28316,
4295      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4296      28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 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},
4302     {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4303      28316, 28316, 28316, 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, 28324, 28324, 28324,
4308      28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4309      28324, 28324, 28324, 28324, 28324, 28324, 28324, 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},
4328     {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4329      28324, 28324, 28324, 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, 28332, 28340, 28352, 28364, 28376,
4338      28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4339      28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4340      28400, 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, 28408, 28416,
4347      28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4348      28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4349      28464, 28464, 28464, 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},
4354     {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4355      28464, 28464, 28464, 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, 28465},
4380     {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4381      28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4382      28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4383      28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4384      28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4385      28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4386      28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4387      28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4388      28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4389      28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4390      28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4391      28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4392      28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4393      28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4394      29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4395      29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4396      29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4397      29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4398      29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4399      29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4400      29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4401      29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4402      29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4403      29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4404      29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4405      29417, 29421, 29425, 29429, 29433, 29437, 29441},
4406     {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4407      29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4408      29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4409      29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4410      29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4411      29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4412      29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4413      29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4414      29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4415      29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4416      29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4417      29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4418      29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4419      29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4420      29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4421      29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4422      30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4423      30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4424      30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4425      30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4426      30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4427      30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4428      30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4429      30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4430      30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4431      30393, 30397, 30401, 30405, 30409, 30413, 30417},
4432     {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4433      30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4434      30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4435      30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4436      30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4437      30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4438      30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4439      30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4440      30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4441      30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4442      30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4443      30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4444      30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4445      30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4446      30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4447      31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4448      31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4449      31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4450      31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4451      31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4452      31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4453      31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4454      31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4455      31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4456      31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4457      31409, 31413, 31417, 31421, 31425, 31429, 31433},
4458     {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4459      31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4460      31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4461      31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4462      31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4463      31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4464      31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4465      31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4466      31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4467      31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4468      31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4469      31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4470      31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4471      31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4472      31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4473      32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4474      32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4475      32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4476      32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4477      32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4478      32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4479      32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4480      32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4481      32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4482      32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4483      32425, 32429, 32433, 32437, 32441, 32445, 32448},
4484     {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4485      32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 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, 32449, 32453,
4489      32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4490      32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4491      32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4492      32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4493      32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4494      32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4495      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4496      32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
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},
4510     {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4511      32696, 32696, 32696, 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, 32697},
4536     {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4537      32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4538      32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4539      32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4540      32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4541      32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4542      32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4543      32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4544      32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4545      32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4546      32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4547      32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4548      33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4549      33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4550      33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4551      33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4552      33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4553      33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4554      33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4555      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4556      33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 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},
4562     {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4563      33260, 33260, 33260, 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, 33261},
4588     {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4589      33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4590      33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4591      33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4592      33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4593      33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4594      33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4595      33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4596      33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4597      33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4598      33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4599      33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4600      33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4601      33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4602      33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4603      33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4604      33884, 33884, 33884, 33884, 33884, 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, 33885},
4614     {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4615      33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4616      33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4617      33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4618      34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4619      34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4620      34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4621      34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4622      34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4623      34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4624      34200, 34200, 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},
4640     {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4641      34200, 34200, 34200, 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      34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4665      34240, 34240, 34240, 34240, 34240, 34240, 34240},
4666     {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4667      34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4668      34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4669      34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4670      34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4671      34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4672      34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4673      34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4674      34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4675      34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4676      34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4677      34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4678      34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4679      34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4680      34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4681      34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4682      34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4683      34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4684      34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4685      35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4686      35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4687      35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4688      35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4689      35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4690      35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4691      35240, 35244, 35248, 35252, 35256, 35260, 35264},
4692     {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4693      35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4694      35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4695      35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4696      35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4697      35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4698      35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4699      35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4700      35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4701      35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4702      35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4703      35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4704      35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4705      35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4706      35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4707      35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4708      35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4709      35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4710      35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4711      36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4712      36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4713      36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4714      36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4715      36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4716      36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4717      36264, 36268, 36272, 36276, 36280, 36284, 36288},
4718     {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4719      36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4720      36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4721      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4722      36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
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}};
4744 const char32_t decomposition_data[9102] = {
4745     0,      32,     32,     776,    97,     32,     772,    50,     51,
4746     32,     769,    956,    32,     807,    49,     111,    49,     8260,
4747     52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4748     65,     769,    65,     770,    65,     771,    65,     776,    65,
4749     778,    67,     807,    69,     768,    69,     769,    69,     770,
4750     69,     776,    73,     768,    73,     769,    73,     770,    73,
4751     776,    78,     771,    79,     768,    79,     769,    79,     770,
4752     79,     771,    79,     776,    85,     768,    85,     769,    85,
4753     770,    85,     776,    89,     769,    97,     768,    97,     769,
4754     97,     770,    97,     771,    97,     776,    97,     778,    99,
4755     807,    101,    768,    101,    769,    101,    770,    101,    776,
4756     105,    768,    105,    769,    105,    770,    105,    776,    110,
4757     771,    111,    768,    111,    769,    111,    770,    111,    771,
4758     111,    776,    117,    768,    117,    769,    117,    770,    117,
4759     776,    121,    769,    121,    776,    65,     772,    97,     772,
4760     65,     774,    97,     774,    65,     808,    97,     808,    67,
4761     769,    99,     769,    67,     770,    99,     770,    67,     775,
4762     99,     775,    67,     780,    99,     780,    68,     780,    100,
4763     780,    69,     772,    101,    772,    69,     774,    101,    774,
4764     69,     775,    101,    775,    69,     808,    101,    808,    69,
4765     780,    101,    780,    71,     770,    103,    770,    71,     774,
4766     103,    774,    71,     775,    103,    775,    71,     807,    103,
4767     807,    72,     770,    104,    770,    73,     771,    105,    771,
4768     73,     772,    105,    772,    73,     774,    105,    774,    73,
4769     808,    105,    808,    73,     775,    73,     74,     105,    106,
4770     74,     770,    106,    770,    75,     807,    107,    807,    76,
4771     769,    108,    769,    76,     807,    108,    807,    76,     780,
4772     108,    780,    76,     183,    108,    183,    78,     769,    110,
4773     769,    78,     807,    110,    807,    78,     780,    110,    780,
4774     700,    110,    79,     772,    111,    772,    79,     774,    111,
4775     774,    79,     779,    111,    779,    82,     769,    114,    769,
4776     82,     807,    114,    807,    82,     780,    114,    780,    83,
4777     769,    115,    769,    83,     770,    115,    770,    83,     807,
4778     115,    807,    83,     780,    115,    780,    84,     807,    116,
4779     807,    84,     780,    116,    780,    85,     771,    117,    771,
4780     85,     772,    117,    772,    85,     774,    117,    774,    85,
4781     778,    117,    778,    85,     779,    117,    779,    85,     808,
4782     117,    808,    87,     770,    119,    770,    89,     770,    121,
4783     770,    89,     776,    90,     769,    122,    769,    90,     775,
4784     122,    775,    90,     780,    122,    780,    115,    79,     795,
4785     111,    795,    85,     795,    117,    795,    68,     90,     780,
4786     68,     122,    780,    100,    122,    780,    76,     74,     76,
4787     106,    108,    106,    78,     74,     78,     106,    110,    106,
4788     65,     780,    97,     780,    73,     780,    105,    780,    79,
4789     780,    111,    780,    85,     780,    117,    780,    85,     776,
4790     772,    117,    776,    772,    85,     776,    769,    117,    776,
4791     769,    85,     776,    780,    117,    776,    780,    85,     776,
4792     768,    117,    776,    768,    65,     776,    772,    97,     776,
4793     772,    65,     775,    772,    97,     775,    772,    198,    772,
4794     230,    772,    71,     780,    103,    780,    75,     780,    107,
4795     780,    79,     808,    111,    808,    79,     808,    772,    111,
4796     808,    772,    439,    780,    658,    780,    106,    780,    68,
4797     90,     68,     122,    100,    122,    71,     769,    103,    769,
4798     78,     768,    110,    768,    65,     778,    769,    97,     778,
4799     769,    198,    769,    230,    769,    216,    769,    248,    769,
4800     65,     783,    97,     783,    65,     785,    97,     785,    69,
4801     783,    101,    783,    69,     785,    101,    785,    73,     783,
4802     105,    783,    73,     785,    105,    785,    79,     783,    111,
4803     783,    79,     785,    111,    785,    82,     783,    114,    783,
4804     82,     785,    114,    785,    85,     783,    117,    783,    85,
4805     785,    117,    785,    83,     806,    115,    806,    84,     806,
4806     116,    806,    72,     780,    104,    780,    65,     775,    97,
4807     775,    69,     807,    101,    807,    79,     776,    772,    111,
4808     776,    772,    79,     771,    772,    111,    771,    772,    79,
4809     775,    111,    775,    79,     775,    772,    111,    775,    772,
4810     89,     772,    121,    772,    104,    614,    106,    114,    633,
4811     635,    641,    119,    121,    32,     774,    32,     775,    32,
4812     778,    32,     808,    32,     771,    32,     779,    611,    108,
4813     115,    120,    661,    768,    769,    787,    776,    769,    697,
4814     32,     837,    59,     32,     769,    168,    769,    913,    769,
4815     183,    917,    769,    919,    769,    921,    769,    927,    769,
4816     933,    769,    937,    769,    953,    776,    769,    921,    776,
4817     933,    776,    945,    769,    949,    769,    951,    769,    953,
4818     769,    965,    776,    769,    953,    776,    965,    776,    959,
4819     769,    965,    769,    969,    769,    946,    952,    933,    978,
4820     769,    978,    776,    966,    960,    954,    961,    962,    920,
4821     949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4822     776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4823     1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4824     776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4825     1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4826     774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4827     1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4828     776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4829     1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4830     776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4831     1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4832     776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4833     1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4834     1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4835     1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4836     2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4837     2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4838     2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4839     2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4840     2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4841     2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4842     3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4843     3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4844     3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4845     3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4846     3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4847     4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4848     3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4849     4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4850     3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4851     4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4852     6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4853     6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4854     198,    66,     68,     69,     398,    71,     72,     73,     74,
4855     75,     76,     77,     78,     79,     546,    80,     82,     84,
4856     85,     87,     97,     592,    593,    7426,   98,     100,    101,
4857     601,    603,    604,    103,    107,    109,    331,    111,    596,
4858     7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4859     946,    947,    948,    966,    967,    105,    114,    117,    118,
4860     946,    947,    961,    966,    967,    1085,   594,    99,     597,
4861     240,    604,    102,    607,    609,    613,    616,    617,    618,
4862     7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4863     628,    629,    632,    642,    643,    427,    649,    650,    7452,
4864     651,    652,    122,    656,    657,    658,    952,    65,     805,
4865     97,     805,    66,     775,    98,     775,    66,     803,    98,
4866     803,    66,     817,    98,     817,    67,     807,    769,    99,
4867     807,    769,    68,     775,    100,    775,    68,     803,    100,
4868     803,    68,     817,    100,    817,    68,     807,    100,    807,
4869     68,     813,    100,    813,    69,     772,    768,    101,    772,
4870     768,    69,     772,    769,    101,    772,    769,    69,     813,
4871     101,    813,    69,     816,    101,    816,    69,     807,    774,
4872     101,    807,    774,    70,     775,    102,    775,    71,     772,
4873     103,    772,    72,     775,    104,    775,    72,     803,    104,
4874     803,    72,     776,    104,    776,    72,     807,    104,    807,
4875     72,     814,    104,    814,    73,     816,    105,    816,    73,
4876     776,    769,    105,    776,    769,    75,     769,    107,    769,
4877     75,     803,    107,    803,    75,     817,    107,    817,    76,
4878     803,    108,    803,    76,     803,    772,    108,    803,    772,
4879     76,     817,    108,    817,    76,     813,    108,    813,    77,
4880     769,    109,    769,    77,     775,    109,    775,    77,     803,
4881     109,    803,    78,     775,    110,    775,    78,     803,    110,
4882     803,    78,     817,    110,    817,    78,     813,    110,    813,
4883     79,     771,    769,    111,    771,    769,    79,     771,    776,
4884     111,    771,    776,    79,     772,    768,    111,    772,    768,
4885     79,     772,    769,    111,    772,    769,    80,     769,    112,
4886     769,    80,     775,    112,    775,    82,     775,    114,    775,
4887     82,     803,    114,    803,    82,     803,    772,    114,    803,
4888     772,    82,     817,    114,    817,    83,     775,    115,    775,
4889     83,     803,    115,    803,    83,     769,    775,    115,    769,
4890     775,    83,     780,    775,    115,    780,    775,    83,     803,
4891     775,    115,    803,    775,    84,     775,    116,    775,    84,
4892     803,    116,    803,    84,     817,    116,    817,    84,     813,
4893     116,    813,    85,     804,    117,    804,    85,     816,    117,
4894     816,    85,     813,    117,    813,    85,     771,    769,    117,
4895     771,    769,    85,     772,    776,    117,    772,    776,    86,
4896     771,    118,    771,    86,     803,    118,    803,    87,     768,
4897     119,    768,    87,     769,    119,    769,    87,     776,    119,
4898     776,    87,     775,    119,    775,    87,     803,    119,    803,
4899     88,     775,    120,    775,    88,     776,    120,    776,    89,
4900     775,    121,    775,    90,     770,    122,    770,    90,     803,
4901     122,    803,    90,     817,    122,    817,    104,    817,    116,
4902     776,    119,    778,    121,    778,    97,     702,    383,    775,
4903     65,     803,    97,     803,    65,     777,    97,     777,    65,
4904     770,    769,    97,     770,    769,    65,     770,    768,    97,
4905     770,    768,    65,     770,    777,    97,     770,    777,    65,
4906     770,    771,    97,     770,    771,    65,     803,    770,    97,
4907     803,    770,    65,     774,    769,    97,     774,    769,    65,
4908     774,    768,    97,     774,    768,    65,     774,    777,    97,
4909     774,    777,    65,     774,    771,    97,     774,    771,    65,
4910     803,    774,    97,     803,    774,    69,     803,    101,    803,
4911     69,     777,    101,    777,    69,     771,    101,    771,    69,
4912     770,    769,    101,    770,    769,    69,     770,    768,    101,
4913     770,    768,    69,     770,    777,    101,    770,    777,    69,
4914     770,    771,    101,    770,    771,    69,     803,    770,    101,
4915     803,    770,    73,     777,    105,    777,    73,     803,    105,
4916     803,    79,     803,    111,    803,    79,     777,    111,    777,
4917     79,     770,    769,    111,    770,    769,    79,     770,    768,
4918     111,    770,    768,    79,     770,    777,    111,    770,    777,
4919     79,     770,    771,    111,    770,    771,    79,     803,    770,
4920     111,    803,    770,    79,     795,    769,    111,    795,    769,
4921     79,     795,    768,    111,    795,    768,    79,     795,    777,
4922     111,    795,    777,    79,     795,    771,    111,    795,    771,
4923     79,     795,    803,    111,    795,    803,    85,     803,    117,
4924     803,    85,     777,    117,    777,    85,     795,    769,    117,
4925     795,    769,    85,     795,    768,    117,    795,    768,    85,
4926     795,    777,    117,    795,    777,    85,     795,    771,    117,
4927     795,    771,    85,     795,    803,    117,    795,    803,    89,
4928     768,    121,    768,    89,     803,    121,    803,    89,     777,
4929     121,    777,    89,     771,    121,    771,    945,    787,    945,
4930     788,    945,    787,    768,    945,    788,    768,    945,    787,
4931     769,    945,    788,    769,    945,    787,    834,    945,    788,
4932     834,    913,    787,    913,    788,    913,    787,    768,    913,
4933     788,    768,    913,    787,    769,    913,    788,    769,    913,
4934     787,    834,    913,    788,    834,    949,    787,    949,    788,
4935     949,    787,    768,    949,    788,    768,    949,    787,    769,
4936     949,    788,    769,    917,    787,    917,    788,    917,    787,
4937     768,    917,    788,    768,    917,    787,    769,    917,    788,
4938     769,    951,    787,    951,    788,    951,    787,    768,    951,
4939     788,    768,    951,    787,    769,    951,    788,    769,    951,
4940     787,    834,    951,    788,    834,    919,    787,    919,    788,
4941     919,    787,    768,    919,    788,    768,    919,    787,    769,
4942     919,    788,    769,    919,    787,    834,    919,    788,    834,
4943     953,    787,    953,    788,    953,    787,    768,    953,    788,
4944     768,    953,    787,    769,    953,    788,    769,    953,    787,
4945     834,    953,    788,    834,    921,    787,    921,    788,    921,
4946     787,    768,    921,    788,    768,    921,    787,    769,    921,
4947     788,    769,    921,    787,    834,    921,    788,    834,    959,
4948     787,    959,    788,    959,    787,    768,    959,    788,    768,
4949     959,    787,    769,    959,    788,    769,    927,    787,    927,
4950     788,    927,    787,    768,    927,    788,    768,    927,    787,
4951     769,    927,    788,    769,    965,    787,    965,    788,    965,
4952     787,    768,    965,    788,    768,    965,    787,    769,    965,
4953     788,    769,    965,    787,    834,    965,    788,    834,    933,
4954     788,    933,    788,    768,    933,    788,    769,    933,    788,
4955     834,    969,    787,    969,    788,    969,    787,    768,    969,
4956     788,    768,    969,    787,    769,    969,    788,    769,    969,
4957     787,    834,    969,    788,    834,    937,    787,    937,    788,
4958     937,    787,    768,    937,    788,    768,    937,    787,    769,
4959     937,    788,    769,    937,    787,    834,    937,    788,    834,
4960     945,    768,    945,    769,    949,    768,    949,    769,    951,
4961     768,    951,    769,    953,    768,    953,    769,    959,    768,
4962     959,    769,    965,    768,    965,    769,    969,    768,    969,
4963     769,    945,    787,    837,    945,    788,    837,    945,    787,
4964     768,    837,    945,    788,    768,    837,    945,    787,    769,
4965     837,    945,    788,    769,    837,    945,    787,    834,    837,
4966     945,    788,    834,    837,    913,    787,    837,    913,    788,
4967     837,    913,    787,    768,    837,    913,    788,    768,    837,
4968     913,    787,    769,    837,    913,    788,    769,    837,    913,
4969     787,    834,    837,    913,    788,    834,    837,    951,    787,
4970     837,    951,    788,    837,    951,    787,    768,    837,    951,
4971     788,    768,    837,    951,    787,    769,    837,    951,    788,
4972     769,    837,    951,    787,    834,    837,    951,    788,    834,
4973     837,    919,    787,    837,    919,    788,    837,    919,    787,
4974     768,    837,    919,    788,    768,    837,    919,    787,    769,
4975     837,    919,    788,    769,    837,    919,    787,    834,    837,
4976     919,    788,    834,    837,    969,    787,    837,    969,    788,
4977     837,    969,    787,    768,    837,    969,    788,    768,    837,
4978     969,    787,    769,    837,    969,    788,    769,    837,    969,
4979     787,    834,    837,    969,    788,    834,    837,    937,    787,
4980     837,    937,    788,    837,    937,    787,    768,    837,    937,
4981     788,    768,    837,    937,    787,    769,    837,    937,    788,
4982     769,    837,    937,    787,    834,    837,    937,    788,    834,
4983     837,    945,    774,    945,    772,    945,    768,    837,    945,
4984     837,    945,    769,    837,    945,    834,    945,    834,    837,
4985     913,    774,    913,    772,    913,    768,    913,    769,    913,
4986     837,    32,     787,    953,    32,     787,    32,     834,    168,
4987     834,    951,    768,    837,    951,    837,    951,    769,    837,
4988     951,    834,    951,    834,    837,    917,    768,    917,    769,
4989     919,    768,    919,    769,    919,    837,    8127,   768,    8127,
4990     769,    8127,   834,    953,    774,    953,    772,    953,    776,
4991     768,    953,    776,    769,    953,    834,    953,    776,    834,
4992     921,    774,    921,    772,    921,    768,    921,    769,    8190,
4993     768,    8190,   769,    8190,   834,    965,    774,    965,    772,
4994     965,    776,    768,    965,    776,    769,    961,    787,    961,
4995     788,    965,    834,    965,    776,    834,    933,    774,    933,
4996     772,    933,    768,    933,    769,    929,    788,    168,    768,
4997     168,    769,    96,     969,    768,    837,    969,    837,    969,
4998     769,    837,    969,    834,    969,    834,    837,    927,    768,
4999     927,    769,    937,    768,    937,    769,    937,    837,    180,
5000     32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5001     32,     32,     32,     32,     8208,   32,     819,    46,     46,
5002     46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5003     8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5004     773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5005     8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5006     56,     57,     43,     8722,   61,     40,     41,     110,    48,
5007     49,     50,     51,     52,     53,     54,     55,     56,     57,
5008     43,     8722,   61,     40,     41,     97,     101,    111,    120,
5009     601,    104,    107,    108,    109,    110,    112,    115,    116,
5010     82,     115,    97,     47,     99,     97,     47,     115,    67,
5011     176,    67,     99,     47,     111,    99,     47,     117,    400,
5012     176,    70,     103,    72,     72,     72,     104,    295,    73,
5013     73,     76,     108,    78,     78,     111,    80,     81,     82,
5014     82,     82,     83,     77,     84,     69,     76,     84,     77,
5015     90,     937,    90,     75,     65,     778,    66,     67,     101,
5016     69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5017     70,     65,     88,     960,    947,    915,    928,    8721,   68,
5018     100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5019     57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5020     8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5021     8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5022     8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5023     8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5024     73,     73,     73,     73,     73,     86,     86,     86,     73,
5025     86,     73,     73,     86,     73,     73,     73,     73,     88,
5026     88,     88,     73,     88,     73,     73,     76,     67,     68,
5027     77,     105,    105,    105,    105,    105,    105,    105,    118,
5028     118,    118,    105,    118,    105,    105,    118,    105,    105,
5029     105,    105,    120,    120,    120,    105,    120,    105,    105,
5030     108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5031     8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5032     824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5033     8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5034     8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5035     8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5036     824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5037     8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5038     824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5039     8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5040     824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5041     8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5042     50,     51,     52,     53,     54,     55,     56,     57,     49,
5043     48,     49,     49,     49,     50,     49,     51,     49,     52,
5044     49,     53,     49,     54,     49,     55,     49,     56,     49,
5045     57,     50,     48,     40,     49,     41,     40,     50,     41,
5046     40,     51,     41,     40,     52,     41,     40,     53,     41,
5047     40,     54,     41,     40,     55,     41,     40,     56,     41,
5048     40,     57,     41,     40,     49,     48,     41,     40,     49,
5049     49,     41,     40,     49,     50,     41,     40,     49,     51,
5050     41,     40,     49,     52,     41,     40,     49,     53,     41,
5051     40,     49,     54,     41,     40,     49,     55,     41,     40,
5052     49,     56,     41,     40,     49,     57,     41,     40,     50,
5053     48,     41,     49,     46,     50,     46,     51,     46,     52,
5054     46,     53,     46,     54,     46,     55,     46,     56,     46,
5055     57,     46,     49,     48,     46,     49,     49,     46,     49,
5056     50,     46,     49,     51,     46,     49,     52,     46,     49,
5057     53,     46,     49,     54,     46,     49,     55,     46,     49,
5058     56,     46,     49,     57,     46,     50,     48,     46,     40,
5059     97,     41,     40,     98,     41,     40,     99,     41,     40,
5060     100,    41,     40,     101,    41,     40,     102,    41,     40,
5061     103,    41,     40,     104,    41,     40,     105,    41,     40,
5062     106,    41,     40,     107,    41,     40,     108,    41,     40,
5063     109,    41,     40,     110,    41,     40,     111,    41,     40,
5064     112,    41,     40,     113,    41,     40,     114,    41,     40,
5065     115,    41,     40,     116,    41,     40,     117,    41,     40,
5066     118,    41,     40,     119,    41,     40,     120,    41,     40,
5067     121,    41,     40,     122,    41,     65,     66,     67,     68,
5068     69,     70,     71,     72,     73,     74,     75,     76,     77,
5069     78,     79,     80,     81,     82,     83,     84,     85,     86,
5070     87,     88,     89,     90,     97,     98,     99,     100,    101,
5071     102,    103,    104,    105,    106,    107,    108,    109,    110,
5072     111,    112,    113,    114,    115,    116,    117,    118,    119,
5073     120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5074     58,     61,     61,     61,     61,     61,     61,     10973,  824,
5075     106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5076     20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5077     20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5078     21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5079     22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5080     23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5081     24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5082     24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5083     26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5084     27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5085     28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5086     29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5087     30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5088     31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5089     32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5090     33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5091     33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5092     35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5093     36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5094     37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5095     38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5096     39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5097     39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5098     40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5099     40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5100     12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5101     12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5102     12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5103     12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5104     12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5105     12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5106     12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5107     12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5108     12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5109     12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5110     12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5111     12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5112     12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5113     12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5114     4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5115     4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5116     4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5117     4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5118     4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5119     4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5120     4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5121     4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5122     4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5123     4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5124     4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5125     20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5126     40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5127     40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5128     40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5129     40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5130     40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5131     4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5132     41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5133     40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5134     4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5135     4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5136     41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5137     40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5138     4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5139     41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5140     41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5141     41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5142     41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5143     41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5144     41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5145     41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5146     41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5147     41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5148     41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5149     41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5150     41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5151     84,     69,     50,     49,     50,     50,     50,     51,     50,
5152     52,     50,     53,     50,     54,     50,     55,     50,     56,
5153     50,     57,     51,     48,     51,     49,     51,     50,     51,
5154     51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5155     4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5156     4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5157     4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5158     4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5159     4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5160     4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5161     20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5162     37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5163     31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5164     38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5165     21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5166     54,     51,     55,     51,     56,     51,     57,     52,     48,
5167     52,     49,     52,     50,     52,     51,     52,     52,     52,
5168     53,     52,     54,     52,     55,     52,     56,     52,     57,
5169     53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5170     26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5171     57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5172     50,     26376,  72,     103,    101,    114,    103,    101,    86,
5173     76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5174     12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5175     12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5176     12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5177     12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5178     12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5179     12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5180     12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5181     12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5182     12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5183     12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5184     12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5185     12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5186     12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5187     12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5188     12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5189     12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5190     12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5191     12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5192     12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5193     12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5194     12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5195     12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5196     12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5197     12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5198     12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5199     12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5200     12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5201     12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5202     12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5203     12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5204     12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5205     12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5206     12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5207     12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5208     12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5209     12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5210     12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5211     12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5212     12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5213     12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5214     12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5215     12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5216     12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5217     12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5218     28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5219     55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5220     49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5221     49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5222     49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5223     50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5224     50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5225     100,    97,     65,     85,     98,     97,     114,    111,    86,
5226     112,    99,     100,    109,    100,    109,    50,     100,    109,
5227     51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5228     26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5229     65,     956,    65,     109,    65,     107,    65,     75,     66,
5230     77,     66,     71,     66,     99,     97,     108,    107,    99,
5231     97,     108,    112,    70,     110,    70,     956,    70,     956,
5232     103,    109,    103,    107,    103,    72,     122,    107,    72,
5233     122,    77,     72,     122,    71,     72,     122,    84,     72,
5234     122,    956,    108,    109,    108,    100,    108,    107,    108,
5235     102,    109,    110,    109,    956,    109,    109,    109,    99,
5236     109,    107,    109,    109,    109,    50,     99,     109,    50,
5237     109,    50,     107,    109,    50,     109,    109,    51,     99,
5238     109,    51,     109,    51,     107,    109,    51,     109,    8725,
5239     115,    109,    8725,   115,    50,     80,     97,     107,    80,
5240     97,     77,     80,     97,     71,     80,     97,     114,    97,
5241     100,    114,    97,     100,    8725,   115,    114,    97,     100,
5242     8725,   115,    50,     112,    115,    110,    115,    956,    115,
5243     109,    115,    112,    86,     110,    86,     956,    86,     109,
5244     86,     107,    86,     77,     86,     112,    87,     110,    87,
5245     956,    87,     109,    87,     107,    87,     77,     87,     107,
5246     937,    77,     937,    97,     46,     109,    46,     66,     113,
5247     99,     99,     99,     100,    67,     8725,   107,    103,    67,
5248     111,    46,     100,    66,     71,     121,    104,    97,     72,
5249     80,     105,    110,    75,     75,     75,     77,     107,    116,
5250     108,    109,    108,    110,    108,    111,    103,    108,    120,
5251     109,    98,     109,    105,    108,    109,    111,    108,    80,
5252     72,     112,    46,     109,    46,     80,     80,     77,     80,
5253     82,     115,    114,    83,     118,    87,     98,     86,     8725,
5254     109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5255     26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5256     56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5257     26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5258     26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5259     26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5260     26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5261     26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5262     26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5263     26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5264     108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5265     42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5266     28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5267     25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5268     28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5269     34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5270     24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5271     27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5272     40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5273     24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5274     27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5275     20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5276     20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5277     19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5278     27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5279     20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5280     24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5281     26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5282     29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5283     21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5284     31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5285     32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5286     38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5287     30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5288     27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5289     38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5290     38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5291     30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5292     29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5293     31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5294     20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5295     38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5296     30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5297     35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5298     20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5299     22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5300     26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5301     30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5302     31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5303     33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5304     36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5305     20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5306     21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5307     24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5308     25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5309     27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5310     29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5311     30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5312     32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5313     35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5314     36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5315     38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5316     16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5317     105,    102,    108,    102,    102,    105,    102,    102,    108,
5318     115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5319     1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5320     1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5321     43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5322     1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5323     1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5324     1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5325     1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5326     1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5327     1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5328     1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5329     1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5330     1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5331     1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5332     1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5333     1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5334     1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5335     1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5336     1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5337     1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5338     1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5339     1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5340     1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5341     1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5342     1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5343     1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5344     1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5345     1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5346     1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5347     1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5348     1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5349     1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5350     1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5351     1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5352     1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5353     1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5354     1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5355     1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5356     1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5357     1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5358     1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5359     1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5360     1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5361     1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5362     1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5363     1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5364     1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5365     1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5366     1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5367     1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5368     1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5369     1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5370     1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5371     1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5372     1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5373     1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5374     1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5375     1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5376     1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5377     1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5378     1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5379     1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5380     1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5381     1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5382     1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5383     1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5384     1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5385     1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5386     1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5387     1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5388     1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5389     1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5390     1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5391     1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5392     1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5393     1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5394     1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5395     1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5396     1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5397     1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5398     1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5399     1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5400     1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5401     1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5402     1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5403     1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5404     1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5405     1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5406     1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5407     1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5408     1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5409     1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5410     1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5411     1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5412     1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5413     1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5414     1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5415     1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5416     1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5417     1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5418     1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5419     1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5420     1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5421     1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5422     1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5423     1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5424     1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5425     1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5426     1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5427     1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5428     1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5429     1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5430     1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5431     1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5432     1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5433     1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5434     1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5435     1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5436     1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5437     1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5438     1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5439     1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5440     1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5441     1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5442     1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5443     1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5444     1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5445     1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5446     1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5447     1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5448     1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5449     1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5450     1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5451     1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5452     1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5453     1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5454     1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5455     1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5456     1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5457     1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5458     1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5459     1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5460     1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5461     1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5462     1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5463     1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5464     1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5465     1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5466     1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5467     1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5468     1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5469     1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5470     59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5471     46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5472     12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5473     12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5474     32,     773,    32,     773,    95,     95,     95,     44,     12289,
5475     46,     59,     58,     63,     33,     8212,   40,     41,     123,
5476     125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5477     62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5478     1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5479     32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5480     1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5481     1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5482     1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5483     1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5484     1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5485     1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5486     1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5487     1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5488     1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5489     1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5490     1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5491     1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5492     1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5493     1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5494     1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5495     1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5496     1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5497     1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5498     37,     38,     39,     40,     41,     42,     43,     44,     45,
5499     46,     47,     48,     49,     50,     51,     52,     53,     54,
5500     55,     56,     57,     58,     59,     60,     61,     62,     63,
5501     64,     65,     66,     67,     68,     69,     70,     71,     72,
5502     73,     74,     75,     76,     77,     78,     79,     80,     81,
5503     82,     83,     84,     85,     86,     87,     88,     89,     90,
5504     91,     92,     93,     94,     95,     96,     97,     98,     99,
5505     100,    101,    102,    103,    104,    105,    106,    107,    108,
5506     109,    110,    111,    112,    113,    114,    115,    116,    117,
5507     118,    119,    120,    121,    122,    123,    124,    125,    126,
5508     10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5509     12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5510     12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5511     12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5512     12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5513     12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5514     12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5515     12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5516     4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5517     4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5518     4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5519     4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5520     4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5521     162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5522     8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5523     665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5524     600,    606,    681,    612,    610,    608,    667,    295,    668,
5525     615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5526     654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5527     638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5528     673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5529     69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5530     70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5531     70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5532     119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5533     119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5534     119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5535     119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5536     68,     69,     70,     71,     72,     73,     74,     75,     76,
5537     77,     78,     79,     80,     81,     82,     83,     84,     85,
5538     86,     87,     88,     89,     90,     97,     98,     99,     100,
5539     101,    102,    103,    104,    105,    106,    107,    108,    109,
5540     110,    111,    112,    113,    114,    115,    116,    117,    118,
5541     119,    120,    121,    122,    65,     66,     67,     68,     69,
5542     70,     71,     72,     73,     74,     75,     76,     77,     78,
5543     79,     80,     81,     82,     83,     84,     85,     86,     87,
5544     88,     89,     90,     97,     98,     99,     100,    101,    102,
5545     103,    105,    106,    107,    108,    109,    110,    111,    112,
5546     113,    114,    115,    116,    117,    118,    119,    120,    121,
5547     122,    65,     66,     67,     68,     69,     70,     71,     72,
5548     73,     74,     75,     76,     77,     78,     79,     80,     81,
5549     82,     83,     84,     85,     86,     87,     88,     89,     90,
5550     97,     98,     99,     100,    101,    102,    103,    104,    105,
5551     106,    107,    108,    109,    110,    111,    112,    113,    114,
5552     115,    116,    117,    118,    119,    120,    121,    122,    65,
5553     67,     68,     71,     74,     75,     78,     79,     80,     81,
5554     83,     84,     85,     86,     87,     88,     89,     90,     97,
5555     98,     99,     100,    102,    104,    105,    106,    107,    108,
5556     109,    110,    112,    113,    114,    115,    116,    117,    118,
5557     119,    120,    121,    122,    65,     66,     67,     68,     69,
5558     70,     71,     72,     73,     74,     75,     76,     77,     78,
5559     79,     80,     81,     82,     83,     84,     85,     86,     87,
5560     88,     89,     90,     97,     98,     99,     100,    101,    102,
5561     103,    104,    105,    106,    107,    108,    109,    110,    111,
5562     112,    113,    114,    115,    116,    117,    118,    119,    120,
5563     121,    122,    65,     66,     68,     69,     70,     71,     74,
5564     75,     76,     77,     78,     79,     80,     81,     83,     84,
5565     85,     86,     87,     88,     89,     97,     98,     99,     100,
5566     101,    102,    103,    104,    105,    106,    107,    108,    109,
5567     110,    111,    112,    113,    114,    115,    116,    117,    118,
5568     119,    120,    121,    122,    65,     66,     68,     69,     70,
5569     71,     73,     74,     75,     76,     77,     79,     83,     84,
5570     85,     86,     87,     88,     89,     97,     98,     99,     100,
5571     101,    102,    103,    104,    105,    106,    107,    108,    109,
5572     110,    111,    112,    113,    114,    115,    116,    117,    118,
5573     119,    120,    121,    122,    65,     66,     67,     68,     69,
5574     70,     71,     72,     73,     74,     75,     76,     77,     78,
5575     79,     80,     81,     82,     83,     84,     85,     86,     87,
5576     88,     89,     90,     97,     98,     99,     100,    101,    102,
5577     103,    104,    105,    106,    107,    108,    109,    110,    111,
5578     112,    113,    114,    115,    116,    117,    118,    119,    120,
5579     121,    122,    65,     66,     67,     68,     69,     70,     71,
5580     72,     73,     74,     75,     76,     77,     78,     79,     80,
5581     81,     82,     83,     84,     85,     86,     87,     88,     89,
5582     90,     97,     98,     99,     100,    101,    102,    103,    104,
5583     105,    106,    107,    108,    109,    110,    111,    112,    113,
5584     114,    115,    116,    117,    118,    119,    120,    121,    122,
5585     65,     66,     67,     68,     69,     70,     71,     72,     73,
5586     74,     75,     76,     77,     78,     79,     80,     81,     82,
5587     83,     84,     85,     86,     87,     88,     89,     90,     97,
5588     98,     99,     100,    101,    102,    103,    104,    105,    106,
5589     107,    108,    109,    110,    111,    112,    113,    114,    115,
5590     116,    117,    118,    119,    120,    121,    122,    65,     66,
5591     67,     68,     69,     70,     71,     72,     73,     74,     75,
5592     76,     77,     78,     79,     80,     81,     82,     83,     84,
5593     85,     86,     87,     88,     89,     90,     97,     98,     99,
5594     100,    101,    102,    103,    104,    105,    106,    107,    108,
5595     109,    110,    111,    112,    113,    114,    115,    116,    117,
5596     118,    119,    120,    121,    122,    65,     66,     67,     68,
5597     69,     70,     71,     72,     73,     74,     75,     76,     77,
5598     78,     79,     80,     81,     82,     83,     84,     85,     86,
5599     87,     88,     89,     90,     97,     98,     99,     100,    101,
5600     102,    103,    104,    105,    106,    107,    108,    109,    110,
5601     111,    112,    113,    114,    115,    116,    117,    118,    119,
5602     120,    121,    122,    65,     66,     67,     68,     69,     70,
5603     71,     72,     73,     74,     75,     76,     77,     78,     79,
5604     80,     81,     82,     83,     84,     85,     86,     87,     88,
5605     89,     90,     97,     98,     99,     100,    101,    102,    103,
5606     104,    105,    106,    107,    108,    109,    110,    111,    112,
5607     113,    114,    115,    116,    117,    118,    119,    120,    121,
5608     122,    305,    567,    913,    914,    915,    916,    917,    918,
5609     919,    920,    921,    922,    923,    924,    925,    926,    927,
5610     928,    929,    920,    931,    932,    933,    934,    935,    936,
5611     937,    8711,   945,    946,    947,    948,    949,    950,    951,
5612     952,    953,    954,    955,    956,    957,    958,    959,    960,
5613     961,    962,    963,    964,    965,    966,    967,    968,    969,
5614     8706,   949,    952,    954,    966,    961,    960,    913,    914,
5615     915,    916,    917,    918,    919,    920,    921,    922,    923,
5616     924,    925,    926,    927,    928,    929,    920,    931,    932,
5617     933,    934,    935,    936,    937,    8711,   945,    946,    947,
5618     948,    949,    950,    951,    952,    953,    954,    955,    956,
5619     957,    958,    959,    960,    961,    962,    963,    964,    965,
5620     966,    967,    968,    969,    8706,   949,    952,    954,    966,
5621     961,    960,    913,    914,    915,    916,    917,    918,    919,
5622     920,    921,    922,    923,    924,    925,    926,    927,    928,
5623     929,    920,    931,    932,    933,    934,    935,    936,    937,
5624     8711,   945,    946,    947,    948,    949,    950,    951,    952,
5625     953,    954,    955,    956,    957,    958,    959,    960,    961,
5626     962,    963,    964,    965,    966,    967,    968,    969,    8706,
5627     949,    952,    954,    966,    961,    960,    913,    914,    915,
5628     916,    917,    918,    919,    920,    921,    922,    923,    924,
5629     925,    926,    927,    928,    929,    920,    931,    932,    933,
5630     934,    935,    936,    937,    8711,   945,    946,    947,    948,
5631     949,    950,    951,    952,    953,    954,    955,    956,    957,
5632     958,    959,    960,    961,    962,    963,    964,    965,    966,
5633     967,    968,    969,    8706,   949,    952,    954,    966,    961,
5634     960,    913,    914,    915,    916,    917,    918,    919,    920,
5635     921,    922,    923,    924,    925,    926,    927,    928,    929,
5636     920,    931,    932,    933,    934,    935,    936,    937,    8711,
5637     945,    946,    947,    948,    949,    950,    951,    952,    953,
5638     954,    955,    956,    957,    958,    959,    960,    961,    962,
5639     963,    964,    965,    966,    967,    968,    969,    8706,   949,
5640     952,    954,    966,    961,    960,    988,    989,    48,     49,
5641     50,     51,     52,     53,     54,     55,     56,     57,     48,
5642     49,     50,     51,     52,     53,     54,     55,     56,     57,
5643     48,     49,     50,     51,     52,     53,     54,     55,     56,
5644     57,     48,     49,     50,     51,     52,     53,     54,     55,
5645     56,     57,     48,     49,     50,     51,     52,     53,     54,
5646     55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5647     1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5648     1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5649     1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5650     1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5651     1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5652     1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5653     42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5654     1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5655     1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5656     1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5657     1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5658     1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5659     1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5660     1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5661     1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5662     1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5663     1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5664     1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5665     1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5666     1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5667     1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5668     1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5669     46,     48,     44,     49,     44,     50,     44,     51,     44,
5670     52,     44,     53,     44,     54,     44,     55,     44,     56,
5671     44,     57,     44,     40,     65,     41,     40,     66,     41,
5672     40,     67,     41,     40,     68,     41,     40,     69,     41,
5673     40,     70,     41,     40,     71,     41,     40,     72,     41,
5674     40,     73,     41,     40,     74,     41,     40,     75,     41,
5675     40,     76,     41,     40,     77,     41,     40,     78,     41,
5676     40,     79,     41,     40,     80,     41,     40,     81,     41,
5677     40,     82,     41,     40,     83,     41,     40,     84,     41,
5678     40,     85,     41,     40,     86,     41,     40,     87,     41,
5679     40,     88,     41,     40,     89,     41,     40,     90,     41,
5680     12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5681     65,     66,     67,     68,     69,     70,     71,     72,     73,
5682     74,     75,     76,     77,     78,     79,     80,     81,     82,
5683     83,     84,     85,     86,     87,     88,     89,     90,     72,
5684     86,     77,     86,     83,     68,     83,     83,     80,     80,
5685     86,     87,     67,     77,     67,     77,     68,     77,     82,
5686     68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5687     21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5688     28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5689     36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5690     24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5691     28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5692     12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5693     12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5694     12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5695     48,     49,     50,     51,     52,     53,     54,     55,     56,
5696     57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5697     20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5698     20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5699     20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5700     21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5701     21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5702     28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5703     21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5704     21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5705     20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5706     136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5707     23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5708     23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5709     24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5710     138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5711     24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5712     172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5713     156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5714     14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5715     24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5716     25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5717     25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5718     25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5719     15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5720     17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5721     26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5722     27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5723     15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5724     146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5725     28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5726     147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5727     15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5728     148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5729     29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5730     29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5731     30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5732     151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5733     16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5734     153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5735     154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5736     17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5737     32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5738     32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5739     32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5740     33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5741     33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5742     33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5743     158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5744     17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5745     34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5746     34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5747     13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5748     162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5749     36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5750     165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5751     38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5752     168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5753     38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5754     170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5755     172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5756     40726,  40763,  173568};
5757 
5758 const uint8_t canonical_combining_class_index[4352] = {
5759     0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5760     15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5761     0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5762     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5763     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  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,  27, 0,  28, 29, 30,
5768     31, 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,  0,  0,  0,  0,  0,
5770     0,  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,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5773     37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5774     53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5775     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5776     0,  0,  0,  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,  55, 56, 0,  0,  0,  57, 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,  0,  0,  0,  0,  0,  0,  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,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5783     0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5784     0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5785     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5786     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  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};
5989 const uint8_t canonical_combining_class_block[67][256] = {
5990     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5991      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
6001     {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6002      230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6003      220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6004      220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6005      220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6006      230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6007      220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6008      230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6009      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6010      0,   0,   0,   0,   0,   0,   0,   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},
6019     {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6020      0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 230,
6025      230, 230, 230, 230, 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, 0,
6027      0,   0,   0,   0,   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},
6031     {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,   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,   220, 230, 230, 230, 230,
6041      220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6042      220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6043      14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6044      0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6045      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6046      0,   0,   0,   0,   0,   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},
6049     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6050      0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6051      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6052      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6053      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6054      27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6055      230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6056      0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6057      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6058      0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6064      230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6065      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6066      0},
6067     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6068      0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6069      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6070      0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6071      220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6072      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6073      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   230, 230, 230, 230, 230,
6083      230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6084      0},
6085     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6086      0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6087      230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6088      230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6089      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6090      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6091      220, 220, 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,   0,
6093      0,   0,   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,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6096      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6098      0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6099      220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6100      230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6101      27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6102      230},
6103     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6104      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6105      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6106      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6107      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6108      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   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, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6112      0, 0, 0, 0, 0, 0, 0, 9, 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, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6114      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6115     {0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6117      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6118      0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6120      0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0,
6123      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0,
6125      0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6128      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6129      0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6131      0, 0, 0, 0, 0, 0, 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, 9, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6139      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6140      0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6141      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6142      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  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, 7, 0, 0, 0,
6145      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  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, 0, 0, 0, 0,
6147      0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6150      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6151      0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6153      0, 0, 0, 0, 0, 0, 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, 9, 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, 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,
6160      0,   0,   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,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6163      107, 107, 107, 107, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6165      0,   0,   0,   0,   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,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6170      0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6171      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6172      0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6173      0,   0,   0,   0},
6174     {0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6175      0,   0, 0,   0,   0,   0,   0, 0, 0,   220, 220, 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, 220, 0,   220, 0,   216, 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, 0,   0,   0,   0,   0,   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, 129, 130, 0,   132, 0,   0, 0,
6182      0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6183      230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6184      0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6185      0,   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,   220, 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,   0,   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},
6192     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6193      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6194      0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 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, 0, 0, 0, 0, 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, 220, 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, 0,   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},
6203     {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, 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, 230, 230, 230, 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, 0,   0,   0,   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},
6215     {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6216      0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6217      0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 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, 9, 0, 0, 0, 0, 0,
6224      0, 0, 0, 0, 0, 230, 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},
6226     {0, 0,   0, 0, 0, 0, 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, 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, 228, 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, 0,   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},
6237     {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,   0, 0, 0, 0, 0, 0,
6239      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 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, 0,   0,   0,   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},
6249     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6250      0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 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,   0,   0,   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,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6256      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6257      230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6258      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6259      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6260      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6261      230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6262      220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6263      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6264      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6265      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6266      0},
6267     {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6268      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6269      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6270      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6271      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6272      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6273      230, 230, 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, 0,   0,   0,   0,   0,   0,   0,
6275      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6276      9,   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,   0,
6278      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6279      0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6280      0,   0,   0, 0, 0, 0, 0, 0, 0},
6281     {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6282      0,   0, 0, 0,   0,   0,   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,   7,   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,   0,   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,   230, 230,
6295      230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6296      0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6297      0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6298      0},
6299     {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6300      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230, 220,
6312      230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6313      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6314      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6315      230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6316      220},
6317     {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6318      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
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      230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6331      0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6332      230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6333     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6334      0, 0, 0, 0, 0, 0, 0, 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, 230, 230, 230,
6344      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,
6346      0,   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,   9,   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,   0,   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,   230,
6360      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6361      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6362      230},
6363     {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6364      0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6365      0, 0, 218, 228, 232, 222, 224, 224, 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, 0,   0,   0,   0,   0,   0,   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, 8, 8, 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, 0, 0, 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},
6376     {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,   230,
6383      0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6384      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6385      0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
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,   0,   0,
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      230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6392     {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6393      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6394      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
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,   0,
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,   9,   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,   230,
6407      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6408      230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6409      0},
6410     {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6411      0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6412      220, 220, 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, 9, 0, 0, 0, 0,
6414      0,   0,   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, 0, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6421      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,
6423      0,   0,   0, 0,   0, 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, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6432      230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6433      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6434      0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6435      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, 0, 0, 0, 0, 0, 0,
6437      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0,
6446      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, 0, 0, 0,
6448      0, 0, 0, 0, 0, 0, 26, 0, 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, 0,  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},
6458     {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,
6460      0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6461      220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6462      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6463      0,   0,   0,   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},
6476     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6477      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 220, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 220, 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},
6498     {0, 0, 0, 0, 0, 0, 0, 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, 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, 230, 230, 230, 230, 230, 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, 0,   0,   0,   0,   0,   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},
6510     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6511      0, 0, 0, 0, 0, 0, 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, 0,   0, 0,   230, 1, 220, 0,
6513      0, 0, 0, 9, 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,   0,   0, 0,   0,
6515      0, 0, 0, 0, 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, 230, 220, 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},
6523     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6524      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 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, 0,   0,   0,   0,   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},
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,  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, 230, 230, 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, 0,   0,   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, 220, 220, 220},
6547     {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, 0, 0, 0, 0, 0, 0,   0,
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, 220, 220,
6551      230, 230, 230, 220, 230, 220, 220, 220, 220, 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, 0,   0,
6553      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6554      0,   0,   0,   0,   230, 220, 230, 220, 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,   0,   0,   0,   0,   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},
6562     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6563      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 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, 9, 0, 0, 0, 0, 0, 0, 0,
6567      0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6569      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 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, 0, 0, 0, 0, 0, 0, 0,
6572      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6573     {230, 230, 230, 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, 0, 0, 0, 0, 0, 0,
6575      0,   0,   0,   0, 0, 0, 0, 9, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6578      0,   0,   0,   0, 0, 7, 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, 0, 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, 9, 0, 0, 0, 0, 0,
6582      0,   0,   0,   0, 7, 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, 0, 0, 0, 0, 0, 0,
6584      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, 0, 0,
6586      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6587      0, 0, 0, 0, 0, 9, 7, 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, 0, 0, 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, 7, 9, 0, 0, 0, 0, 0,
6595      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,
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,   7,   7,   0, 0, 0,
6600      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6601      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6602      0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6603      230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6604      0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6605      0,   0,   0,   0,   0,   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, 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, 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, 9, 0, 0, 0, 7,   0,
6615      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6616      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6617      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   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, 9, 7, 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, 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, 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, 9,
6631      7, 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, 0,
6633      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, 0, 0, 0, 0, 0, 0, 0, 0,
6636      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 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, 9, 7, 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, 0, 0, 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},
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, 0, 0, 0, 9, 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, 0, 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},
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, 0, 0, 0, 0, 0, 0, 0, 0,
6658      0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 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, 0, 0, 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},
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, 0, 0, 0, 0, 0, 0, 0, 0,
6669      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 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, 0, 0, 0, 0, 0, 0, 0, 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, 9, 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},
6678     {0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6680      0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 9, 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, 0, 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},
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, 0, 0, 0, 0, 0, 0, 0, 0,
6691      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 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},
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, 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, 7, 0, 9, 9, 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, 0, 0, 0, 0, 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, 9, 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, 0, 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},
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, 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, 9, 9, 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, 0, 0, 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},
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, 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      1, 1, 1, 1, 1, 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,
6734      0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6735      0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 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, 0,   0,   0,   0,   0,   0,   0,   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},
6746     {0, 0, 0, 0, 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, 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      6, 6, 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      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 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, 0, 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},
6768     {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, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6775      216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6776      220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6777      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6778      0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 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,   0,   0,   0,   0,   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, 0, 0, 0, 0, 0, 0,
6785      0,   0,   0,   0, 0, 0, 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      230, 230, 230, 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      0,   0,   0,   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},
6796     {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6797      230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6798      230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6799      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6800      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 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,   0,   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},
6814     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6815      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   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,   230, 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,   0,   0,
6824      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6825      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, 0,   0,   0,   0,   0, 0,
6827      0, 0, 0, 0, 0, 0, 0, 0, 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, 232, 232, 220, 230, 0, 0,
6837      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, 0, 0, 0, 0,
6839      0, 0, 0, 0, 0, 0, 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, 220, 220, 220, 220, 220, 220, 220, 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, 0,   0,   0,   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, 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, 230, 230, 230, 230, 230, 230, 7, 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, 0,   0,   0,   0,   0,   0,   0, 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}};
6864 
6865 const uint8_t composition_index[4352] = {
6866     0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6867     5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6868     5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6869     5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6870     5, 5, 5, 5, 5,  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, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 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, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  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};
7064 const uint16_t composition_block[67][257] = {
7065     {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7066      1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
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,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7070      163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7071      365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7072      503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7073      719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7074      755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7075      755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7076      755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7077      761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7078      769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7079      789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7080      815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7081      843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7082      869, 869},
7083     {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7084      885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7085      893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7086      893, 893, 893, 893, 893, 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, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7089      901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7090      911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7091      917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7092      919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7093      919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7094      939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7095      959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7096      961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7097      961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7098      961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7099      965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7100      965, 965},
7101     {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7102      965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7103      965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7104      973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7105      977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7106      977, 977, 977, 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, 979, 979, 979,
7111      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7112      979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 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},
7119     {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7120      979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  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,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7132      1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7133      1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7134      1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7135      1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7136      1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7137      1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7138      1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7139      1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7140      1171, 1171, 1171, 1171, 1171},
7141     {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7142      1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7143      1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7144      1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7145      1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7146      1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7147      1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7148      1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7149      1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7150      1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7151      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7152      1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 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, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7160      1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7161      1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7162      1275, 1275, 1275, 1275, 1275},
7163     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7164      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
7174     {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7175      1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7176      1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7177      1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7178      1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7179      1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7180      1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7181      1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7182      1285, 1285, 1285, 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, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7191      1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7192      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7193      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7194      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7195      1291, 1291, 1291, 1291, 1291},
7196     {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7197      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7198      1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7199      1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7200      1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7201      1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7202      1297, 1297, 1297, 1297, 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, 1301, 1301, 1301, 1301,
7213      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7214      1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 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},
7218     {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7219      1301, 1301, 1301, 1301, 1301, 1301, 1301, 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      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7225      1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
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, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7231      1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7232      1309, 1309, 1309, 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, 1313, 1315, 1315, 1315, 1315,
7235      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7236      1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 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},
7240     {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7241      1315, 1315, 1315, 1315, 1315, 1315, 1315, 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, 1317,
7246      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7247      1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 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      1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7257      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7258      1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 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},
7262     {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7263      1327, 1327, 1327, 1327, 1327, 1327, 1327, 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, 1331,
7268      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7269      1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
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, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7281      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7282      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7283      1341, 1341, 1341, 1341, 1341},
7284     {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7285      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7286      1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7287      1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7288      1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7289      1343, 1343, 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},
7306     {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7307      1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7308      1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7309      1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7310      1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7311      1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7312      1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7313      1365, 1365, 1365, 1365, 1365, 1365, 1365, 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},
7328     {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7329      1365, 1365, 1365, 1365, 1365, 1365, 1365, 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, 1367, 1369, 1369, 1369, 1369,
7333      1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7334      1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7335      1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7336      1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7337      1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7338      1377, 1377, 1377, 1377, 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, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7342      1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7343      1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7344      1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7345      1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7346      1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7347      1393, 1393, 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},
7350     {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7351      1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7352      1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7353      1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7354      1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7355      1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7356      1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7357      1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7358      1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7359      1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7360      1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7361      1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7362      1641, 1641, 1641, 1641, 1641, 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, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7366      1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7367      1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7368      1651, 1651, 1651, 1651, 1651, 1651, 1651, 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, 1653, 1653, 1653, 1653, 1653,
7371      1653, 1653, 1653, 1659, 1659},
7372     {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7373      1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 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, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7385      1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7386      1665, 1665, 1665, 1665, 1665, 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, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7390      1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7391      1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7392      1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7393      1671, 1671, 1671, 1671, 1671},
7394     {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7395      1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7396      1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7397      1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7398      1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7399      1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7400      1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7401      1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7402      1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7403      1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7404      1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7405      1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7406      1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7407      1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7408      1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7409      1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7410      1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7411      1741, 1741, 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},
7416     {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7417      1741, 1741, 1741, 1741, 1741, 1741, 1741, 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, 1743,
7422      1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7423      1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7424      1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7425      1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7426      1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7427      1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7428      1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7429      1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7430      1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7431      1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7432      1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7433      1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7434      1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7435      1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7436      1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7437      1855, 1855, 1857, 1857, 1857},
7438     {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7439      1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 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, 1859, 1859,
7451      1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7452      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7453      1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 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},
7460     {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7461      1863, 1863, 1863, 1863, 1863, 1863, 1863, 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, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7465      1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7466      1867, 1867, 1867, 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},
7482     {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7483      1867, 1867, 1867, 1867, 1867, 1867, 1867, 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      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7489      1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
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},
7504     {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7505      1871, 1871, 1871, 1871, 1871, 1871, 1871, 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, 1877, 1877, 1877, 1877, 1877, 1877,
7520      1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7521      1877, 1877, 1877, 1877, 1877, 1877, 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},
7526     {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7527      1877, 1877, 1877, 1877, 1877, 1877, 1877, 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, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7542      1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7543      1881, 1881, 1881, 1881, 1881, 1881, 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},
7548     {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7549      1881, 1881, 1881, 1881, 1881, 1881, 1881, 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, 1883, 1883, 1883, 1883, 1883, 1883,
7553      1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7554      1883, 1883, 1883, 1883, 1883, 1883, 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}};
7570 const char32_t composition_data[1883] = {
7571     0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7572     770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7573     196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7574     803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7575     7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7576     775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7577     7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7578     774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7579     516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7580     816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7581     286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7582     776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7583     204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7584     775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7585     522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7586     780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7587     317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7588     775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7589     7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7590     768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7591     334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7592     783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7593     7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7594     785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7595     348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7596     775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7597     7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7598     772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7599     368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7600     804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7601     7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7602     803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7603     374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7604     803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7605     7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7606     772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7607     229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7608     808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7609     265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7610     803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7611     233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7612     776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7613     7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7614     769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7615     487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7616     803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7617     237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7618     777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7619     303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7620     803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7621     7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7622     803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7623     328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7624     769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7625     559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7626     785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7627     7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7628     803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7629     7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7630     776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7631     7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7632     772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7633     369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7634     804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7635     7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7636     778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7637     253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7638     777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7639     380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7640     834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7641     478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7642     769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7643     7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7644     772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7645     473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7646     769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7647     7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7648     771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7649     555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7650     768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7651     7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7652     769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7653     7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7654     776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7655     7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7656     777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7657     7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7658     803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7659     481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7660     768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7661     7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7662     768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7663     8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7664     788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7665     8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7666     788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7667     8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7668     774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7669     8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7670     787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7671     943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7672     834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7673     8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7674     776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7675     974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7676     769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7677     8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7678     769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7679     1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7680     769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7681     1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7682     769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7683     1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7684     769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7685     1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7686     783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7687     1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7688     1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7689     2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7690     3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7691     3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7692     3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7693     4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7694     6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7695     6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7696     775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7697     7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7698     834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7699     8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7700     837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7701     7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7702     837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7703     7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7704     769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7705     7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7706     837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7707     7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7708     837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7709     8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7710     769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7711     7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7712     769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7713     8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7714     768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7715     8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7716     837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7717     8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7718     769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7719     8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7720     837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7721     8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7722     824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7723     8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7724     824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7725     8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7726     824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7727     8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7728     824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7729     8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7730     12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7731     12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7732     12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7733     12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7734     12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7735     12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7736     12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7737     12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7738     12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7739     12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7740     69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7741     70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7742     71984, 71992};
7743 
7744 }  // namespace ada::idna
7745 #endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7746 /* end file src/normalization_tables.cpp */
7747 
7748 namespace ada::idna {
7749 
7750 // See
7751 // https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7752 constexpr char32_t hangul_sbase = 0xAC00;
7753 constexpr char32_t hangul_tbase = 0x11A7;
7754 constexpr char32_t hangul_vbase = 0x1161;
7755 constexpr char32_t hangul_lbase = 0x1100;
7756 constexpr char32_t hangul_lcount = 19;
7757 constexpr char32_t hangul_vcount = 21;
7758 constexpr char32_t hangul_tcount = 28;
7759 constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7760 constexpr char32_t hangul_scount =
7761     hangul_lcount * hangul_vcount * hangul_tcount;
7762 
compute_decomposition_length(const std::u32string_view input)7763 std::pair<bool, size_t> compute_decomposition_length(
7764     const std::u32string_view input) noexcept {
7765   bool decomposition_needed{false};
7766   size_t additional_elements{0};
7767   for (char32_t current_character : input) {
7768     size_t decomposition_length{0};
7769 
7770     if (current_character >= hangul_sbase &&
7771         current_character < hangul_sbase + hangul_scount) {
7772       decomposition_length = 2;
7773       if ((current_character - hangul_sbase) % hangul_tcount) {
7774         decomposition_length = 3;
7775       }
7776     } else if (current_character < 0x110000) {
7777       const uint8_t di = decomposition_index[current_character >> 8];
7778       const uint16_t* const decomposition =
7779           decomposition_block[di] + (current_character % 256);
7780       decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7781       if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7782         decomposition_length = 0;
7783       }
7784     }
7785     if (decomposition_length != 0) {
7786       decomposition_needed = true;
7787       additional_elements += decomposition_length - 1;
7788     }
7789   }
7790   return {decomposition_needed, additional_elements};
7791 }
7792 
decompose(std::u32string & input,size_t additional_elements)7793 void decompose(std::u32string& input, size_t additional_elements) {
7794   input.resize(input.size() + additional_elements);
7795   for (size_t descending_idx = input.size(),
7796               input_count = descending_idx - additional_elements;
7797        input_count--;) {
7798     if (input[input_count] >= hangul_sbase &&
7799         input[input_count] < hangul_sbase + hangul_scount) {
7800       // Hangul decomposition.
7801       char32_t s_index = input[input_count] - hangul_sbase;
7802       if (s_index % hangul_tcount != 0) {
7803         input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7804       }
7805       input[--descending_idx] =
7806           hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7807       input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7808     } else if (input[input_count] < 0x110000) {
7809       // Check decomposition_data.
7810       const uint16_t* decomposition =
7811           decomposition_block[decomposition_index[input[input_count] >> 8]] +
7812           (input[input_count] % 256);
7813       uint16_t decomposition_length =
7814           (decomposition[1] >> 2) - (decomposition[0] >> 2);
7815       if (decomposition_length > 0 && (decomposition[0] & 1)) {
7816         decomposition_length = 0;
7817       }
7818       if (decomposition_length > 0) {
7819         // Non-recursive decomposition.
7820         while (decomposition_length-- > 0) {
7821           input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7822                                                        decomposition_length];
7823         }
7824       } else {
7825         // No decomposition.
7826         input[--descending_idx] = input[input_count];
7827       }
7828     } else {
7829       // Non-Unicode character.
7830       input[--descending_idx] = input[input_count];
7831     }
7832   }
7833 }
7834 
get_ccc(char32_t c)7835 uint8_t get_ccc(char32_t c) noexcept {
7836   return c < 0x110000 ? canonical_combining_class_block
7837                             [canonical_combining_class_index[c >> 8]][c % 256]
7838                       : 0;
7839 }
7840 
sort_marks(std::u32string & input)7841 void sort_marks(std::u32string& input) {
7842   for (size_t idx = 1; idx < input.size(); idx++) {
7843     uint8_t ccc = get_ccc(input[idx]);
7844     if (ccc == 0) {
7845       continue;
7846     }  // Skip non-combining characters.
7847     auto current_character = input[idx];
7848     size_t back_idx = idx;
7849     while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7850       input[back_idx] = input[back_idx - 1];
7851       back_idx--;
7852     }
7853     input[back_idx] = current_character;
7854   }
7855 }
7856 
decompose_nfc(std::u32string & input)7857 void decompose_nfc(std::u32string& input) {
7858   /**
7859    * Decompose the domain_name string to Unicode Normalization Form C.
7860    * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7861    */
7862   auto [decomposition_needed, additional_elements] =
7863       compute_decomposition_length(input);
7864   if (decomposition_needed) {
7865     decompose(input, additional_elements);
7866   }
7867   sort_marks(input);
7868 }
7869 
compose(std::u32string & input)7870 void compose(std::u32string& input) {
7871   /**
7872    * Compose the domain_name string to Unicode Normalization Form C.
7873    * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7874    */
7875   size_t input_count{0};
7876   size_t composition_count{0};
7877   for (; input_count < input.size(); input_count++, composition_count++) {
7878     input[composition_count] = input[input_count];
7879     if (input[input_count] >= hangul_lbase &&
7880         input[input_count] < hangul_lbase + hangul_lcount) {
7881       if (input_count + 1 < input.size() &&
7882           input[input_count + 1] >= hangul_vbase &&
7883           input[input_count + 1] < hangul_vbase + hangul_vcount) {
7884         input[composition_count] =
7885             hangul_sbase +
7886             ((input[input_count] - hangul_lbase) * hangul_vcount +
7887              input[input_count + 1] - hangul_vbase) *
7888                 hangul_tcount;
7889         input_count++;
7890         if (input_count + 1 < input.size() &&
7891             input[input_count + 1] > hangul_tbase &&
7892             input[input_count + 1] < hangul_tbase + hangul_tcount) {
7893           input[composition_count] += input[++input_count] - hangul_tbase;
7894         }
7895       }
7896     } else if (input[input_count] >= hangul_sbase &&
7897                input[input_count] < hangul_sbase + hangul_scount) {
7898       if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7899           input_count + 1 < input.size() &&
7900           input[input_count + 1] > hangul_tbase &&
7901           input[input_count + 1] < hangul_tbase + hangul_tcount) {
7902         input[composition_count] += input[++input_count] - hangul_tbase;
7903       }
7904     } else if (input[input_count] < 0x110000) {
7905       const uint16_t* composition =
7906           &composition_block[composition_index[input[input_count] >> 8]]
7907                             [input[input_count] % 256];
7908       size_t initial_composition_count = composition_count;
7909       for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7910            input_count++) {
7911         uint8_t ccc = get_ccc(input[input_count + 1]);
7912 
7913         if (composition[1] != composition[0] && previous_ccc < ccc) {
7914           // Try finding a composition.
7915           uint16_t left = composition[0];
7916           uint16_t right = composition[1];
7917           while (left + 2 < right) {
7918             // mean without overflow
7919             uint16_t middle = left + (((right - left) >> 1) & ~1);
7920             if (composition_data[middle] <= input[input_count + 1]) {
7921               left = middle;
7922             }
7923             if (composition_data[middle] >= input[input_count + 1]) {
7924               right = middle;
7925             }
7926           }
7927           if (composition_data[left] == input[input_count + 1]) {
7928             input[initial_composition_count] = composition_data[left + 1];
7929             composition =
7930                 &composition_block
7931                     [composition_index[composition_data[left + 1] >> 8]]
7932                     [composition_data[left + 1] % 256];
7933             continue;
7934           }
7935         }
7936 
7937         if (ccc == 0) {
7938           break;
7939         }  // Not a combining character.
7940         previous_ccc = ccc;
7941         input[++composition_count] = input[input_count + 1];
7942       }
7943     }
7944   }
7945 
7946   if (composition_count < input_count) {
7947     input.resize(composition_count);
7948   }
7949 }
7950 
normalize(std::u32string & input)7951 void normalize(std::u32string& input) {
7952   /**
7953    * Normalize the domain_name string to Unicode Normalization Form C.
7954    * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7955    */
7956   decompose_nfc(input);
7957   compose(input);
7958 }
7959 
7960 }  // namespace ada::idna
7961 /* end file src/normalization.cpp */
7962 /* begin file src/punycode.cpp */
7963 
7964 #include <cstdint>
7965 
7966 namespace ada::idna {
7967 
7968 constexpr int32_t base = 36;
7969 constexpr int32_t tmin = 1;
7970 constexpr int32_t tmax = 26;
7971 constexpr int32_t skew = 38;
7972 constexpr int32_t damp = 700;
7973 constexpr int32_t initial_bias = 72;
7974 constexpr uint32_t initial_n = 128;
7975 
char_to_digit_value(char value)7976 static constexpr int32_t char_to_digit_value(char value) {
7977   if (value >= 'a' && value <= 'z') return value - 'a';
7978   if (value >= '0' && value <= '9') return value - '0' + 26;
7979   return -1;
7980 }
7981 
digit_to_char(int32_t digit)7982 static constexpr char digit_to_char(int32_t digit) {
7983   return digit < 26 ? char(digit + 97) : char(digit + 22);
7984 }
7985 
adapt(int32_t d,int32_t n,bool firsttime)7986 static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
7987   if (firsttime) {
7988     d = d / damp;
7989   } else {
7990     d = d / 2;
7991   }
7992   d += d / n;
7993   int32_t k = 0;
7994   while (d > ((base - tmin) * tmax) / 2) {
7995     d /= base - tmin;
7996     k += base;
7997   }
7998   return k + (((base - tmin + 1) * d) / (d + skew));
7999 }
8000 
punycode_to_utf32(std::string_view input,std::u32string & out)8001 bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8002   int32_t written_out{0};
8003   out.reserve(out.size() + input.size());
8004   uint32_t n = initial_n;
8005   int32_t i = 0;
8006   int32_t bias = initial_bias;
8007   // grab ascii content
8008   size_t end_of_ascii = input.find_last_of('-');
8009   if (end_of_ascii != std::string_view::npos) {
8010     for (uint8_t c : input.substr(0, end_of_ascii)) {
8011       if (c >= 0x80) {
8012         return false;
8013       }
8014       out.push_back(c);
8015       written_out++;
8016     }
8017     input.remove_prefix(end_of_ascii + 1);
8018   }
8019   while (!input.empty()) {
8020     int32_t oldi = i;
8021     int32_t w = 1;
8022     for (int32_t k = base;; k += base) {
8023       if (input.empty()) {
8024         return false;
8025       }
8026       uint8_t code_point = input.front();
8027       input.remove_prefix(1);
8028       int32_t digit = char_to_digit_value(code_point);
8029       if (digit < 0) {
8030         return false;
8031       }
8032       if (digit > (0x7fffffff - i) / w) {
8033         return false;
8034       }
8035       i = i + digit * w;
8036       int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8037       if (digit < t) {
8038         break;
8039       }
8040       if (w > 0x7fffffff / (base - t)) {
8041         return false;
8042       }
8043       w = w * (base - t);
8044     }
8045     bias = adapt(i - oldi, written_out + 1, oldi == 0);
8046     if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8047       return false;
8048     }
8049     n = n + i / (written_out + 1);
8050     i = i % (written_out + 1);
8051     if (n < 0x80) {
8052       return false;
8053     }
8054     out.insert(out.begin() + i, n);
8055     written_out++;
8056     ++i;
8057   }
8058 
8059   return true;
8060 }
8061 
verify_punycode(std::string_view input)8062 bool verify_punycode(std::string_view input) {
8063   size_t written_out{0};
8064   uint32_t n = initial_n;
8065   int32_t i = 0;
8066   int32_t bias = initial_bias;
8067   // grab ascii content
8068   size_t end_of_ascii = input.find_last_of('-');
8069   if (end_of_ascii != std::string_view::npos) {
8070     for (uint8_t c : input.substr(0, end_of_ascii)) {
8071       if (c >= 0x80) {
8072         return false;
8073       }
8074       written_out++;
8075     }
8076     input.remove_prefix(end_of_ascii + 1);
8077   }
8078   while (!input.empty()) {
8079     int32_t oldi = i;
8080     int32_t w = 1;
8081     for (int32_t k = base;; k += base) {
8082       if (input.empty()) {
8083         return false;
8084       }
8085       uint8_t code_point = input.front();
8086       input.remove_prefix(1);
8087       int32_t digit = char_to_digit_value(code_point);
8088       if (digit < 0) {
8089         return false;
8090       }
8091       if (digit > (0x7fffffff - i) / w) {
8092         return false;
8093       }
8094       i = i + digit * w;
8095       int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8096       if (digit < t) {
8097         break;
8098       }
8099       if (w > 0x7fffffff / (base - t)) {
8100         return false;
8101       }
8102       w = w * (base - t);
8103     }
8104     bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8105     if (i / (written_out + 1) > 0x7fffffff - n) {
8106       return false;
8107     }
8108     n = n + i / int32_t(written_out + 1);
8109     i = i % int32_t(written_out + 1);
8110     if (n < 0x80) {
8111       return false;
8112     }
8113     written_out++;
8114     ++i;
8115   }
8116 
8117   return true;
8118 }
8119 
utf32_to_punycode(std::u32string_view input,std::string & out)8120 bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8121   out.reserve(input.size() + out.size());
8122   uint32_t n = initial_n;
8123   int32_t d = 0;
8124   int32_t bias = initial_bias;
8125   size_t h = 0;
8126   // first push the ascii content
8127   for (uint32_t c : input) {
8128     if (c < 0x80) {
8129       ++h;
8130       out.push_back(char(c));
8131     }
8132     if (c > 0x10ffff || (c >= 0xd880 && c < 0xe000)) {
8133       return false;
8134     }
8135   }
8136   size_t b = h;
8137   if (b > 0) {
8138     out.push_back('-');
8139   }
8140   while (h < input.size()) {
8141     uint32_t m = 0x10FFFF;
8142     for (auto code_point : input) {
8143       if (code_point >= n && code_point < m) m = code_point;
8144     }
8145 
8146     if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8147       return false;
8148     }
8149     d = d + int32_t((m - n) * (h + 1));
8150     n = m;
8151     for (auto c : input) {
8152       if (c < n) {
8153         if (d == 0x7fffffff) {
8154           return false;
8155         }
8156         ++d;
8157       }
8158       if (c == n) {
8159         int32_t q = d;
8160         for (int32_t k = base;; k += base) {
8161           int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8162 
8163           if (q < t) {
8164             break;
8165           }
8166           out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8167           q = (q - t) / (base - t);
8168         }
8169         out.push_back(digit_to_char(q));
8170         bias = adapt(d, int32_t(h + 1), h == b);
8171         d = 0;
8172         ++h;
8173       }
8174     }
8175     ++d;
8176     ++n;
8177   }
8178   return true;
8179 }
8180 
8181 }  // namespace ada::idna
8182 /* end file src/punycode.cpp */
8183 /* begin file src/validity.cpp */
8184 #include <algorithm>
8185 #include <string_view>
8186 
8187 namespace ada::idna {
8188 
8189 enum direction : uint8_t {
8190   NONE,
8191   BN,
8192   CS,
8193   ES,
8194   ON,
8195   EN,
8196   L,
8197   R,
8198   NSM,
8199   AL,
8200   AN,
8201   ET,
8202   WS,
8203   RLO,
8204   LRO,
8205   PDF,
8206   RLE,
8207   RLI,
8208   FSI,
8209   PDI,
8210   LRI,
8211   B,
8212   S,
8213   LRE
8214 };
8215 
8216 struct directions {
8217   uint32_t start_code;
8218   uint32_t final_code;
8219   direction direct;
8220 };
8221 
8222 static directions dir_table[] = {
8223     {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8224     {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8225     {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8226     {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8227     {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8228     {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8229     {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8230     {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8231     {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8232     {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8233     {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8234     {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8235     {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8236     {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8237     {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8238     {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8239     {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8240     {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8241     {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8242     {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8243     {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8244     {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8245     {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8246     {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8247     {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8248     {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8249     {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8250     {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8251     {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8252     {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8253     {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8254     {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8255     {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8256     {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8257     {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8258     {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8259     {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8260     {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8261     {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8262     {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8263     {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8264     {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8265     {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8266     {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8267     {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8268     {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8269     {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8270     {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8271     {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8272     {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8273     {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8274     {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8275     {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8276     {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8277     {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8278     {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8279     {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8280     {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8281     {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8282     {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8283     {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8284     {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8285     {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8286     {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8287     {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8288     {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8289     {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8290     {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8291     {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8292     {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8293     {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8294     {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8295     {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8296     {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8297     {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8298     {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8299     {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8300     {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8301     {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8302     {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8303     {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8304     {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8305     {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8306     {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8307     {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8308     {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8309     {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8310     {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8311     {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8312     {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8313     {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8314     {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8315     {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8316     {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8317     {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8318     {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8319     {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8320     {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8321     {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8322     {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8323     {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8324     {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8325     {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8326     {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8327     {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8328     {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8329     {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8330     {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8331     {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8332     {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8333     {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8334     {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8335     {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8336     {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8337     {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8338     {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8339     {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8340     {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8341     {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8342     {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8343     {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8344     {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8345     {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8346     {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8347     {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8348     {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8349     {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8350     {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8351     {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8352     {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8353     {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8354     {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8355     {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8356     {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8357     {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8358     {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8359     {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8360     {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8361     {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8362     {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8363     {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8364     {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8365     {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8366     {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8367     {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8368     {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8369     {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8370     {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8371     {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8372     {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8373     {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8374     {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8375     {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8376     {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8377     {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8378     {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8379     {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8380     {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8381     {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8382     {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8383     {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8384     {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8385     {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8386     {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8387     {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8388     {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8389     {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8390     {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8391     {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8392     {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8393     {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8394     {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8395     {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8396     {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8397     {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8398     {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8399     {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8400     {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8401     {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8402     {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8403     {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8404     {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8405     {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8406     {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8407     {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8408     {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8409     {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8410     {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8411     {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8412     {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8413     {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8414     {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8415     {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8416     {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8417     {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8418     {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8419     {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8420     {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8421     {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8422     {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8423     {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8424     {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8425     {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8426     {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8427     {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8428     {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8429     {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8430     {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8431     {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8432     {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8433     {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8434     {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8435     {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8436     {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8437     {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8438     {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8439     {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8440     {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8441     {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8442     {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8443     {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8444     {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8445     {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8446     {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8447     {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8448     {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8449     {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8450     {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8451     {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8452     {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8453     {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8454     {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8455     {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8456     {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8457     {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8458     {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8459     {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8460     {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8461     {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8462     {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8463     {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8464     {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8465     {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8466     {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8467     {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8468     {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8469     {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8470     {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8471     {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8472     {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8473     {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8474     {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8475     {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8476     {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8477     {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8478     {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8479     {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8480     {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8481     {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8482     {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8483     {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8484     {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8485     {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8486     {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8487     {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8488     {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8489     {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8490     {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8491     {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8492     {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8493     {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8494     {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8495     {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8496     {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8497     {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8498     {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8499     {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8500     {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8501     {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8502     {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8503     {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8504     {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8505     {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8506     {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8507     {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8508     {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8509     {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8510     {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8511     {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8512     {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8513     {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8514     {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8515     {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8516     {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8517     {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8518     {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8519     {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8520     {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8521     {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8522     {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8523     {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8524     {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8525     {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8526     {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8527     {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8528     {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8529     {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8530     {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8531     {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8532     {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8533     {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8534     {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8535     {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8536     {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8537     {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8538     {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8539     {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8540     {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8541     {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8542     {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8543     {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8544     {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8545     {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8546     {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8547     {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8548     {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8549     {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8550     {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8551     {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8552     {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8553     {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8554     {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8555     {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8556     {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8557     {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8558     {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8559     {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8560     {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8561     {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8562     {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8563     {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8564     {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8565     {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8566     {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8567     {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8568     {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8569     {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8570     {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8571     {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8572     {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8573     {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8574     {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8575     {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8576     {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8577     {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8578     {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8579     {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8580     {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8581     {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8582     {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8583     {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8584     {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8585     {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8586     {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8587     {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8588     {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8589     {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8590     {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8591     {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8592     {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8593     {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8594     {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8595     {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8596     {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8597     {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8598     {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8599     {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8600     {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8601     {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8602     {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8603     {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8604     {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8605     {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8606     {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8607     {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8608     {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8609     {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8610     {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8611     {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8612     {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8613     {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8614     {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8615     {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8616     {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8617     {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8618     {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8619     {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8620     {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8621     {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8622     {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8623     {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8624     {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8625     {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8626     {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8627     {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8628     {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8629     {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8630     {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8631     {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8632     {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8633     {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8634     {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8635     {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8636     {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8637     {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8638     {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8639     {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8640     {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8641     {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8642     {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8643     {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8644     {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8645     {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8646     {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8647     {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8648     {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8649     {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8650     {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8651     {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8652     {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8653     {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8654     {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8655     {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8656     {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8657     {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8658     {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8659     {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8660     {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8661     {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8662     {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8663     {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8664     {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8665     {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8666     {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8667     {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8668     {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8669     {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8670     {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8671     {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8672     {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8673     {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8674     {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8675     {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8676     {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8677     {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8678     {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8679     {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8680     {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8681     {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8682     {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8683     {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8684     {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8685     {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8686     {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8687     {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8688     {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8689     {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8690     {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8691     {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8692     {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8693     {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8694     {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8695     {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8696     {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8697     {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8698     {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8699     {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8700     {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8701     {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8702     {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8703     {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8704     {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8705     {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8706     {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8707     {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8708     {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8709     {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8710     {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8711     {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8712     {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8713     {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8714     {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8715     {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8716     {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8717     {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8718     {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8719     {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8720     {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8721     {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8722     {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8723     {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8724     {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8725     {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8726     {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8727     {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8728     {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8729     {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8730     {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8731     {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8732     {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8733     {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8734     {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8735     {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8736     {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8737     {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8738     {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8739     {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8740     {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8741     {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8742     {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8743     {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8744     {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8745     {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8746     {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8747     {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8748     {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8749     {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8750     {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8751     {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8752     {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8753     {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8754     {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8755     {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8756     {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8757     {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8758     {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8759     {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8760     {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8761     {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8762     {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8763     {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8764     {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8765     {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8766     {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8767     {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8768     {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8769     {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8770     {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8771     {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8772     {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8773     {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8774     {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8775     {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8776     {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8777     {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8778     {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8779     {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8780     {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8781     {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8782     {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8783     {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8784     {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8785     {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8786     {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8787     {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8788     {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8789     {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8790     {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8791     {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8792     {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8793     {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8794     {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8795     {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8796     {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8797     {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8798     {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8799     {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8800     {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8801     {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8802     {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8803     {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8804     {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8805     {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8806     {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8807     {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8808     {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8809     {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8810     {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8811     {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8812     {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8813     {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8814     {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8815     {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8816     {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8817     {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8818     {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8819     {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8820     {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8821     {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8822     {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8823     {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8824     {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8825     {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8826     {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8827     {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8828     {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8829     {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8830     {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8831     {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8832     {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8833     {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8834     {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8835     {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8836     {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8837     {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8838     {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8839     {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8840     {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8841     {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8842     {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8843     {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8844     {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8845     {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8846     {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8847     {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8848     {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8849     {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8850     {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8851     {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8852     {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8853     {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8854     {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8855     {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8856     {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8857     {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8858     {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8859     {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8860     {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8861     {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8862     {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8863     {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8864     {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8865     {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8866     {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8867     {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8868     {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8869     {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8870     {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8871     {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8872     {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8873     {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8874     {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8875     {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8876     {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8877     {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8878     {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8879     {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8880     {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8881     {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8882     {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8883     {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8884     {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8885     {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8886     {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8887     {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8888     {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8889     {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8890     {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8891     {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8892     {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8893     {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8894     {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8895     {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8896     {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8897     {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8898     {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8899     {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8900     {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8901     {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8902     {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8903     {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8904     {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8905     {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8906     {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8907     {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8908     {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8909     {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8910     {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8911     {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8912     {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8913     {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8914     {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8915     {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8916     {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8917     {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8918     {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8919     {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8920     {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8921     {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8922     {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8923     {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8924     {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8925     {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8926     {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8927     {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8928     {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8929     {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8930     {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8931     {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8932     {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8933     {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8934     {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8935     {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8936     {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8937     {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8938     {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8939     {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8940     {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8941     {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8942     {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8943     {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8944     {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8945     {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8946     {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8947     {0x100000, 0x10fffd, direction::L}};
8948 
8949 // CheckJoiners and CheckBidi are true for URL specification.
8950 
find_direction(uint32_t code_point)8951 inline static direction find_direction(uint32_t code_point) noexcept {
8952   auto it = std::lower_bound(
8953       std::begin(dir_table), std::end(dir_table), code_point,
8954       [](const directions& d, uint32_t c) { return d.final_code < c; });
8955 
8956   // next check is almost surely in vain, but we use it for safety.
8957   if (it == std::end(dir_table)) {
8958     return direction::NONE;
8959   }
8960   // We have that d.final_code >= c.
8961   if (code_point >= it->start_code) {
8962     return it->direct;
8963   }
8964   return direction::NONE;
8965 }
8966 
find_last_not_of_nsm(const std::u32string_view label)8967 inline static size_t find_last_not_of_nsm(
8968     const std::u32string_view label) noexcept {
8969   for (int i = label.size() - 1; i >= 0; i--)
8970     if (find_direction(label[i]) != direction::NSM) return i;
8971 
8972   return std::u32string_view::npos;
8973 }
8974 
8975 // An RTL label is a label that contains at least one character of type R, AL,
8976 // or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
is_rtl_label(const std::u32string_view label)8977 inline static bool is_rtl_label(const std::u32string_view label) noexcept {
8978   const size_t mask =
8979       (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
8980 
8981   size_t directions = 0;
8982   for (size_t i = 0; i < label.size(); i++) {
8983     directions |= 1u << find_direction(label[i]);
8984   }
8985   return (directions & mask) != 0;
8986 }
8987 
is_label_valid(const std::u32string_view label)8988 bool is_label_valid(const std::u32string_view label) {
8989   if (label.empty()) {
8990     return true;
8991   }
8992 
8993   ///////////////
8994   // We have a normalization step which ensures that we are in NFC.
8995   // If we receive punycode, we normalize and check that the normalized
8996   // version matches the original.
8997   // --------------------------------------
8998   // The label must be in Unicode Normalization Form NFC.
8999 
9000   // Current URL standard indicatest that CheckHyphens is set to false.
9001   // ---------------------------------------
9002   // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9003   // in both the third and fourth positions. If CheckHyphens, the label must
9004   // neither begin nor end with a U+002D HYPHEN-MINUS character.
9005 
9006   // This is not necessary because we segment the
9007   // labels by '.'.
9008   // ---------------------------------------
9009   // The label must not contain a U+002E ( . ) FULL STOP.
9010   // if (label.find('.') != std::string_view::npos) return false;
9011 
9012   // The label must not begin with a combining mark, that is:
9013   // General_Category=Mark.
9014   constexpr static uint32_t combining[] = {
9015       0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9016       0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9017       0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9018       0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9019       0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9020       0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9021       0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9022       0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9023       0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9024       0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9025       0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9026       0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9027       0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9028       0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9029       0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9030       0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9031       0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9032       0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9033       0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9034       0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9035       0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9036       0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9037       0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9038       0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9039       0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9040       0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9041       0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9042       0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9043       0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9044       0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9045       0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9046       0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9047       0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9048       0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9049       0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9050       0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9051       0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9052       0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9053       0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9054       0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9055       0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9056       0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9057       0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9058       0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9059       0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9060       0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9061       0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9062       0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9063       0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9064       0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9065       0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9066       0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9067       0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9068       0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9069       0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9070       0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9071       0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9072       0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9073       0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9074       0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9075       0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9076       0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9077       0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9078       0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9079       0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9080       0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9081       0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9082       0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9083       0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9084       0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9085       0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9086       0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9087       0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9088       0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9089       0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9090       0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9091       0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9092       0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9093       0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9094       0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9095       0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9096       0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9097       0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9098       0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9099       0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9100       0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9101       0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9102       0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9103       0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9104       0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9105       0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9106       0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9107       0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9108       0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9109       0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9110       0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9111       0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9112       0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9113       0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9114       0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9115       0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9116       0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9117       0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9118       0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9119       0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9120       0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9121       0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9122       0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9123       0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9124       0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9125       0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9126       0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9127       0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9128       0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9129       0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9130       0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9131       0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9132       0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9133       0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9134       0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9135       0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9136       0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9137       0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9138       0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9139       0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9140       0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9141       0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9142       0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9143       0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9144       0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9145       0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9146       0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9147       0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9148       0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9149       0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9150       0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9151       0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9152       0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9153       0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9154       0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9155       0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9156       0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9157       0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9158       0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9159       0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9160       0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9161       0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9162       0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9163       0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9164       0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9165       0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9166       0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9167       0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9168       0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9169       0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9170       0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9171       0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9172       0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9173       0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9174       0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9175       0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9176       0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9177       0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9178       0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9179       0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9180       0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9181       0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9182       0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9183       0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9184       0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9185       0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9186       0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9187       0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9188       0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9189       0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9190       0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9191       0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9192       0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9193       0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9194       0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9195       0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9196       0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9197       0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9198       0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9199       0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9200       0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9201       0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9202       0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9203       0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9204       0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9205       0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9206       0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9207       0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9208       0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9209       0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9210       0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9211       0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9212       0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9213       0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9214       0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9215       0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9216       0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9217       0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9218       0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9219       0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9220       0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9221       0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9222       0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9223       0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9224       0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9225       0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9226       0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9227       0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9228       0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9229       0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9230       0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9231       0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9232       0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9233       0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9234       0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9235       0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9236       0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9237       0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9238       0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9239       0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9240       0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9241       0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9242       0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9243       0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9244       0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9245       0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9246       0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9247       0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9248       0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9249       0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9250       0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9251       0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9252       0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9253       0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9254       0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9255       0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9256       0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9257       0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9258       0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9259       0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9260       0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9261       0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9262       0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9263       0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9264       0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9265       0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9266       0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9267       0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9268       0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9269       0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9270       0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9271       0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9272       0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9273       0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9274       0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9275       0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9276       0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9277       0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9278       0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9279       0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9280       0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9281       0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9282       0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9283       0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9284       0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9285       0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9286       0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9287       0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9288       0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9289       0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9290       0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9291       0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9292       0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9293       0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9294       0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9295       0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9296       0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9297       0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9298       0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9299       0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9300       0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9301       0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9302   if (std::binary_search(std::begin(combining), std::end(combining),
9303                          label.front())) {
9304     return false;
9305   }
9306   // We verify this next step as part of the mapping:
9307   // ---------------------------------------------
9308   // Each code point in the label must only have certain status values
9309   // according to Section 5, IDNA Mapping Table:
9310   // - For Transitional Processing, each value must be valid.
9311   // - For Nontransitional Processing, each value must be either valid or
9312   // deviation.
9313 
9314   // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9315   // A, in The Unicode Code Points and Internationalized Domain Names for
9316   // Applications (IDNA) [IDNA2008].
9317   constexpr static uint32_t virama[] = {
9318       0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9319       0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9320       0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9321       0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9322       0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9323       0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9324       0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9325       0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9326   constexpr static uint32_t R[] = {
9327       0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9328       0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9329       0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9330       0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9331       0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9332       0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9333       0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9334       0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9335   constexpr static uint32_t L[] = {0xa872};
9336   constexpr static uint32_t D[] = {
9337       0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9338       0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9339       0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9340       0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9341       0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9342       0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9343       0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9344       0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9345       0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9346       0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9347       0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9348       0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9349       0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9350       0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9351       0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9352       0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9353       0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9354       0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9355       0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9356       0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9357       0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9358       0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9359       0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9360       0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9361       0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9362       0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9363       0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9364       0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9365       0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9366       0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9367       0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9368       0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9369       0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9370       0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9371       0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9372       0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9373       0xa870, 0xa871};
9374 
9375   for (size_t i = 0; i < label.size(); i++) {
9376     uint32_t c = label[i];
9377     if (c == 0x200c) {
9378       if (i > 0) {
9379         if (std::binary_search(std::begin(virama), std::end(virama),
9380                                label[i - 1])) {
9381           return true;
9382         }
9383       }
9384       if ((i == 0) || (i + 1 >= label.size())) {
9385         return false;
9386       }
9387       // we go backward looking for L or D
9388       auto is_l_or_d = [](uint32_t code) {
9389         return std::binary_search(std::begin(L), std::end(L), code) ||
9390                std::binary_search(std::begin(D), std::end(D), code);
9391       };
9392       auto is_r_or_d = [](uint32_t code) {
9393         return std::binary_search(std::begin(R), std::end(R), code) ||
9394                std::binary_search(std::begin(D), std::end(D), code);
9395       };
9396       std::u32string_view before = label.substr(0, i);
9397       std::u32string_view after = label.substr(i + 1);
9398       return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9399               before.end()) &&
9400              (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9401               after.end());
9402     } else if (c == 0x200d) {
9403       if (i > 0) {
9404         if (std::binary_search(std::begin(virama), std::end(virama),
9405                                label[i - 1])) {
9406           return true;
9407         }
9408       }
9409       return false;
9410     }
9411   }
9412 
9413   // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9414   // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9415   // Section 2.
9416 
9417   // The following rule, consisting of six conditions, applies to labels
9418   // in Bidi domain names.  The requirements that this rule satisfies are
9419   // described in Section 3.  All of the conditions must be satisfied for
9420   // the rule to be satisfied.
9421   //
9422   //  1.  The first character must be a character with Bidi property L, R,
9423   //     or AL.  If it has the R or AL property, it is an RTL label; if it
9424   //     has the L property, it is an LTR label.
9425   //
9426   //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9427   //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9428   //
9429   //   3.  In an RTL label, the end of the label must be a character with
9430   //       Bidi property R, AL, EN, or AN, followed by zero or more
9431   //       characters with Bidi property NSM.
9432   //
9433   //   4.  In an RTL label, if an EN is present, no AN may be present, and
9434   //       vice versa.
9435   //
9436   //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9437   //       ES, CS, ET, ON, BN, or NSM are allowed.
9438   //
9439   //   6.  In an LTR label, the end of the label must be a character with
9440   //       Bidi property L or EN, followed by zero or more characters with
9441   //       Bidi property NSM.
9442 
9443   size_t last_non_nsm_char = find_last_not_of_nsm(label);
9444   if (last_non_nsm_char == std::u32string_view::npos) {
9445     return false;
9446   }
9447 
9448   // A "Bidi domain name" is a domain name that contains at least one RTL label.
9449   // The following rule, consisting of six conditions, applies to labels in Bidi
9450   // domain names.
9451   if (is_rtl_label(label)) {
9452     // The first character must be a character with Bidi property L, R,
9453     // or AL. If it has the R or AL property, it is an RTL label; if it
9454     // has the L property, it is an LTR label.
9455 
9456     if (find_direction(label[0]) == direction::L) {
9457       // Eval as LTR
9458 
9459       // In an LTR label, only characters with the Bidi properties L, EN,
9460       // ES, CS, ET, ON, BN, or NSM are allowed.
9461       for (size_t i = 0; i < last_non_nsm_char; i++) {
9462         const direction d = find_direction(label[i]);
9463         if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9464               d == direction::CS || d == direction::ET || d == direction::ON ||
9465               d == direction::BN || d == direction::NSM)) {
9466           return false;
9467         }
9468 
9469         if ((i == last_non_nsm_char) &&
9470             !(d == direction::L || d == direction::EN)) {
9471           return false;
9472         }
9473       }
9474 
9475       return true;
9476 
9477     } else {
9478       // Eval as RTL
9479 
9480       bool has_an = false;
9481       bool has_en = false;
9482       for (size_t i = 0; i <= last_non_nsm_char; i++) {
9483         const direction d = find_direction(label[i]);
9484 
9485         // In an RTL label, if an EN is present, no AN may be present, and vice
9486         // versa.
9487         if ((d == direction::EN && ((has_en = true) && has_an)) ||
9488             (d == direction::AN && ((has_an = true) && has_en))) {
9489           return false;
9490         }
9491 
9492         if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9493               d == direction::EN || d == direction::ES || d == direction::CS ||
9494               d == direction::ET || d == direction::ON || d == direction::BN ||
9495               d == direction::NSM)) {
9496           return false;
9497         }
9498 
9499         if (i == last_non_nsm_char &&
9500             !(d == direction::R || d == direction::AL || d == direction::AN ||
9501               d == direction::EN)) {
9502           return false;
9503         }
9504       }
9505 
9506       return true;
9507     }
9508   }
9509 
9510   return true;
9511 }
9512 
9513 }  // namespace ada::idna
9514 /* end file src/validity.cpp */
9515 /* begin file src/to_ascii.cpp */
9516 
9517 #include <algorithm>
9518 #include <cstdint>
9519 
9520 
9521 namespace ada::idna {
9522 
begins_with(std::u32string_view view,std::u32string_view prefix)9523 bool constexpr begins_with(std::u32string_view view,
9524                            std::u32string_view prefix) {
9525   if (view.size() < prefix.size()) {
9526     return false;
9527   }
9528   return view.substr(0, prefix.size()) == prefix;
9529 }
9530 
begins_with(std::string_view view,std::string_view prefix)9531 bool constexpr begins_with(std::string_view view, std::string_view prefix) {
9532   if (view.size() < prefix.size()) {
9533     return false;
9534   }
9535   return view.substr(0, prefix.size()) == prefix;
9536 }
9537 
is_ascii(std::u32string_view view)9538 bool constexpr is_ascii(std::u32string_view view) {
9539   for (uint32_t c : view) {
9540     if (c >= 0x80) {
9541       return false;
9542     }
9543   }
9544   return true;
9545 }
9546 
is_ascii(std::string_view view)9547 bool constexpr is_ascii(std::string_view view) {
9548   for (uint8_t c : view) {
9549     if (c >= 0x80) {
9550       return false;
9551     }
9552   }
9553   return true;
9554 }
9555 
9556 constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9557     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9558     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9559     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9560     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9561     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9562     0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9563     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9564     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9565     1, 1, 1, 1, 1, 1, 1, 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};
9568 
9569 static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9570 
is_forbidden_domain_code_point(const char c)9571 inline bool is_forbidden_domain_code_point(const char c) noexcept {
9572   return is_forbidden_domain_code_point_table[uint8_t(c)];
9573 }
9574 
contains_forbidden_domain_code_point(std::string_view view)9575 bool contains_forbidden_domain_code_point(std::string_view view) {
9576   return (
9577       std::any_of(view.begin(), view.end(), is_forbidden_domain_code_point));
9578 }
9579 
9580 // We return "" on error.
from_ascii_to_ascii(std::string_view ut8_string)9581 static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9582   static const std::string error = "";
9583   // copy and map
9584   // we could be more efficient by avoiding the copy when unnecessary.
9585   std::string mapped_string = std::string(ut8_string);
9586   ascii_map(mapped_string.data(), mapped_string.size());
9587   std::string out;
9588   size_t label_start = 0;
9589 
9590   while (label_start != mapped_string.size()) {
9591     size_t loc_dot = mapped_string.find('.', label_start);
9592     bool is_last_label = (loc_dot == std::string_view::npos);
9593     size_t label_size = is_last_label ? mapped_string.size() - label_start
9594                                       : loc_dot - label_start;
9595     size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9596     std::string_view label_view(mapped_string.data() + label_start, label_size);
9597     label_start += label_size_with_dot;
9598     if (label_size == 0) {
9599       // empty label? Nothing to do.
9600     } else if (begins_with(label_view, "xn--")) {
9601       // The xn-- part is the expensive game.
9602       out.append(label_view);
9603       std::string_view puny_segment_ascii(
9604           out.data() + out.size() - label_view.size() + 4,
9605           label_view.size() - 4);
9606       std::u32string tmp_buffer;
9607       bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9608       if (!is_ok) {
9609         return error;
9610       }
9611       std::u32string post_map = ada::idna::map(tmp_buffer);
9612       if (tmp_buffer != post_map) {
9613         return error;
9614       }
9615       std::u32string pre_normal = post_map;
9616       normalize(post_map);
9617       if (post_map != pre_normal) {
9618         return error;
9619       }
9620       if (post_map.empty()) {
9621         return error;
9622       }
9623       if (!is_label_valid(post_map)) {
9624         return error;
9625       }
9626     } else {
9627       out.append(label_view);
9628     }
9629     if (!is_last_label) {
9630       out.push_back('.');
9631     }
9632   }
9633   return out;
9634 }
9635 
9636 // We return "" on error.
to_ascii(std::string_view ut8_string)9637 std::string to_ascii(std::string_view ut8_string) {
9638   if (is_ascii(ut8_string)) {
9639     return from_ascii_to_ascii(ut8_string);
9640   }
9641   static const std::string error = "";
9642   // We convert to UTF-32
9643   size_t utf32_length =
9644       ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9645   std::u32string utf32(utf32_length, '\0');
9646   size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9647       ut8_string.data(), ut8_string.size(), utf32.data());
9648   if (actual_utf32_length == 0) {
9649     return error;
9650   }
9651   // mapping
9652   utf32 = ada::idna::map(utf32);
9653   normalize(utf32);
9654   std::string out;
9655   size_t label_start = 0;
9656 
9657   while (label_start != utf32.size()) {
9658     size_t loc_dot = utf32.find('.', label_start);
9659     bool is_last_label = (loc_dot == std::string_view::npos);
9660     size_t label_size =
9661         is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9662     size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9663     std::u32string_view label_view(utf32.data() + label_start, label_size);
9664     label_start += label_size_with_dot;
9665     if (label_size == 0) {
9666       // empty label? Nothing to do.
9667     } else if (begins_with(label_view, U"xn--")) {
9668       // we do not need to check, e.g., Xn-- because mapping goes to lower case
9669       for (char32_t c : label_view) {
9670         if (c >= 0x80) {
9671           return error;
9672         }
9673         out += (unsigned char)(c);
9674       }
9675       std::string_view puny_segment_ascii(
9676           out.data() + out.size() - label_view.size() + 4,
9677           label_view.size() - 4);
9678       std::u32string tmp_buffer;
9679       bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9680       if (!is_ok) {
9681         return error;
9682       }
9683       std::u32string post_map = ada::idna::map(tmp_buffer);
9684       if (tmp_buffer != post_map) {
9685         return error;
9686       }
9687       std::u32string pre_normal = post_map;
9688       normalize(post_map);
9689       if (post_map != pre_normal) {
9690         return error;
9691       }
9692       if (post_map.empty()) {
9693         return error;
9694       }
9695       if (!is_label_valid(post_map)) {
9696         return error;
9697       }
9698     } else {
9699       // The fast path here is an ascii label.
9700       if (is_ascii(label_view)) {
9701         // no validation needed.
9702         for (char32_t c : label_view) {
9703           out += (unsigned char)(c);
9704         }
9705       } else {
9706         // slow path.
9707         // first check validity.
9708         if (!is_label_valid(label_view)) {
9709           return error;
9710         }
9711         // It is valid! So now we must encode it as punycode...
9712         out.append("xn--");
9713         bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9714         if (!is_ok) {
9715           return error;
9716         }
9717       }
9718     }
9719     if (!is_last_label) {
9720       out.push_back('.');
9721     }
9722   }
9723   return out;
9724 }
9725 }  // namespace ada::idna
9726 /* end file src/to_ascii.cpp */
9727 /* begin file src/to_unicode.cpp */
9728 
9729 #include <algorithm>
9730 #include <string>
9731 
9732 
9733 namespace ada::idna {
to_unicode(std::string_view input)9734 std::string to_unicode(std::string_view input) {
9735   std::string output;
9736   output.reserve(input.size());
9737 
9738   size_t label_start = 0;
9739   while (label_start < input.size()) {
9740     size_t loc_dot = input.find('.', label_start);
9741     bool is_last_label = (loc_dot == std::string_view::npos);
9742     size_t label_size =
9743         is_last_label ? input.size() - label_start : loc_dot - label_start;
9744     auto label_view = std::string_view(input.data() + label_start, label_size);
9745 
9746     if (ada::idna::begins_with(label_view, "xn--") &&
9747         ada::idna::is_ascii(label_view)) {
9748       label_view.remove_prefix(4);
9749       if (ada::idna::verify_punycode(label_view)) {
9750         std::u32string tmp_buffer;
9751         if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9752           auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9753                                                              tmp_buffer.size());
9754           std::string final_utf8(utf8_size, '\0');
9755           ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9756                                    final_utf8.data());
9757           output.append(final_utf8);
9758         } else {
9759           // ToUnicode never fails.  If any step fails, then the original input
9760           // sequence is returned immediately in that step.
9761           output.append(
9762               std::string_view(input.data() + label_start, label_size));
9763         }
9764       } else {
9765         output.append(std::string_view(input.data() + label_start, label_size));
9766       }
9767     } else {
9768       output.append(label_view);
9769     }
9770 
9771     if (!is_last_label) {
9772       output.push_back('.');
9773     }
9774 
9775     label_start += label_size + 1;
9776   }
9777 
9778   return output;
9779 }
9780 }  // namespace ada::idna
9781 /* end file src/to_unicode.cpp */
9782 /* end file src/idna.cpp */
9783 /* end file src/ada_idna.cpp */
9784 ADA_POP_DISABLE_WARNINGS
9785 
9786 #include <algorithm>
9787 #if ADA_NEON
9788 #include <arm_neon.h>
9789 #elif ADA_SSE2
9790 #include <emmintrin.h>
9791 #endif
9792 
9793 namespace ada::unicode {
9794 
broadcast(uint8_t v)9795 constexpr uint64_t broadcast(uint8_t v) noexcept {
9796   return 0x101010101010101ull * v;
9797 }
9798 
to_lower_ascii(char * input,size_t length)9799 constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
9800   uint64_t broadcast_80 = broadcast(0x80);
9801   uint64_t broadcast_Ap = broadcast(128 - 'A');
9802   uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
9803   uint64_t non_ascii = 0;
9804   size_t i = 0;
9805 
9806   for (; i + 7 < length; i += 8) {
9807     uint64_t word{};
9808     memcpy(&word, input + i, sizeof(word));
9809     non_ascii |= (word & broadcast_80);
9810     word ^=
9811         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9812     memcpy(input + i, &word, sizeof(word));
9813   }
9814   if (i < length) {
9815     uint64_t word{};
9816     memcpy(&word, input + i, length - i);
9817     non_ascii |= (word & broadcast_80);
9818     word ^=
9819         (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
9820     memcpy(input + i, &word, length - i);
9821   }
9822   return non_ascii == 0;
9823 }
9824 #if ADA_NEON
has_tabs_or_newline(std::string_view user_input)9825 ada_really_inline bool has_tabs_or_newline(
9826     std::string_view user_input) noexcept {
9827   size_t i = 0;
9828   const uint8x16_t mask1 = vmovq_n_u8('\r');
9829   const uint8x16_t mask2 = vmovq_n_u8('\n');
9830   const uint8x16_t mask3 = vmovq_n_u8('\t');
9831   uint8x16_t running{0};
9832   for (; i + 15 < user_input.size(); i += 16) {
9833     uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
9834     running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9835                                                   vceqq_u8(word, mask2))),
9836                        vceqq_u8(word, mask3));
9837   }
9838   if (i < user_input.size()) {
9839     uint8_t buffer[16]{};
9840     memcpy(buffer, user_input.data() + i, user_input.size() - i);
9841     uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
9842     running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1),
9843                                                   vceqq_u8(word, mask2))),
9844                        vceqq_u8(word, mask3));
9845   }
9846   return vmaxvq_u8(running) != 0;
9847 }
9848 #elif ADA_SSE2
has_tabs_or_newline(std::string_view user_input)9849 ada_really_inline bool has_tabs_or_newline(
9850     std::string_view user_input) noexcept {
9851   size_t i = 0;
9852   const __m128i mask1 = _mm_set1_epi8('\r');
9853   const __m128i mask2 = _mm_set1_epi8('\n');
9854   const __m128i mask3 = _mm_set1_epi8('\t');
9855   __m128i running{0};
9856   for (; i + 15 < user_input.size(); i += 16) {
9857     __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
9858     running = _mm_or_si128(
9859         _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9860                                            _mm_cmpeq_epi8(word, mask2))),
9861         _mm_cmpeq_epi8(word, mask3));
9862   }
9863   if (i < user_input.size()) {
9864     alignas(16) uint8_t buffer[16]{};
9865     memcpy(buffer, user_input.data() + i, user_input.size() - i);
9866     __m128i word = _mm_load_si128((const __m128i*)buffer);
9867     running = _mm_or_si128(
9868         _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
9869                                            _mm_cmpeq_epi8(word, mask2))),
9870         _mm_cmpeq_epi8(word, mask3));
9871   }
9872   return _mm_movemask_epi8(running) != 0;
9873 }
9874 #else
has_tabs_or_newline(std::string_view user_input)9875 ada_really_inline bool has_tabs_or_newline(
9876     std::string_view user_input) noexcept {
9877   auto has_zero_byte = [](uint64_t v) {
9878     return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
9879   };
9880   size_t i = 0;
9881   uint64_t mask1 = broadcast('\r');
9882   uint64_t mask2 = broadcast('\n');
9883   uint64_t mask3 = broadcast('\t');
9884   uint64_t running{0};
9885   for (; i + 7 < user_input.size(); i += 8) {
9886     uint64_t word{};
9887     memcpy(&word, user_input.data() + i, sizeof(word));
9888     uint64_t xor1 = word ^ mask1;
9889     uint64_t xor2 = word ^ mask2;
9890     uint64_t xor3 = word ^ mask3;
9891     running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9892   }
9893   if (i < user_input.size()) {
9894     uint64_t word{};
9895     memcpy(&word, user_input.data() + i, user_input.size() - i);
9896     uint64_t xor1 = word ^ mask1;
9897     uint64_t xor2 = word ^ mask2;
9898     uint64_t xor3 = word ^ mask3;
9899     running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
9900   }
9901   return running;
9902 }
9903 #endif
9904 
9905 // A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
9906 // U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
9907 // U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
9908 // U+007C (|).
9909 constexpr static bool is_forbidden_host_code_point_table[] = {
9910     1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9911     0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9912     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9913     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9914     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9915     0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9916     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9917     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9918     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9919     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9920     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
9921 static_assert(sizeof(is_forbidden_host_code_point_table) == 256);
9922 
is_forbidden_host_code_point(const char c)9923 ada_really_inline constexpr bool is_forbidden_host_code_point(
9924     const char c) noexcept {
9925   return is_forbidden_host_code_point_table[uint8_t(c)];
9926 }
9927 
9928 static_assert(unicode::is_forbidden_host_code_point('\0'));
9929 static_assert(unicode::is_forbidden_host_code_point('\t'));
9930 static_assert(unicode::is_forbidden_host_code_point('\n'));
9931 static_assert(unicode::is_forbidden_host_code_point('\r'));
9932 static_assert(unicode::is_forbidden_host_code_point(' '));
9933 static_assert(unicode::is_forbidden_host_code_point('#'));
9934 static_assert(unicode::is_forbidden_host_code_point('/'));
9935 static_assert(unicode::is_forbidden_host_code_point(':'));
9936 static_assert(unicode::is_forbidden_host_code_point('?'));
9937 static_assert(unicode::is_forbidden_host_code_point('@'));
9938 static_assert(unicode::is_forbidden_host_code_point('['));
9939 static_assert(unicode::is_forbidden_host_code_point('?'));
9940 static_assert(unicode::is_forbidden_host_code_point('<'));
9941 static_assert(unicode::is_forbidden_host_code_point('>'));
9942 static_assert(unicode::is_forbidden_host_code_point('\\'));
9943 static_assert(unicode::is_forbidden_host_code_point(']'));
9944 static_assert(unicode::is_forbidden_host_code_point('^'));
9945 static_assert(unicode::is_forbidden_host_code_point('|'));
9946 
9947 constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9948     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9949     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9950     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9951     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9952     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9953     0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9954     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9955     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9956     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9957     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9958     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9959 
9960 static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9961 
is_forbidden_domain_code_point(const char c)9962 ada_really_inline constexpr bool is_forbidden_domain_code_point(
9963     const char c) noexcept {
9964   return is_forbidden_domain_code_point_table[uint8_t(c)];
9965 }
9966 
contains_forbidden_domain_code_point(const char * input,size_t length)9967 ada_really_inline constexpr bool contains_forbidden_domain_code_point(
9968     const char* input, size_t length) noexcept {
9969   size_t i = 0;
9970   uint8_t accumulator{};
9971   for (; i + 4 <= length; i += 4) {
9972     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9973     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
9974     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
9975     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
9976   }
9977   for (; i < length; i++) {
9978     accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
9979   }
9980   return accumulator;
9981 }
9982 
9983 constexpr static uint8_t is_forbidden_domain_code_point_table_or_upper[] = {
9984     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9985     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9986     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
9987     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0,
9988     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9989     0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9990     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9991     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9992     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9993     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9994     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9995 
9996 static_assert(sizeof(is_forbidden_domain_code_point_table_or_upper) == 256);
9997 static_assert(is_forbidden_domain_code_point_table_or_upper[uint8_t('A')] == 2);
9998 static_assert(is_forbidden_domain_code_point_table_or_upper[uint8_t('Z')] == 2);
9999 
10000 ada_really_inline constexpr uint8_t
contains_forbidden_domain_code_point_or_upper(const char * input,size_t length)10001 contains_forbidden_domain_code_point_or_upper(const char* input,
10002                                               size_t length) noexcept {
10003   size_t i = 0;
10004   uint8_t accumulator{};
10005   for (; i + 4 <= length; i += 4) {
10006     accumulator |=
10007         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10008     accumulator |=
10009         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10010     accumulator |=
10011         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10012     accumulator |=
10013         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10014   }
10015   for (; i < length; i++) {
10016     accumulator |=
10017         is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10018   }
10019   return accumulator;
10020 }
10021 
10022 static_assert(unicode::is_forbidden_domain_code_point('%'));
10023 static_assert(unicode::is_forbidden_domain_code_point('\x7f'));
10024 static_assert(unicode::is_forbidden_domain_code_point('\0'));
10025 static_assert(unicode::is_forbidden_domain_code_point('\t'));
10026 static_assert(unicode::is_forbidden_domain_code_point('\n'));
10027 static_assert(unicode::is_forbidden_domain_code_point('\r'));
10028 static_assert(unicode::is_forbidden_domain_code_point(' '));
10029 static_assert(unicode::is_forbidden_domain_code_point('#'));
10030 static_assert(unicode::is_forbidden_domain_code_point('/'));
10031 static_assert(unicode::is_forbidden_domain_code_point(':'));
10032 static_assert(unicode::is_forbidden_domain_code_point('?'));
10033 static_assert(unicode::is_forbidden_domain_code_point('@'));
10034 static_assert(unicode::is_forbidden_domain_code_point('['));
10035 static_assert(unicode::is_forbidden_domain_code_point('?'));
10036 static_assert(unicode::is_forbidden_domain_code_point('<'));
10037 static_assert(unicode::is_forbidden_domain_code_point('>'));
10038 static_assert(unicode::is_forbidden_domain_code_point('\\'));
10039 static_assert(unicode::is_forbidden_domain_code_point(']'));
10040 static_assert(unicode::is_forbidden_domain_code_point('^'));
10041 static_assert(unicode::is_forbidden_domain_code_point('|'));
10042 
10043 constexpr static bool is_alnum_plus_table[] = {
10044     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10045     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0,
10046     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
10047     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
10048     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
10049     1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10050     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10051     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10052     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10053     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10054     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
10055 
10056 static_assert(sizeof(is_alnum_plus_table) == 256);
10057 
is_alnum_plus(const char c)10058 ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10059   return is_alnum_plus_table[uint8_t(c)];
10060   // A table is almost surely much faster than the
10061   // following under most compilers: return
10062   // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10063 }
10064 static_assert(unicode::is_alnum_plus('+'));
10065 static_assert(unicode::is_alnum_plus('-'));
10066 static_assert(unicode::is_alnum_plus('.'));
10067 static_assert(unicode::is_alnum_plus('0'));
10068 static_assert(unicode::is_alnum_plus('1'));
10069 static_assert(unicode::is_alnum_plus('a'));
10070 static_assert(unicode::is_alnum_plus('b'));
10071 
is_ascii_hex_digit(const char c)10072 ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10073   return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10074          (c >= 'a' && c <= 'f');
10075 }
10076 
is_c0_control_or_space(const char c)10077 ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10078   return (unsigned char)c <= ' ';
10079 }
10080 
is_ascii_tab_or_newline(const char c)10081 ada_really_inline constexpr bool is_ascii_tab_or_newline(
10082     const char c) noexcept {
10083   return c == '\t' || c == '\n' || c == '\r';
10084 }
10085 
10086 constexpr std::string_view table_is_double_dot_path_segment[] = {
10087     "..", "%2e.", ".%2e", "%2e%2e"};
10088 
is_double_dot_path_segment(std::string_view input)10089 ada_really_inline ada_constexpr bool is_double_dot_path_segment(
10090     std::string_view input) noexcept {
10091   // This will catch most cases:
10092   // The length must be 2,4 or 6.
10093   // We divide by two and require
10094   // that the result be between 1 and 3 inclusively.
10095   uint64_t half_length = uint64_t(input.size()) / 2;
10096   if (half_length - 1 > 2) {
10097     return false;
10098   }
10099   // We have a string of length 2, 4 or 6.
10100   // We now check the first character:
10101   if ((input[0] != '.') && (input[0] != '%')) {
10102     return false;
10103   }
10104   // We are unlikely the get beyond this point.
10105   int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10106   const std::string_view target = table_is_double_dot_path_segment[hash_value];
10107   if (target.size() != input.size()) {
10108     return false;
10109   }
10110   // We almost never get here.
10111   // Optimizing the rest is relatively unimportant.
10112   auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10113     uint16_t A, B;
10114     memcpy(&A, a.data(), sizeof(A));
10115     memcpy(&B, b.data(), sizeof(B));
10116     return A == B;
10117   };
10118   if (!prefix_equal_unsafe(input, target)) {
10119     return false;
10120   }
10121   for (size_t i = 2; i < input.size(); i++) {
10122     char c = input[i];
10123     if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10124       return false;
10125     }
10126   }
10127   return true;
10128   // The above code might be a bit better than the code below. Compilers
10129   // are not stupid and may use the fact that these strings have length 2,4 and
10130   // 6 and other tricks.
10131   // return input == ".." ||
10132   //  input == ".%2e" || input == ".%2E" ||
10133   //  input == "%2e." || input == "%2E." ||
10134   //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10135   //  "%2e%2E";
10136 }
10137 
is_single_dot_path_segment(std::string_view input)10138 ada_really_inline constexpr bool is_single_dot_path_segment(
10139     std::string_view input) noexcept {
10140   return input == "." || input == "%2e" || input == "%2E";
10141 }
10142 
is_lowercase_hex(const char c)10143 ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10144   return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10145 }
10146 
convert_hex_to_binary(const char c)10147 unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10148   // this code can be optimized.
10149   if (c <= '9') {
10150     return c - '0';
10151   }
10152   char del = c >= 'a' ? 'a' : 'A';
10153   return 10 + (c - del);
10154 }
10155 
percent_decode(const std::string_view input,size_t first_percent)10156 std::string percent_decode(const std::string_view input, size_t first_percent) {
10157   // next line is for safety only, we expect users to avoid calling
10158   // percent_decode when first_percent is outside the range.
10159   if (first_percent == std::string_view::npos) {
10160     return std::string(input);
10161   }
10162   std::string dest(input.substr(0, first_percent));
10163   dest.reserve(input.length());
10164   const char* pointer = input.data() + first_percent;
10165   const char* end = input.data() + input.size();
10166   // Optimization opportunity: if the following code gets
10167   // called often, it can be optimized quite a bit.
10168   while (pointer < end) {
10169     const char ch = pointer[0];
10170     size_t remaining = end - pointer - 1;
10171     if (ch != '%' || remaining < 2 ||
10172         (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10173             (!is_ascii_hex_digit(pointer[1]) ||
10174              !is_ascii_hex_digit(pointer[2])))) {
10175       dest += ch;
10176       pointer++;
10177       continue;
10178     } else {
10179       unsigned a = convert_hex_to_binary(pointer[1]);
10180       unsigned b = convert_hex_to_binary(pointer[2]);
10181       char c = static_cast<char>(a * 16 + b);
10182       dest += c;
10183       pointer += 3;
10184     }
10185   }
10186   return dest;
10187 }
10188 
percent_encode(const std::string_view input,const uint8_t character_set[])10189 std::string percent_encode(const std::string_view input,
10190                            const uint8_t character_set[]) {
10191   auto pointer =
10192       std::find_if(input.begin(), input.end(), [character_set](const char c) {
10193         return character_sets::bit_at(character_set, c);
10194       });
10195   // Optimization: Don't iterate if percent encode is not required
10196   if (pointer == input.end()) {
10197     return std::string(input);
10198   }
10199 
10200   std::string result(input.substr(0, std::distance(input.begin(), pointer)));
10201   result.reserve(input.length());  // in the worst case, percent encoding might
10202                                    // produce 3 characters.
10203 
10204   for (; pointer != input.end(); pointer++) {
10205     if (character_sets::bit_at(character_set, *pointer)) {
10206       result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10207     } else {
10208       result += *pointer;
10209     }
10210   }
10211 
10212   return result;
10213 }
10214 
10215 template <bool append>
percent_encode(const std::string_view input,const uint8_t character_set[],std::string & out)10216 bool percent_encode(const std::string_view input, const uint8_t character_set[],
10217                     std::string& out) {
10218   ada_log("percent_encode ", input, " to output string while ",
10219           append ? "appending" : "overwriting");
10220   auto pointer =
10221       std::find_if(input.begin(), input.end(), [character_set](const char c) {
10222         return character_sets::bit_at(character_set, c);
10223       });
10224   ada_log("percent_encode done checking, moved to ",
10225           std::distance(input.begin(), pointer));
10226 
10227   // Optimization: Don't iterate if percent encode is not required
10228   if (pointer == input.end()) {
10229     ada_log("percent_encode encoding not needed.");
10230     return false;
10231   }
10232   if (!append) {
10233     out.clear();
10234   }
10235   ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10236           " bytes");
10237   out.append(input.data(), std::distance(input.begin(), pointer));
10238   ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10239           " bytes");
10240   for (; pointer != input.end(); pointer++) {
10241     if (character_sets::bit_at(character_set, *pointer)) {
10242       out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10243     } else {
10244       out += *pointer;
10245     }
10246   }
10247   return true;
10248 }
10249 
to_ascii(std::optional<std::string> & out,const std::string_view plain,size_t first_percent)10250 bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10251               size_t first_percent) {
10252   std::string percent_decoded_buffer;
10253   std::string_view input = plain;
10254   if (first_percent != std::string_view::npos) {
10255     percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10256     input = percent_decoded_buffer;
10257   }
10258   // input is a non-empty UTF-8 string, must be percent decoded
10259   std::string idna_ascii = ada::idna::to_ascii(input);
10260   if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10261                                 idna_ascii.data(), idna_ascii.size())) {
10262     return false;
10263   }
10264   out = std::move(idna_ascii);
10265   return true;
10266 }
10267 
percent_encode(const std::string_view input,const uint8_t character_set[],size_t index)10268 std::string percent_encode(const std::string_view input,
10269                            const uint8_t character_set[], size_t index) {
10270   std::string out;
10271   out.append(input.data(), index);
10272   auto pointer = input.begin() + index;
10273   for (; pointer != input.end(); pointer++) {
10274     if (character_sets::bit_at(character_set, *pointer)) {
10275       out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10276     } else {
10277       out += *pointer;
10278     }
10279   }
10280   return out;
10281 }
10282 
to_unicode(std::string_view input)10283 std::string to_unicode(std::string_view input) {
10284   return ada::idna::to_unicode(input);
10285 }
10286 
10287 }  // namespace ada::unicode
10288 /* end file src/unicode.cpp */
10289 /* begin file src/serializers.cpp */
10290 
10291 #include <array>
10292 #include <string>
10293 
10294 namespace ada::serializers {
10295 
find_longest_sequence_of_ipv6_pieces(const std::array<uint16_t,8> & address,size_t & compress,size_t & compress_length)10296 void find_longest_sequence_of_ipv6_pieces(
10297     const std::array<uint16_t, 8>& address, size_t& compress,
10298     size_t& compress_length) noexcept {
10299   for (size_t i = 0; i < 8; i++) {
10300     if (address[i] == 0) {
10301       size_t next = i + 1;
10302       while (next != 8 && address[next] == 0) ++next;
10303       const size_t count = next - i;
10304       if (compress_length < count) {
10305         compress_length = count;
10306         compress = i;
10307         if (next == 8) break;
10308         i = next;
10309       }
10310     }
10311   }
10312 }
10313 
ipv6(const std::array<uint16_t,8> & address)10314 std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
10315   size_t compress_length = 0;  // The length of a long sequence of zeros.
10316   size_t compress = 0;         // The start of a long sequence of zeros.
10317   find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
10318 
10319   if (compress_length <= 1) {
10320     // Optimization opportunity: Find a faster way then snprintf for imploding
10321     // and return here.
10322     compress = compress_length = 8;
10323   }
10324 
10325   std::string output(4 * 8 + 7 + 2, '\0');
10326   size_t piece_index = 0;
10327   char* point = output.data();
10328   char* point_end = output.data() + output.size();
10329   *point++ = '[';
10330   while (true) {
10331     if (piece_index == compress) {
10332       *point++ = ':';
10333       // If we skip a value initially, we need to write '::', otherwise
10334       // a single ':' will do since it follows a previous ':'.
10335       if (piece_index == 0) {
10336         *point++ = ':';
10337       }
10338       piece_index += compress_length;
10339       if (piece_index == 8) {
10340         break;
10341       }
10342     }
10343     point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
10344     piece_index++;
10345     if (piece_index == 8) {
10346       break;
10347     }
10348     *point++ = ':';
10349   }
10350   *point++ = ']';
10351   output.resize(point - output.data());
10352   return output;
10353 }
10354 
ipv4(const uint64_t address)10355 std::string ipv4(const uint64_t address) noexcept {
10356   std::string output(15, '\0');
10357   char* point = output.data();
10358   char* point_end = output.data() + output.size();
10359   point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
10360   for (int i = 2; i >= 0; i--) {
10361     *point++ = '.';
10362     point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
10363   }
10364   output.resize(point - output.data());
10365   return output;
10366 }
10367 
10368 }  // namespace ada::serializers
10369 /* end file src/serializers.cpp */
10370 /* begin file src/implementation.cpp */
10371 #include <string_view>
10372 
10373 
10374 namespace ada {
10375 
10376 template <class result_type>
parse(std::string_view input,const result_type * base_url)10377 ada_warn_unused tl::expected<result_type, ada::errors> parse(
10378     std::string_view input, const result_type* base_url) {
10379   result_type u = ada::parser::parse_url<result_type>(input, base_url);
10380   if (!u.is_valid) {
10381     return tl::unexpected(errors::generic_error);
10382   }
10383   return u;
10384 }
10385 
10386 template ada::result<url> parse<url>(std::string_view input,
10387                                      const url* base_url = nullptr);
10388 template ada::result<url_aggregator> parse<url_aggregator>(
10389     std::string_view input, const url_aggregator* base_url = nullptr);
10390 
href_from_file(std::string_view input)10391 std::string href_from_file(std::string_view input) {
10392   // This is going to be much faster than constructing a URL.
10393   std::string tmp_buffer;
10394   std::string_view internal_input;
10395   if (unicode::has_tabs_or_newline(input)) {
10396     tmp_buffer = input;
10397     helpers::remove_ascii_tab_or_newline(tmp_buffer);
10398     internal_input = tmp_buffer;
10399   } else {
10400     internal_input = input;
10401   }
10402   std::string path;
10403   if (internal_input.empty()) {
10404     path = "/";
10405   } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
10406     helpers::parse_prepared_path(internal_input.substr(1),
10407                                  ada::scheme::type::FILE, path);
10408   } else {
10409     helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
10410   }
10411   return "file://" + path;
10412 }
10413 
can_parse(std::string_view input,const std::string_view * base_input)10414 bool can_parse(std::string_view input, const std::string_view* base_input) {
10415   ada::result<ada::url_aggregator> base;
10416   ada::url_aggregator* base_pointer = nullptr;
10417   if (base_input != nullptr) {
10418     base = ada::parse<url_aggregator>(*base_input);
10419     if (!base) {
10420       return false;
10421     }
10422     base_pointer = &base.value();
10423   }
10424   return ada::parse<url_aggregator>(input, base_pointer).has_value();
10425 }
10426 
to_string(ada::encoding_type type)10427 ada_warn_unused std::string to_string(ada::encoding_type type) {
10428   switch (type) {
10429     case ada::encoding_type::UTF8:
10430       return "UTF-8";
10431     case ada::encoding_type::UTF_16LE:
10432       return "UTF-16LE";
10433     case ada::encoding_type::UTF_16BE:
10434       return "UTF-16BE";
10435     default:
10436       unreachable();
10437   }
10438 }
10439 
10440 }  // namespace ada
10441 /* end file src/implementation.cpp */
10442 /* begin file src/helpers.cpp */
10443 
10444 #include <algorithm>
10445 #include <charconv>
10446 #include <cstring>
10447 #include <sstream>
10448 
10449 namespace ada::helpers {
10450 
10451 template <typename out_iter>
encode_json(std::string_view view,out_iter out)10452 void encode_json(std::string_view view, out_iter out) {
10453   // trivial implementation. could be faster.
10454   const char* hexvalues =
10455       "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
10456   for (uint8_t c : view) {
10457     if (c == '\\') {
10458       *out++ = '\\';
10459       *out++ = '\\';
10460     } else if (c == '"') {
10461       *out++ = '\\';
10462       *out++ = '"';
10463     } else if (c <= 0x1f) {
10464       *out++ = '\\';
10465       *out++ = 'u';
10466       *out++ = '0';
10467       *out++ = '0';
10468       *out++ = hexvalues[2 * c];
10469       *out++ = hexvalues[2 * c + 1];
10470     } else {
10471       *out++ = c;
10472     }
10473   }
10474 }
10475 
get_state(ada::state s)10476 ada_unused std::string get_state(ada::state s) {
10477   switch (s) {
10478     case ada::state::AUTHORITY:
10479       return "Authority";
10480     case ada::state::SCHEME_START:
10481       return "Scheme Start";
10482     case ada::state::SCHEME:
10483       return "Scheme";
10484     case ada::state::HOST:
10485       return "Host";
10486     case ada::state::NO_SCHEME:
10487       return "No Scheme";
10488     case ada::state::FRAGMENT:
10489       return "Fragment";
10490     case ada::state::RELATIVE_SCHEME:
10491       return "Relative Scheme";
10492     case ada::state::RELATIVE_SLASH:
10493       return "Relative Slash";
10494     case ada::state::FILE:
10495       return "File";
10496     case ada::state::FILE_HOST:
10497       return "File Host";
10498     case ada::state::FILE_SLASH:
10499       return "File Slash";
10500     case ada::state::PATH_OR_AUTHORITY:
10501       return "Path or Authority";
10502     case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
10503       return "Special Authority Ignore Slashes";
10504     case ada::state::SPECIAL_AUTHORITY_SLASHES:
10505       return "Special Authority Slashes";
10506     case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
10507       return "Special Relative or Authority";
10508     case ada::state::QUERY:
10509       return "Query";
10510     case ada::state::PATH:
10511       return "Path";
10512     case ada::state::PATH_START:
10513       return "Path Start";
10514     case ada::state::OPAQUE_PATH:
10515       return "Opaque Path";
10516     case ada::state::PORT:
10517       return "Port";
10518     default:
10519       return "unknown state";
10520   }
10521 }
10522 
prune_hash(std::string_view & input)10523 ada_really_inline std::optional<std::string_view> prune_hash(
10524     std::string_view& input) noexcept {
10525   // compiles down to 20--30 instructions including a class to memchr (C
10526   // function). this function should be quite fast.
10527   size_t location_of_first = input.find('#');
10528   if (location_of_first == std::string_view::npos) {
10529     return std::nullopt;
10530   }
10531   std::string_view hash = input;
10532   hash.remove_prefix(location_of_first + 1);
10533   input.remove_suffix(input.size() - location_of_first);
10534   return hash;
10535 }
10536 
shorten_path(std::string & path,ada::scheme::type type)10537 ada_really_inline bool shorten_path(std::string& path,
10538                                     ada::scheme::type type) noexcept {
10539   size_t first_delimiter = path.find_first_of('/', 1);
10540 
10541   // Let path be url's path.
10542   // If url's scheme is "file", path's size is 1, and path[0] is a normalized
10543   // Windows drive letter, then return.
10544   if (type == ada::scheme::type::FILE &&
10545       first_delimiter == std::string_view::npos && !path.empty()) {
10546     if (checkers::is_normalized_windows_drive_letter(
10547             helpers::substring(path, 1))) {
10548       return false;
10549     }
10550   }
10551 
10552   // Remove path's last item, if any.
10553   size_t last_delimiter = path.rfind('/');
10554   if (last_delimiter != std::string::npos) {
10555     path.erase(last_delimiter);
10556     return true;
10557   }
10558 
10559   return false;
10560 }
10561 
shorten_path(std::string_view & path,ada::scheme::type type)10562 ada_really_inline bool shorten_path(std::string_view& path,
10563                                     ada::scheme::type type) noexcept {
10564   size_t first_delimiter = path.find_first_of('/', 1);
10565 
10566   // Let path be url's path.
10567   // If url's scheme is "file", path's size is 1, and path[0] is a normalized
10568   // Windows drive letter, then return.
10569   if (type == ada::scheme::type::FILE &&
10570       first_delimiter == std::string_view::npos && !path.empty()) {
10571     if (checkers::is_normalized_windows_drive_letter(
10572             helpers::substring(path, 1))) {
10573       return false;
10574     }
10575   }
10576 
10577   // Remove path's last item, if any.
10578   if (!path.empty()) {
10579     size_t slash_loc = path.rfind('/');
10580     if (slash_loc != std::string_view::npos) {
10581       path.remove_suffix(path.size() - slash_loc);
10582       return true;
10583     }
10584   }
10585 
10586   return false;
10587 }
10588 
remove_ascii_tab_or_newline(std::string & input)10589 ada_really_inline void remove_ascii_tab_or_newline(
10590     std::string& input) noexcept {
10591   // if this ever becomes a performance issue, we could use an approach similar
10592   // to has_tabs_or_newline
10593   input.erase(std::remove_if(input.begin(), input.end(),
10594                              [](char c) {
10595                                return ada::unicode::is_ascii_tab_or_newline(c);
10596                              }),
10597               input.end());
10598 }
10599 
substring(std::string_view input,size_t pos)10600 ada_really_inline std::string_view substring(std::string_view input,
10601                                              size_t pos) noexcept {
10602   ADA_ASSERT_TRUE(pos <= input.size());
10603   // The following is safer but unneeded if we have the above line:
10604   // return pos > input.size() ? std::string_view() : input.substr(pos);
10605   return input.substr(pos);
10606 }
10607 
resize(std::string_view & input,size_t pos)10608 ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
10609   ADA_ASSERT_TRUE(pos <= input.size());
10610   input.remove_suffix(input.size() - pos);
10611 }
10612 
10613 // Reverse the byte order.
swap_bytes(uint64_t val)10614 ada_really_inline uint64_t swap_bytes(uint64_t val) noexcept {
10615   // performance: this often compiles to a single instruction (e.g., bswap)
10616   return ((((val)&0xff00000000000000ull) >> 56) |
10617           (((val)&0x00ff000000000000ull) >> 40) |
10618           (((val)&0x0000ff0000000000ull) >> 24) |
10619           (((val)&0x000000ff00000000ull) >> 8) |
10620           (((val)&0x00000000ff000000ull) << 8) |
10621           (((val)&0x0000000000ff0000ull) << 24) |
10622           (((val)&0x000000000000ff00ull) << 40) |
10623           (((val)&0x00000000000000ffull) << 56));
10624 }
10625 
swap_bytes_if_big_endian(uint64_t val)10626 ada_really_inline uint64_t swap_bytes_if_big_endian(uint64_t val) noexcept {
10627   // performance: under little-endian systems (most systems), this function
10628   // is free (just returns the input).
10629 #if ADA_IS_BIG_ENDIAN
10630   return swap_bytes(val);
10631 #else
10632   return val;  // unchanged (trivial)
10633 #endif
10634 }
10635 
10636 // starting at index location, this finds the next location of a character
10637 // :, /, \\, ? or [. If none is found, view.size() is returned.
10638 // For use within get_host_delimiter_location.
find_next_host_delimiter_special(std::string_view view,size_t location)10639 ada_really_inline size_t find_next_host_delimiter_special(
10640     std::string_view view, size_t location) noexcept {
10641   // performance: if you plan to call find_next_host_delimiter more than once,
10642   // you *really* want find_next_host_delimiter to be inlined, because
10643   // otherwise, the constants may get reloaded each time (bad).
10644   auto has_zero_byte = [](uint64_t v) {
10645     return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
10646   };
10647   auto index_of_first_set_byte = [](uint64_t v) {
10648     return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
10649   };
10650   auto broadcast = [](uint8_t v) -> uint64_t {
10651     return 0x101010101010101ull * v;
10652   };
10653   size_t i = location;
10654   uint64_t mask1 = broadcast(':');
10655   uint64_t mask2 = broadcast('/');
10656   uint64_t mask3 = broadcast('\\');
10657   uint64_t mask4 = broadcast('?');
10658   uint64_t mask5 = broadcast('[');
10659   // This loop will get autovectorized under many optimizing compilers,
10660   // so you get actually SIMD!
10661   for (; i + 7 < view.size(); i += 8) {
10662     uint64_t word{};
10663     // performance: the next memcpy translates into a single CPU instruction.
10664     memcpy(&word, view.data() + i, sizeof(word));
10665     // performance: on little-endian systems (most systems), this next line is
10666     // free.
10667     word = swap_bytes_if_big_endian(word);
10668     uint64_t xor1 = word ^ mask1;
10669     uint64_t xor2 = word ^ mask2;
10670     uint64_t xor3 = word ^ mask3;
10671     uint64_t xor4 = word ^ mask4;
10672     uint64_t xor5 = word ^ mask5;
10673     uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10674                         has_zero_byte(xor3) | has_zero_byte(xor4) |
10675                         has_zero_byte(xor5);
10676     if (is_match) {
10677       return size_t(i + index_of_first_set_byte(is_match));
10678     }
10679   }
10680   if (i < view.size()) {
10681     uint64_t word{};
10682     // performance: the next memcpy translates into a function call, but
10683     // that is difficult to avoid. Might be a bit expensive.
10684     memcpy(&word, view.data() + i, view.size() - i);
10685     word = swap_bytes_if_big_endian(word);
10686     uint64_t xor1 = word ^ mask1;
10687     uint64_t xor2 = word ^ mask2;
10688     uint64_t xor3 = word ^ mask3;
10689     uint64_t xor4 = word ^ mask4;
10690     uint64_t xor5 = word ^ mask5;
10691     uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10692                         has_zero_byte(xor3) | has_zero_byte(xor4) |
10693                         has_zero_byte(xor5);
10694     if (is_match) {
10695       return size_t(i + index_of_first_set_byte(is_match));
10696     }
10697   }
10698   return view.size();
10699 }
10700 
10701 // starting at index location, this finds the next location of a character
10702 // :, /, ? or [. If none is found, view.size() is returned.
10703 // For use within get_host_delimiter_location.
find_next_host_delimiter(std::string_view view,size_t location)10704 ada_really_inline size_t find_next_host_delimiter(std::string_view view,
10705                                                   size_t location) noexcept {
10706   // performance: if you plan to call find_next_host_delimiter more than once,
10707   // you *really* want find_next_host_delimiter to be inlined, because
10708   // otherwise, the constants may get reloaded each time (bad).
10709   auto has_zero_byte = [](uint64_t v) {
10710     return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
10711   };
10712   auto index_of_first_set_byte = [](uint64_t v) {
10713     return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
10714   };
10715   auto broadcast = [](uint8_t v) -> uint64_t {
10716     return 0x101010101010101ull * v;
10717   };
10718   size_t i = location;
10719   uint64_t mask1 = broadcast(':');
10720   uint64_t mask2 = broadcast('/');
10721   uint64_t mask4 = broadcast('?');
10722   uint64_t mask5 = broadcast('[');
10723   // This loop will get autovectorized under many optimizing compilers,
10724   // so you get actually SIMD!
10725   for (; i + 7 < view.size(); i += 8) {
10726     uint64_t word{};
10727     // performance: the next memcpy translates into a single CPU instruction.
10728     memcpy(&word, view.data() + i, sizeof(word));
10729     // performance: on little-endian systems (most systems), this next line is
10730     // free.
10731     word = swap_bytes_if_big_endian(word);
10732     uint64_t xor1 = word ^ mask1;
10733     uint64_t xor2 = word ^ mask2;
10734     uint64_t xor4 = word ^ mask4;
10735     uint64_t xor5 = word ^ mask5;
10736     uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10737                         has_zero_byte(xor4) | has_zero_byte(xor5);
10738     if (is_match) {
10739       return size_t(i + index_of_first_set_byte(is_match));
10740     }
10741   }
10742   if (i < view.size()) {
10743     uint64_t word{};
10744     // performance: the next memcpy translates into a function call, but
10745     // that is difficult to avoid. Might be a bit expensive.
10746     memcpy(&word, view.data() + i, view.size() - i);
10747     // performance: on little-endian systems (most systems), this next line is
10748     // free.
10749     word = swap_bytes_if_big_endian(word);
10750     uint64_t xor1 = word ^ mask1;
10751     uint64_t xor2 = word ^ mask2;
10752     uint64_t xor4 = word ^ mask4;
10753     uint64_t xor5 = word ^ mask5;
10754     uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
10755                         has_zero_byte(xor4) | has_zero_byte(xor5);
10756     if (is_match) {
10757       return size_t(i + index_of_first_set_byte(is_match));
10758     }
10759   }
10760   return view.size();
10761 }
10762 
get_host_delimiter_location(const bool is_special,std::string_view & view)10763 ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
10764     const bool is_special, std::string_view& view) noexcept {
10765   /**
10766    * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
10767    * compute a variable called insideBrackets but this variable is only used
10768    * once, to check whether a ':' character was found outside brackets. Exact
10769    * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
10770    * It is conceptually simpler and arguably more efficient to just return a
10771    * Boolean indicating whether ':' was found outside brackets.
10772    */
10773   const size_t view_size = view.size();
10774   size_t location = 0;
10775   bool found_colon = false;
10776   /**
10777    * Performance analysis:
10778    *
10779    * We are basically seeking the end of the hostname which can be indicated
10780    * by the end of the view, or by one of the characters ':', '/', '?', '\\'
10781    * (where '\\' is only applicable for special URLs). However, these must
10782    * appear outside a bracket range. E.g., if you have [something?]fd: then the
10783    * '?' does not count.
10784    *
10785    * So we can skip ahead to the next delimiter, as long as we include '[' in
10786    * the set of delimiters, and that we handle it first.
10787    *
10788    * So the trick is to have a fast function that locates the next delimiter.
10789    * Unless we find '[', then it only needs to be called once! Ideally, such a
10790    * function would be provided by the C++ standard library, but it seems that
10791    * find_first_of is not very fast, so we are forced to roll our own.
10792    *
10793    * We do not break into two loops for speed, but for clarity.
10794    */
10795   if (is_special) {
10796     // We move to the next delimiter.
10797     location = find_next_host_delimiter_special(view, location);
10798     // Unless we find '[' then we are going only going to have to call
10799     // find_next_host_delimiter_special once.
10800     for (; location < view_size;
10801          location = find_next_host_delimiter_special(view, location)) {
10802       if (view[location] == '[') {
10803         location = view.find(']', location);
10804         if (location == std::string_view::npos) {
10805           // performance: view.find might get translated to a memchr, which
10806           // has no notion of std::string_view::npos, so the code does not
10807           // reflect the assembly.
10808           location = view_size;
10809           break;
10810         }
10811       } else {
10812         found_colon = view[location] == ':';
10813         break;
10814       }
10815     }
10816   } else {
10817     // We move to the next delimiter.
10818     location = find_next_host_delimiter(view, location);
10819     // Unless we find '[' then we are going only going to have to call
10820     // find_next_host_delimiter_special once.
10821     for (; location < view_size;
10822          location = find_next_host_delimiter(view, location)) {
10823       if (view[location] == '[') {
10824         location = view.find(']', location);
10825         if (location == std::string_view::npos) {
10826           // performance: view.find might get translated to a memchr, which
10827           // has no notion of std::string_view::npos, so the code does not
10828           // reflect the assembly.
10829           location = view_size;
10830           break;
10831         }
10832       } else {
10833         found_colon = view[location] == ':';
10834         break;
10835       }
10836     }
10837   }
10838   // performance: remove_suffix may translate into a single instruction.
10839   view.remove_suffix(view_size - location);
10840   return {location, found_colon};
10841 }
10842 
trim_c0_whitespace(std::string_view & input)10843 ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
10844   while (!input.empty() &&
10845          ada::unicode::is_c0_control_or_space(input.front())) {
10846     input.remove_prefix(1);
10847   }
10848   while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
10849     input.remove_suffix(1);
10850   }
10851 }
10852 
parse_prepared_path(std::string_view input,ada::scheme::type type,std::string & path)10853 ada_really_inline void parse_prepared_path(std::string_view input,
10854                                            ada::scheme::type type,
10855                                            std::string& path) {
10856   ada_log("parse_prepared_path ", input);
10857   uint8_t accumulator = checkers::path_signature(input);
10858   // Let us first detect a trivial case.
10859   // If it is special, we check that we have no dot, no %,  no \ and no
10860   // character needing percent encoding. Otherwise, we check that we have no %,
10861   // no dot, and no character needing percent encoding.
10862   constexpr uint8_t need_encoding = 1;
10863   constexpr uint8_t backslash_char = 2;
10864   constexpr uint8_t dot_char = 4;
10865   constexpr uint8_t percent_char = 8;
10866   bool special = type != ada::scheme::NOT_SPECIAL;
10867   bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
10868                                       checkers::is_windows_drive_letter(input));
10869   bool trivial_path =
10870       (special ? (accumulator == 0)
10871                : ((accumulator & (need_encoding | dot_char | percent_char)) ==
10872                   0)) &&
10873       (!may_need_slow_file_handling);
10874   if (accumulator == dot_char && !may_need_slow_file_handling) {
10875     // '4' means that we have at least one dot, but nothing that requires
10876     // percent encoding or decoding. The only part that is not trivial is
10877     // that we may have single dots and double dots path segments.
10878     // If we have such segments, then we either have a path that begins
10879     // with '.' (easy to check), or we have the sequence './'.
10880     // Note: input cannot be empty, it must at least contain one character ('.')
10881     // Note: we know that '\' is not present.
10882     if (input[0] != '.') {
10883       size_t slashdot = input.find("/.");
10884       if (slashdot == std::string_view::npos) {  // common case
10885         trivial_path = true;
10886       } else {  // uncommon
10887         // only three cases matter: /./, /.. or a final /
10888         trivial_path =
10889             !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
10890               input[slashdot + 2] == '/');
10891       }
10892     }
10893   }
10894   if (trivial_path) {
10895     ada_log("parse_path trivial");
10896     path += '/';
10897     path += input;
10898     return;
10899   }
10900   // We are going to need to look a bit at the path, but let us see if we can
10901   // ignore percent encoding *and* backslashes *and* percent characters.
10902   // Except for the trivial case, this is likely to capture 99% of paths out
10903   // there.
10904   bool fast_path =
10905       (special &&
10906        (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
10907       (type != ada::scheme::type::FILE);
10908   if (fast_path) {
10909     ada_log("parse_prepared_path fast");
10910     // Here we don't need to worry about \ or percent encoding.
10911     // We also do not have a file protocol. We might have dots, however,
10912     // but dots must as appear as '.', and they cannot be encoded because
10913     // the symbol '%' is not present.
10914     size_t previous_location = 0;  // We start at 0.
10915     do {
10916       size_t new_location = input.find('/', previous_location);
10917       // std::string_view path_view = input;
10918       //  We process the last segment separately:
10919       if (new_location == std::string_view::npos) {
10920         std::string_view path_view = input.substr(previous_location);
10921         if (path_view == "..") {  // The path ends with ..
10922           // e.g., if you receive ".." with an empty path, you go to "/".
10923           if (path.empty()) {
10924             path = '/';
10925             return;
10926           }
10927           // Fast case where we have nothing to do:
10928           if (path.back() == '/') {
10929             return;
10930           }
10931           // If you have the path "/joe/myfriend",
10932           // then you delete 'myfriend'.
10933           path.resize(path.rfind('/') + 1);
10934           return;
10935         }
10936         path += '/';
10937         if (path_view != ".") {
10938           path.append(path_view);
10939         }
10940         return;
10941       } else {
10942         // This is a non-final segment.
10943         std::string_view path_view =
10944             input.substr(previous_location, new_location - previous_location);
10945         previous_location = new_location + 1;
10946         if (path_view == "..") {
10947           size_t last_delimiter = path.rfind('/');
10948           if (last_delimiter != std::string::npos) {
10949             path.erase(last_delimiter);
10950           }
10951         } else if (path_view != ".") {
10952           path += '/';
10953           path.append(path_view);
10954         }
10955       }
10956     } while (true);
10957   } else {
10958     ada_log("parse_path slow");
10959     // we have reached the general case
10960     bool needs_percent_encoding = (accumulator & 1);
10961     std::string path_buffer_tmp;
10962     do {
10963       size_t location = (special && (accumulator & 2))
10964                             ? input.find_first_of("/\\")
10965                             : input.find('/');
10966       std::string_view path_view = input;
10967       if (location != std::string_view::npos) {
10968         path_view.remove_suffix(path_view.size() - location);
10969         input.remove_prefix(location + 1);
10970       }
10971       // path_buffer is either path_view or it might point at a percent encoded
10972       // temporary file.
10973       std::string_view path_buffer =
10974           (needs_percent_encoding &&
10975            ada::unicode::percent_encode<false>(
10976                path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
10977               ? path_buffer_tmp
10978               : path_view;
10979       if (unicode::is_double_dot_path_segment(path_buffer)) {
10980         if ((helpers::shorten_path(path, type) || special) &&
10981             location == std::string_view::npos) {
10982           path += '/';
10983         }
10984       } else if (unicode::is_single_dot_path_segment(path_buffer) &&
10985                  (location == std::string_view::npos)) {
10986         path += '/';
10987       }
10988       // Otherwise, if path_buffer is not a single-dot path segment, then:
10989       else if (!unicode::is_single_dot_path_segment(path_buffer)) {
10990         // If url's scheme is "file", url's path is empty, and path_buffer is a
10991         // Windows drive letter, then replace the second code point in
10992         // path_buffer with U+003A (:).
10993         if (type == ada::scheme::type::FILE && path.empty() &&
10994             checkers::is_windows_drive_letter(path_buffer)) {
10995           path += '/';
10996           path += path_buffer[0];
10997           path += ':';
10998           path_buffer.remove_prefix(2);
10999           path.append(path_buffer);
11000         } else {
11001           // Append path_buffer to url's path.
11002           path += '/';
11003           path.append(path_buffer);
11004         }
11005       }
11006       if (location == std::string_view::npos) {
11007         return;
11008       }
11009     } while (true);
11010   }
11011 }
11012 
overlaps(std::string_view input1,const std::string & input2)11013 bool overlaps(std::string_view input1, const std::string& input2) noexcept {
11014   ada_log("helpers::overlaps check if string_view '", input1, "' [",
11015           input1.size(), " bytes] is part of string '", input2, "' [",
11016           input2.size(), " bytes]");
11017   return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
11018          input1.data() < input2.data() + input2.size();
11019 }
11020 
11021 template <class url_type>
strip_trailing_spaces_from_opaque_path(url_type & url)11022 ada_really_inline void strip_trailing_spaces_from_opaque_path(
11023     url_type& url) noexcept {
11024   ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11025   if (!url.has_opaque_path) return;
11026   if (url.has_hash()) return;
11027   if (url.has_search()) return;
11028 
11029   auto path = std::string(url.get_pathname());
11030   while (!path.empty() && path.back() == ' ') {
11031     path.resize(path.size() - 1);
11032   }
11033   url.update_base_pathname(path);
11034 }
11035 
11036 ada_really_inline size_t
find_authority_delimiter_special(std::string_view view)11037 find_authority_delimiter_special(std::string_view view) noexcept {
11038   auto has_zero_byte = [](uint64_t v) {
11039     return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
11040   };
11041   auto index_of_first_set_byte = [](uint64_t v) {
11042     return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
11043   };
11044   auto broadcast = [](uint8_t v) -> uint64_t {
11045     return 0x101010101010101ull * v;
11046   };
11047   size_t i = 0;
11048   uint64_t mask1 = broadcast('@');
11049   uint64_t mask2 = broadcast('/');
11050   uint64_t mask3 = broadcast('?');
11051   uint64_t mask4 = broadcast('\\');
11052 
11053   for (; i + 7 < view.size(); i += 8) {
11054     uint64_t word{};
11055     memcpy(&word, view.data() + i, sizeof(word));
11056     word = swap_bytes_if_big_endian(word);
11057     uint64_t xor1 = word ^ mask1;
11058     uint64_t xor2 = word ^ mask2;
11059     uint64_t xor3 = word ^ mask3;
11060     uint64_t xor4 = word ^ mask4;
11061     uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
11062                         has_zero_byte(xor3) | has_zero_byte(xor4);
11063     if (is_match) {
11064       return size_t(i + index_of_first_set_byte(is_match));
11065     }
11066   }
11067 
11068   if (i < view.size()) {
11069     uint64_t word{};
11070     memcpy(&word, view.data() + i, view.size() - i);
11071     word = swap_bytes_if_big_endian(word);
11072     uint64_t xor1 = word ^ mask1;
11073     uint64_t xor2 = word ^ mask2;
11074     uint64_t xor3 = word ^ mask3;
11075     uint64_t xor4 = word ^ mask4;
11076     uint64_t is_match = has_zero_byte(xor1) | has_zero_byte(xor2) |
11077                         has_zero_byte(xor3) | has_zero_byte(xor4);
11078     if (is_match) {
11079       return size_t(i + index_of_first_set_byte(is_match));
11080     }
11081   }
11082 
11083   return view.size();
11084 }
11085 
11086 ada_really_inline size_t
find_authority_delimiter(std::string_view view)11087 find_authority_delimiter(std::string_view view) noexcept {
11088   auto has_zero_byte = [](uint64_t v) {
11089     return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080);
11090   };
11091   auto index_of_first_set_byte = [](uint64_t v) {
11092     return ((((v - 1) & 0x101010101010101) * 0x101010101010101) >> 56) - 1;
11093   };
11094   auto broadcast = [](uint8_t v) -> uint64_t {
11095     return 0x101010101010101ull * v;
11096   };
11097   size_t i = 0;
11098   uint64_t mask1 = broadcast('@');
11099   uint64_t mask2 = broadcast('/');
11100   uint64_t mask3 = broadcast('?');
11101 
11102   for (; i + 7 < view.size(); i += 8) {
11103     uint64_t word{};
11104     memcpy(&word, view.data() + i, sizeof(word));
11105     word = swap_bytes_if_big_endian(word);
11106     uint64_t xor1 = word ^ mask1;
11107     uint64_t xor2 = word ^ mask2;
11108     uint64_t xor3 = word ^ mask3;
11109     uint64_t is_match =
11110         has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
11111     if (is_match) {
11112       return size_t(i + index_of_first_set_byte(is_match));
11113     }
11114   }
11115 
11116   if (i < view.size()) {
11117     uint64_t word{};
11118     memcpy(&word, view.data() + i, view.size() - i);
11119     word = swap_bytes_if_big_endian(word);
11120     uint64_t xor1 = word ^ mask1;
11121     uint64_t xor2 = word ^ mask2;
11122     uint64_t xor3 = word ^ mask3;
11123     uint64_t is_match =
11124         has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
11125     if (is_match) {
11126       return size_t(i + index_of_first_set_byte(is_match));
11127     }
11128   }
11129 
11130   return view.size();
11131 }
11132 
11133 }  // namespace ada::helpers
11134 
11135 namespace ada {
to_string(ada::state state)11136 ada_warn_unused std::string to_string(ada::state state) {
11137   return ada::helpers::get_state(state);
11138 }
11139 }  // namespace ada
11140 /* end file src/helpers.cpp */
11141 /* begin file src/url.cpp */
11142 
11143 #include <numeric>
11144 #include <algorithm>
11145 #include <string>
11146 
11147 namespace ada {
11148 
parse_opaque_host(std::string_view input)11149 bool url::parse_opaque_host(std::string_view input) {
11150   ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
11151   if (std::any_of(input.begin(), input.end(),
11152                   ada::unicode::is_forbidden_host_code_point)) {
11153     return is_valid = false;
11154   }
11155 
11156   // Return the result of running UTF-8 percent-encode on input using the C0
11157   // control percent-encode set.
11158   host = ada::unicode::percent_encode(
11159       input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
11160   return true;
11161 }
11162 
parse_ipv4(std::string_view input)11163 bool url::parse_ipv4(std::string_view input) {
11164   ada_log("parse_ipv4 ", input, "[", input.size(), " bytes]");
11165   if (input.back() == '.') {
11166     input.remove_suffix(1);
11167   }
11168   size_t digit_count{0};
11169   int pure_decimal_count = 0;  // entries that are decimal
11170   std::string_view original_input =
11171       input;  // we might use this if pure_decimal_count == 4.
11172   uint64_t ipv4{0};
11173   // we could unroll for better performance?
11174   for (; (digit_count < 4) && !(input.empty()); digit_count++) {
11175     uint32_t
11176         segment_result{};  // If any number exceeds 32 bits, we have an error.
11177     bool is_hex = checkers::has_hex_prefix(input);
11178     if (is_hex && ((input.length() == 2) ||
11179                    ((input.length() > 2) && (input[2] == '.')))) {
11180       // special case
11181       segment_result = 0;
11182       input.remove_prefix(2);
11183     } else {
11184       std::from_chars_result r;
11185       if (is_hex) {
11186         r = std::from_chars(input.data() + 2, input.data() + input.size(),
11187                             segment_result, 16);
11188       } else if ((input.length() >= 2) && input[0] == '0' &&
11189                  checkers::is_digit(input[1])) {
11190         r = std::from_chars(input.data() + 1, input.data() + input.size(),
11191                             segment_result, 8);
11192       } else {
11193         pure_decimal_count++;
11194         r = std::from_chars(input.data(), input.data() + input.size(),
11195                             segment_result, 10);
11196       }
11197       if (r.ec != std::errc()) {
11198         return is_valid = false;
11199       }
11200       input.remove_prefix(r.ptr - input.data());
11201     }
11202     if (input.empty()) {
11203       // We have the last value.
11204       // At this stage, ipv4 contains digit_count*8 bits.
11205       // So we have 32-digit_count*8 bits left.
11206       if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
11207         return is_valid = false;
11208       }
11209       ipv4 <<= (32 - digit_count * 8);
11210       ipv4 |= segment_result;
11211       goto final;
11212     } else {
11213       // There is more, so that the value must no be larger than 255
11214       // and we must have a '.'.
11215       if ((segment_result > 255) || (input[0] != '.')) {
11216         return is_valid = false;
11217       }
11218       ipv4 <<= 8;
11219       ipv4 |= segment_result;
11220       input.remove_prefix(1);  // remove '.'
11221     }
11222   }
11223   if ((digit_count != 4) || (!input.empty())) {
11224     return is_valid = false;
11225   }
11226 final:
11227   // We could also check r.ptr to see where the parsing ended.
11228   if (pure_decimal_count == 4) {
11229     host = original_input;  // The original input was already all decimal and we
11230                             // validated it.
11231   } else {
11232     host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
11233   }
11234   return true;
11235 }
11236 
parse_ipv6(std::string_view input)11237 bool url::parse_ipv6(std::string_view input) {
11238   ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
11239 
11240   if (input.empty()) {
11241     return is_valid = false;
11242   }
11243   // Let address be a new IPv6 address whose IPv6 pieces are all 0.
11244   std::array<uint16_t, 8> address{};
11245 
11246   // Let pieceIndex be 0.
11247   int piece_index = 0;
11248 
11249   // Let compress be null.
11250   std::optional<int> compress{};
11251 
11252   // Let pointer be a pointer for input.
11253   std::string_view::iterator pointer = input.begin();
11254 
11255   // If c is U+003A (:), then:
11256   if (input[0] == ':') {
11257     // If remaining does not start with U+003A (:), validation error, return
11258     // failure.
11259     if (input.size() == 1 || input[1] != ':') {
11260       ada_log("parse_ipv6 starts with : but the rest does not start with :");
11261       return is_valid = false;
11262     }
11263 
11264     // Increase pointer by 2.
11265     pointer += 2;
11266 
11267     // Increase pieceIndex by 1 and then set compress to pieceIndex.
11268     compress = ++piece_index;
11269   }
11270 
11271   // While c is not the EOF code point:
11272   while (pointer != input.end()) {
11273     // If pieceIndex is 8, validation error, return failure.
11274     if (piece_index == 8) {
11275       ada_log("parse_ipv6 piece_index == 8");
11276       return is_valid = false;
11277     }
11278 
11279     // If c is U+003A (:), then:
11280     if (*pointer == ':') {
11281       // If compress is non-null, validation error, return failure.
11282       if (compress.has_value()) {
11283         ada_log("parse_ipv6 compress is non-null");
11284         return is_valid = false;
11285       }
11286 
11287       // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
11288       // then continue.
11289       pointer++;
11290       compress = ++piece_index;
11291       continue;
11292     }
11293 
11294     // Let value and length be 0.
11295     uint16_t value = 0, length = 0;
11296 
11297     // While length is less than 4 and c is an ASCII hex digit,
11298     // set value to value times 0x10 + c interpreted as hexadecimal number, and
11299     // increase pointer and length by 1.
11300     while (length < 4 && pointer != input.end() &&
11301            unicode::is_ascii_hex_digit(*pointer)) {
11302       // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11303       value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
11304       pointer++;
11305       length++;
11306     }
11307 
11308     // If c is U+002E (.), then:
11309     if (pointer != input.end() && *pointer == '.') {
11310       // If length is 0, validation error, return failure.
11311       if (length == 0) {
11312         ada_log("parse_ipv6 length is 0");
11313         return is_valid = false;
11314       }
11315 
11316       // Decrease pointer by length.
11317       pointer -= length;
11318 
11319       // If pieceIndex is greater than 6, validation error, return failure.
11320       if (piece_index > 6) {
11321         ada_log("parse_ipv6 piece_index > 6");
11322         return is_valid = false;
11323       }
11324 
11325       // Let numbersSeen be 0.
11326       int numbers_seen = 0;
11327 
11328       // While c is not the EOF code point:
11329       while (pointer != input.end()) {
11330         // Let ipv4Piece be null.
11331         std::optional<uint16_t> ipv4_piece{};
11332 
11333         // If numbersSeen is greater than 0, then:
11334         if (numbers_seen > 0) {
11335           // If c is a U+002E (.) and numbersSeen is less than 4, then increase
11336           // pointer by 1.
11337           if (*pointer == '.' && numbers_seen < 4) {
11338             pointer++;
11339           }
11340           // Otherwise, validation error, return failure.
11341           else {
11342             ada_log("parse_ipv6 Otherwise, validation error, return failure");
11343             return is_valid = false;
11344           }
11345         }
11346 
11347         // If c is not an ASCII digit, validation error, return failure.
11348         if (pointer == input.end() || !checkers::is_digit(*pointer)) {
11349           ada_log(
11350               "parse_ipv6 If c is not an ASCII digit, validation error, return "
11351               "failure");
11352           return is_valid = false;
11353         }
11354 
11355         // While c is an ASCII digit:
11356         while (pointer != input.end() && checkers::is_digit(*pointer)) {
11357           // Let number be c interpreted as decimal number.
11358           int number = *pointer - '0';
11359 
11360           // If ipv4Piece is null, then set ipv4Piece to number.
11361           if (!ipv4_piece.has_value()) {
11362             ipv4_piece = number;
11363           }
11364           // Otherwise, if ipv4Piece is 0, validation error, return failure.
11365           else if (ipv4_piece == 0) {
11366             ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
11367             return is_valid = false;
11368           }
11369           // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
11370           else {
11371             ipv4_piece = *ipv4_piece * 10 + number;
11372           }
11373 
11374           // If ipv4Piece is greater than 255, validation error, return failure.
11375           if (ipv4_piece > 255) {
11376             ada_log("parse_ipv6 ipv4_piece > 255");
11377             return is_valid = false;
11378           }
11379 
11380           // Increase pointer by 1.
11381           pointer++;
11382         }
11383 
11384         // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
11385         // ipv4Piece.
11386         // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
11387         address[piece_index] =
11388             uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
11389 
11390         // Increase numbersSeen by 1.
11391         numbers_seen++;
11392 
11393         // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
11394         if (numbers_seen == 2 || numbers_seen == 4) {
11395           piece_index++;
11396         }
11397       }
11398 
11399       // If numbersSeen is not 4, validation error, return failure.
11400       if (numbers_seen != 4) {
11401         return is_valid = false;
11402       }
11403 
11404       // Break.
11405       break;
11406     }
11407     // Otherwise, if c is U+003A (:):
11408     else if ((pointer != input.end()) && (*pointer == ':')) {
11409       // Increase pointer by 1.
11410       pointer++;
11411 
11412       // If c is the EOF code point, validation error, return failure.
11413       if (pointer == input.end()) {
11414         ada_log(
11415             "parse_ipv6 If c is the EOF code point, validation error, return "
11416             "failure");
11417         return is_valid = false;
11418       }
11419     }
11420     // Otherwise, if c is not the EOF code point, validation error, return
11421     // failure.
11422     else if (pointer != input.end()) {
11423       ada_log(
11424           "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
11425           "error, return failure");
11426       return is_valid = false;
11427     }
11428 
11429     // Set address[pieceIndex] to value.
11430     address[piece_index] = value;
11431 
11432     // Increase pieceIndex by 1.
11433     piece_index++;
11434   }
11435 
11436   // If compress is non-null, then:
11437   if (compress.has_value()) {
11438     // Let swaps be pieceIndex - compress.
11439     int swaps = piece_index - *compress;
11440 
11441     // Set pieceIndex to 7.
11442     piece_index = 7;
11443 
11444     // While pieceIndex is not 0 and swaps is greater than 0,
11445     // swap address[pieceIndex] with address[compress + swaps - 1], and then
11446     // decrease both pieceIndex and swaps by 1.
11447     while (piece_index != 0 && swaps > 0) {
11448       std::swap(address[piece_index], address[*compress + swaps - 1]);
11449       piece_index--;
11450       swaps--;
11451     }
11452   }
11453   // Otherwise, if compress is null and pieceIndex is not 8, validation error,
11454   // return failure.
11455   else if (piece_index != 8) {
11456     ada_log(
11457         "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
11458         "error, return failure");
11459     return is_valid = false;
11460   }
11461   host = ada::serializers::ipv6(address);
11462   ada_log("parse_ipv6 ", *host);
11463   return true;
11464 }
11465 
11466 template <bool has_state_override>
parse_scheme(const std::string_view input)11467 ada_really_inline bool url::parse_scheme(const std::string_view input) {
11468   auto parsed_type = ada::scheme::get_scheme_type(input);
11469   bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
11470   /**
11471    * In the common case, we will immediately recognize a special scheme (e.g.,
11472    *http, https), in which case, we can go really fast.
11473    **/
11474   if (is_input_special) {  // fast path!!!
11475     if (has_state_override) {
11476       // If url's scheme is not a special scheme and buffer is a special scheme,
11477       // then return.
11478       if (is_special() != is_input_special) {
11479         return true;
11480       }
11481 
11482       // If url includes credentials or has a non-null port, and buffer is
11483       // "file", then return.
11484       if ((has_credentials() || port.has_value()) &&
11485           parsed_type == ada::scheme::type::FILE) {
11486         return true;
11487       }
11488 
11489       // If url's scheme is "file" and its host is an empty host, then return.
11490       // An empty host is the empty string.
11491       if (type == ada::scheme::type::FILE && host.has_value() &&
11492           host.value().empty()) {
11493         return true;
11494       }
11495     }
11496 
11497     type = parsed_type;
11498 
11499     if (has_state_override) {
11500       // This is uncommon.
11501       uint16_t urls_scheme_port = get_special_port();
11502 
11503       if (urls_scheme_port) {
11504         // If url's port is url's scheme's default port, then set url's port to
11505         // null.
11506         if (port.has_value() && *port == urls_scheme_port) {
11507           port = std::nullopt;
11508         }
11509       }
11510     }
11511   } else {  // slow path
11512     std::string _buffer = std::string(input);
11513     // Next function is only valid if the input is ASCII and returns false
11514     // otherwise, but it seems that we always have ascii content so we do not
11515     // need to check the return value.
11516     // bool is_ascii =
11517     unicode::to_lower_ascii(_buffer.data(), _buffer.size());
11518 
11519     if (has_state_override) {
11520       // If url's scheme is a special scheme and buffer is not a special scheme,
11521       // then return. If url's scheme is not a special scheme and buffer is a
11522       // special scheme, then return.
11523       if (is_special() != ada::scheme::is_special(_buffer)) {
11524         return true;
11525       }
11526 
11527       // If url includes credentials or has a non-null port, and buffer is
11528       // "file", then return.
11529       if ((has_credentials() || port.has_value()) && _buffer == "file") {
11530         return true;
11531       }
11532 
11533       // If url's scheme is "file" and its host is an empty host, then return.
11534       // An empty host is the empty string.
11535       if (type == ada::scheme::type::FILE && host.has_value() &&
11536           host.value().empty()) {
11537         return true;
11538       }
11539     }
11540 
11541     set_scheme(std::move(_buffer));
11542 
11543     if (has_state_override) {
11544       // This is uncommon.
11545       uint16_t urls_scheme_port = get_special_port();
11546 
11547       if (urls_scheme_port) {
11548         // If url's port is url's scheme's default port, then set url's port to
11549         // null.
11550         if (port.has_value() && *port == urls_scheme_port) {
11551           port = std::nullopt;
11552         }
11553       }
11554     }
11555   }
11556 
11557   return true;
11558 }
11559 
parse_host(std::string_view input)11560 ada_really_inline bool url::parse_host(std::string_view input) {
11561   ada_log("parse_host ", input, "[", input.size(), " bytes]");
11562   if (input.empty()) {
11563     return is_valid = false;
11564   }  // technically unnecessary.
11565   // If input starts with U+005B ([), then:
11566   if (input[0] == '[') {
11567     // If input does not end with U+005D (]), validation error, return failure.
11568     if (input.back() != ']') {
11569       return is_valid = false;
11570     }
11571     ada_log("parse_host ipv6");
11572 
11573     // Return the result of IPv6 parsing input with its leading U+005B ([) and
11574     // trailing U+005D (]) removed.
11575     input.remove_prefix(1);
11576     input.remove_suffix(1);
11577     return parse_ipv6(input);
11578   }
11579 
11580   // If isNotSpecial is true, then return the result of opaque-host parsing
11581   // input.
11582   if (!is_special()) {
11583     return parse_opaque_host(input);
11584   }
11585   // Let domain be the result of running UTF-8 decode without BOM on the
11586   // percent-decoding of input. Let asciiDomain be the result of running domain
11587   // to ASCII with domain and false. The most common case is an ASCII input, in
11588   // which case we do not need to call the expensive 'to_ascii' if a few
11589   // conditions are met: no '%' and no 'xn-' subsequence.
11590   std::string buffer = std::string(input);
11591   // This next function checks that the result is ascii, but we are going to
11592   // to check anyhow with is_forbidden.
11593   // bool is_ascii =
11594   unicode::to_lower_ascii(buffer.data(), buffer.size());
11595   bool is_forbidden = unicode::contains_forbidden_domain_code_point(
11596       buffer.data(), buffer.size());
11597   if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
11598     // fast path
11599     host = std::move(buffer);
11600     if (checkers::is_ipv4(host.value())) {
11601       ada_log("parse_host fast path ipv4");
11602       return parse_ipv4(host.value());
11603     }
11604     ada_log("parse_host fast path ", *host);
11605     return true;
11606   }
11607   ada_log("parse_host calling to_ascii");
11608   is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
11609   if (!is_valid) {
11610     ada_log("parse_host to_ascii returns false");
11611     return is_valid = false;
11612   }
11613 
11614   if (std::any_of(host.value().begin(), host.value().end(),
11615                   ada::unicode::is_forbidden_domain_code_point)) {
11616     host = std::nullopt;
11617     return is_valid = false;
11618   }
11619 
11620   // If asciiDomain ends in a number, then return the result of IPv4 parsing
11621   // asciiDomain.
11622   if (checkers::is_ipv4(host.value())) {
11623     ada_log("parse_host got ipv4", *host);
11624     return parse_ipv4(host.value());
11625   }
11626 
11627   return true;
11628 }
11629 
parse_path(std::string_view input)11630 ada_really_inline void url::parse_path(std::string_view input) {
11631   ada_log("parse_path ", input);
11632   std::string tmp_buffer;
11633   std::string_view internal_input;
11634   if (unicode::has_tabs_or_newline(input)) {
11635     tmp_buffer = input;
11636     // Optimization opportunity: Instead of copying and then pruning, we could
11637     // just directly build the string from user_input.
11638     helpers::remove_ascii_tab_or_newline(tmp_buffer);
11639     internal_input = tmp_buffer;
11640   } else {
11641     internal_input = input;
11642   }
11643 
11644   // If url is special, then:
11645   if (is_special()) {
11646     if (internal_input.empty()) {
11647       path = "/";
11648     } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11649       helpers::parse_prepared_path(internal_input.substr(1), type, path);
11650       return;
11651     } else {
11652       helpers::parse_prepared_path(internal_input, type, path);
11653       return;
11654     }
11655   } else if (!internal_input.empty()) {
11656     if (internal_input[0] == '/') {
11657       helpers::parse_prepared_path(internal_input.substr(1), type, path);
11658       return;
11659     } else {
11660       helpers::parse_prepared_path(internal_input, type, path);
11661       return;
11662     }
11663   } else {
11664     if (!host.has_value()) {
11665       path = "/";
11666     }
11667   }
11668   return;
11669 }
11670 
to_string() const11671 std::string url::to_string() const {
11672   if (!is_valid) {
11673     return "null";
11674   }
11675   std::string answer;
11676   auto back = std::back_insert_iterator(answer);
11677   answer.append("{\n");
11678   answer.append("\t\"protocol\":\"");
11679   helpers::encode_json(get_protocol(), back);
11680   answer.append("\",\n");
11681   if (has_credentials()) {
11682     answer.append("\t\"username\":\"");
11683     helpers::encode_json(username, back);
11684     answer.append("\",\n");
11685     answer.append("\t\"password\":\"");
11686     helpers::encode_json(password, back);
11687     answer.append("\",\n");
11688   }
11689   if (host.has_value()) {
11690     answer.append("\t\"host\":\"");
11691     helpers::encode_json(host.value(), back);
11692     answer.append("\",\n");
11693   }
11694   if (port.has_value()) {
11695     answer.append("\t\"port\":\"");
11696     answer.append(std::to_string(port.value()));
11697     answer.append("\",\n");
11698   }
11699   answer.append("\t\"path\":\"");
11700   helpers::encode_json(path, back);
11701   answer.append("\",\n");
11702   answer.append("\t\"opaque path\":");
11703   answer.append((has_opaque_path ? "true" : "false"));
11704   if (has_search()) {
11705     answer.append(",\n");
11706     answer.append("\t\"query\":\"");
11707     helpers::encode_json(query.value(), back);
11708     answer.append("\"");
11709   }
11710   if (hash.has_value()) {
11711     answer.append(",\n");
11712     answer.append("\t\"hash\":\"");
11713     helpers::encode_json(hash.value(), back);
11714     answer.append("\"");
11715   }
11716   answer.append("\n}");
11717   return answer;
11718 }
11719 
has_valid_domain() const11720 [[nodiscard]] bool url::has_valid_domain() const noexcept {
11721   if (!host.has_value()) {
11722     return false;
11723   }
11724   return checkers::verify_dns_length(host.value());
11725 }
11726 
11727 }  // namespace ada
11728 /* end file src/url.cpp */
11729 /* begin file src/url-getters.cpp */
11730 /**
11731  * @file url-getters.cpp
11732  * Includes all the getters of `ada::url`
11733  */
11734 
11735 #include <algorithm>
11736 #include <string>
11737 
11738 namespace ada {
get_origin() const11739 [[nodiscard]] std::string url::get_origin() const noexcept {
11740   if (is_special()) {
11741     // Return a new opaque origin.
11742     if (type == scheme::FILE) {
11743       return "null";
11744     }
11745     return ada::helpers::concat(get_protocol(), "//", get_host());
11746   }
11747 
11748   if (non_special_scheme == "blob") {
11749     if (!path.empty()) {
11750       auto result = ada::parse<ada::url>(path);
11751       if (result &&
11752           (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
11753         // If pathURL's scheme is not "http" and not "https", then return a
11754         // new opaque origin.
11755         return ada::helpers::concat(result->get_protocol(), "//",
11756                                     result->get_host());
11757       }
11758     }
11759   }
11760 
11761   // Return a new opaque origin.
11762   return "null";
11763 }
11764 
get_protocol() const11765 [[nodiscard]] std::string url::get_protocol() const noexcept {
11766   if (is_special()) {
11767     return helpers::concat(ada::scheme::details::is_special_list[type], ":");
11768   }
11769   // We only move the 'scheme' if it is non-special.
11770   return helpers::concat(non_special_scheme, ":");
11771 }
11772 
get_host() const11773 [[nodiscard]] std::string url::get_host() const noexcept {
11774   // If url's host is null, then return the empty string.
11775   // If url's port is null, return url's host, serialized.
11776   // Return url's host, serialized, followed by U+003A (:) and url's port,
11777   // serialized.
11778   if (!host.has_value()) {
11779     return "";
11780   }
11781   if (port.has_value()) {
11782     return host.value() + ":" + get_port();
11783   }
11784   return host.value();
11785 }
11786 
get_hostname() const11787 [[nodiscard]] std::string url::get_hostname() const noexcept {
11788   return host.value_or("");
11789 }
11790 
get_pathname() const11791 [[nodiscard]] const std::string_view url::get_pathname() const noexcept {
11792   return path;
11793 }
11794 
get_search() const11795 [[nodiscard]] std::string url::get_search() const noexcept {
11796   // If this's URL's query is either null or the empty string, then return the
11797   // empty string. Return U+003F (?), followed by this's URL's query.
11798   return (!query.has_value() || (query.value().empty())) ? ""
11799                                                          : "?" + query.value();
11800 }
11801 
get_username() const11802 [[nodiscard]] const std::string& url::get_username() const noexcept {
11803   return username;
11804 }
11805 
get_password() const11806 [[nodiscard]] const std::string& url::get_password() const noexcept {
11807   return password;
11808 }
11809 
get_port() const11810 [[nodiscard]] std::string url::get_port() const noexcept {
11811   return port.has_value() ? std::to_string(port.value()) : "";
11812 }
11813 
get_hash() const11814 [[nodiscard]] std::string url::get_hash() const noexcept {
11815   // If this's URL's fragment is either null or the empty string, then return
11816   // the empty string. Return U+0023 (#), followed by this's URL's fragment.
11817   return (!hash.has_value() || (hash.value().empty())) ? ""
11818                                                        : "#" + hash.value();
11819 }
11820 
11821 }  // namespace ada
11822 /* end file src/url-getters.cpp */
11823 /* begin file src/url-setters.cpp */
11824 /**
11825  * @file url-setters.cpp
11826  * Includes all the setters of `ada::url`
11827  */
11828 
11829 #include <optional>
11830 #include <string>
11831 
11832 namespace ada {
11833 
11834 template <bool override_hostname>
set_host_or_hostname(const std::string_view input)11835 bool url::set_host_or_hostname(const std::string_view input) {
11836   if (has_opaque_path) {
11837     return false;
11838   }
11839 
11840   std::optional<std::string> previous_host = host;
11841   std::optional<uint16_t> previous_port = port;
11842 
11843   size_t host_end_pos = input.find('#');
11844   std::string _host(input.data(), host_end_pos != std::string_view::npos
11845                                       ? host_end_pos
11846                                       : input.size());
11847   helpers::remove_ascii_tab_or_newline(_host);
11848   std::string_view new_host(_host);
11849 
11850   // If url's scheme is "file", then set state to file host state, instead of
11851   // host state.
11852   if (type != ada::scheme::type::FILE) {
11853     std::string_view host_view(_host.data(), _host.length());
11854     auto [location, found_colon] =
11855         helpers::get_host_delimiter_location(is_special(), host_view);
11856 
11857     // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
11858     // Note: the 'found_colon' value is true if and only if a colon was
11859     // encountered while not inside brackets.
11860     if (found_colon) {
11861       if (override_hostname) {
11862         return false;
11863       }
11864       std::string_view buffer = new_host.substr(location + 1);
11865       if (!buffer.empty()) {
11866         set_port(buffer);
11867       }
11868     }
11869     // If url is special and host_view is the empty string, validation error,
11870     // return failure. Otherwise, if state override is given, host_view is the
11871     // empty string, and either url includes credentials or url's port is
11872     // non-null, return.
11873     else if (host_view.empty() &&
11874              (is_special() || has_credentials() || port.has_value())) {
11875       return false;
11876     }
11877 
11878     // Let host be the result of host parsing host_view with url is not special.
11879     if (host_view.empty()) {
11880       host = "";
11881       return true;
11882     }
11883 
11884     bool succeeded = parse_host(host_view);
11885     if (!succeeded) {
11886       host = previous_host;
11887       update_base_port(previous_port);
11888     }
11889     return succeeded;
11890   }
11891 
11892   size_t location = new_host.find_first_of("/\\?");
11893   if (location != std::string_view::npos) {
11894     new_host.remove_suffix(new_host.length() - location);
11895   }
11896 
11897   if (new_host.empty()) {
11898     // Set url's host to the empty string.
11899     host = "";
11900   } else {
11901     // Let host be the result of host parsing buffer with url is not special.
11902     if (!parse_host(new_host)) {
11903       host = previous_host;
11904       update_base_port(previous_port);
11905       return false;
11906     }
11907 
11908     // If host is "localhost", then set host to the empty string.
11909     if (host.has_value() && host.value() == "localhost") {
11910       host = "";
11911     }
11912   }
11913   return true;
11914 }
11915 
set_host(const std::string_view input)11916 bool url::set_host(const std::string_view input) {
11917   return set_host_or_hostname<false>(input);
11918 }
11919 
set_hostname(const std::string_view input)11920 bool url::set_hostname(const std::string_view input) {
11921   return set_host_or_hostname<true>(input);
11922 }
11923 
set_username(const std::string_view input)11924 bool url::set_username(const std::string_view input) {
11925   if (cannot_have_credentials_or_port()) {
11926     return false;
11927   }
11928   username = ada::unicode::percent_encode(
11929       input, character_sets::USERINFO_PERCENT_ENCODE);
11930   return true;
11931 }
11932 
set_password(const std::string_view input)11933 bool url::set_password(const std::string_view input) {
11934   if (cannot_have_credentials_or_port()) {
11935     return false;
11936   }
11937   password = ada::unicode::percent_encode(
11938       input, character_sets::USERINFO_PERCENT_ENCODE);
11939   return true;
11940 }
11941 
set_port(const std::string_view input)11942 bool url::set_port(const std::string_view input) {
11943   if (cannot_have_credentials_or_port()) {
11944     return false;
11945   }
11946   std::string trimmed(input);
11947   helpers::remove_ascii_tab_or_newline(trimmed);
11948   if (trimmed.empty()) {
11949     port = std::nullopt;
11950     return true;
11951   }
11952   // Input should not start with control characters.
11953   if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
11954     return false;
11955   }
11956   // Input should contain at least one ascii digit.
11957   if (input.find_first_of("0123456789") == std::string_view::npos) {
11958     return false;
11959   }
11960 
11961   // Revert changes if parse_port fails.
11962   std::optional<uint16_t> previous_port = port;
11963   parse_port(trimmed);
11964   if (is_valid) {
11965     return true;
11966   }
11967   port = previous_port;
11968   is_valid = true;
11969   return false;
11970 }
11971 
set_hash(const std::string_view input)11972 void url::set_hash(const std::string_view input) {
11973   if (input.empty()) {
11974     hash = std::nullopt;
11975     helpers::strip_trailing_spaces_from_opaque_path(*this);
11976     return;
11977   }
11978 
11979   std::string new_value;
11980   new_value = input[0] == '#' ? input.substr(1) : input;
11981   helpers::remove_ascii_tab_or_newline(new_value);
11982   hash = unicode::percent_encode(new_value,
11983                                  ada::character_sets::FRAGMENT_PERCENT_ENCODE);
11984   return;
11985 }
11986 
set_search(const std::string_view input)11987 void url::set_search(const std::string_view input) {
11988   if (input.empty()) {
11989     query = std::nullopt;
11990     helpers::strip_trailing_spaces_from_opaque_path(*this);
11991     return;
11992   }
11993 
11994   std::string new_value;
11995   new_value = input[0] == '?' ? input.substr(1) : input;
11996   helpers::remove_ascii_tab_or_newline(new_value);
11997 
11998   auto query_percent_encode_set =
11999       is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12000                    : ada::character_sets::QUERY_PERCENT_ENCODE;
12001 
12002   query = ada::unicode::percent_encode(std::string_view(new_value),
12003                                        query_percent_encode_set);
12004 }
12005 
set_pathname(const std::string_view input)12006 bool url::set_pathname(const std::string_view input) {
12007   if (has_opaque_path) {
12008     return false;
12009   }
12010   path = "";
12011   parse_path(input);
12012   return true;
12013 }
12014 
set_protocol(const std::string_view input)12015 bool url::set_protocol(const std::string_view input) {
12016   std::string view(input);
12017   helpers::remove_ascii_tab_or_newline(view);
12018   if (view.empty()) {
12019     return true;
12020   }
12021 
12022   // Schemes should start with alpha values.
12023   if (!checkers::is_alpha(view[0])) {
12024     return false;
12025   }
12026 
12027   view.append(":");
12028 
12029   std::string::iterator pointer =
12030       std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
12031 
12032   if (pointer != view.end() && *pointer == ':') {
12033     return parse_scheme<true>(
12034         std::string_view(view.data(), pointer - view.begin()));
12035   }
12036   return false;
12037 }
12038 
set_href(const std::string_view input)12039 bool url::set_href(const std::string_view input) {
12040   ada::result<ada::url> out = ada::parse<ada::url>(input);
12041 
12042   if (out) {
12043     username = out->username;
12044     password = out->password;
12045     host = out->host;
12046     port = out->port;
12047     path = out->path;
12048     query = out->query;
12049     hash = out->hash;
12050     type = out->type;
12051     non_special_scheme = out->non_special_scheme;
12052     has_opaque_path = out->has_opaque_path;
12053   }
12054 
12055   return out.has_value();
12056 }
12057 
12058 }  // namespace ada
12059 /* end file src/url-setters.cpp */
12060 /* begin file src/parser.cpp */
12061 
12062 #include <numeric>
12063 #include <limits>
12064 
12065 namespace ada::parser {
12066 
12067 template <class result_type>
parse_url(std::string_view user_input,const result_type * base_url)12068 result_type parse_url(std::string_view user_input,
12069                       const result_type* base_url) {
12070   // We can specialize the implementation per type.
12071   // Important: result_type_is_ada_url is evaluated at *compile time*. This
12072   // means that doing if constexpr(result_type_is_ada_url) { something } else {
12073   // something else } is free (at runtime). This means that ada::url_aggregator
12074   // and ada::url **do not have to support the exact same API**.
12075   constexpr bool result_type_is_ada_url =
12076       std::is_same<ada::url, result_type>::value;
12077   constexpr bool result_type_is_ada_url_aggregator =
12078       std::is_same<ada::url_aggregator, result_type>::value;
12079   static_assert(result_type_is_ada_url ||
12080                 result_type_is_ada_url_aggregator);  // We don't support
12081                                                      // anything else for now.
12082 
12083   ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12084           " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12085           ")");
12086 
12087   ada::state state = ada::state::SCHEME_START;
12088   result_type url{};
12089 
12090   // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12091   // surely the result of a bug or are otherwise a security concern.
12092   if (user_input.size() > std::numeric_limits<uint32_t>::max()) {
12093     url.is_valid = false;
12094   }
12095   // Going forward, user_input.size() is in [0,
12096   // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12097   // base, or the optional_url was invalid, we must return.
12098   if (base_url != nullptr) {
12099     url.is_valid &= base_url->is_valid;
12100   }
12101   if (!url.is_valid) {
12102     return url;
12103   }
12104   if constexpr (result_type_is_ada_url_aggregator) {
12105     // Most of the time, we just need user_input.size().
12106     // In some instances, we may need a bit more.
12107     ///////////////////////////
12108     // This is *very* important. This line should *not* be removed
12109     // hastily. There are principled reasons why reserve is important
12110     // for performance. If you have a benchmark with small inputs,
12111     // it may not matter, but in other instances, it could.
12112     ////
12113     // This rounds up to the next power of two.
12114     // We know that user_input.size() is in [0,
12115     // std::numeric_limits<uint32_t>::max).
12116     uint32_t reserve_capacity =
12117         (0xFFFFFFFF >>
12118          helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12119         1;
12120     url.reserve(reserve_capacity);
12121     //
12122     //
12123     //
12124   }
12125   std::string tmp_buffer;
12126   std::string_view internal_input;
12127   if (unicode::has_tabs_or_newline(user_input)) {
12128     tmp_buffer = user_input;
12129     // Optimization opportunity: Instead of copying and then pruning, we could
12130     // just directly build the string from user_input.
12131     helpers::remove_ascii_tab_or_newline(tmp_buffer);
12132     internal_input = tmp_buffer;
12133   } else {
12134     internal_input = user_input;
12135   }
12136 
12137   // Leading and trailing control characters are uncommon and easy to deal with
12138   // (no performance concern).
12139   std::string_view url_data = internal_input;
12140   helpers::trim_c0_whitespace(url_data);
12141 
12142   // Optimization opportunity. Most websites do not have fragment.
12143   std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12144   // We add it last so that an implementation like ada::url_aggregator
12145   // can append it last to its internal buffer, thus improving performance.
12146 
12147   // Here url_data no longer has its fragment.
12148   // We are going to access the data from url_data (it is immutable).
12149   // At any given time, we are pointing at byte 'input_position' in url_data.
12150   // The input_position variable should range from 0 to input_size.
12151   // It is illegal to access url_data at input_size.
12152   size_t input_position = 0;
12153   const size_t input_size = url_data.size();
12154   // Keep running the following state machine by switching on state.
12155   // If after a run pointer points to the EOF code point, go to the next step.
12156   // Otherwise, increase pointer by 1 and continue with the state machine.
12157   // We never decrement input_position.
12158   while (input_position <= input_size) {
12159     ada_log("In parsing at ", input_position, " out of ", input_size,
12160             " in state ", ada::to_string(state));
12161     switch (state) {
12162       case ada::state::SCHEME_START: {
12163         ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
12164         // If c is an ASCII alpha, append c, lowercased, to buffer, and set
12165         // state to scheme state.
12166         if ((input_position != input_size) &&
12167             checkers::is_alpha(url_data[input_position])) {
12168           state = ada::state::SCHEME;
12169           input_position++;
12170         } else {
12171           // Otherwise, if state override is not given, set state to no scheme
12172           // state and decrease pointer by 1.
12173           state = ada::state::NO_SCHEME;
12174         }
12175         break;
12176       }
12177       case ada::state::SCHEME: {
12178         ada_log("SCHEME ", helpers::substring(url_data, input_position));
12179         // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
12180         // append c, lowercased, to buffer.
12181         while ((input_position != input_size) &&
12182                (ada::unicode::is_alnum_plus(url_data[input_position]))) {
12183           input_position++;
12184         }
12185         // Otherwise, if c is U+003A (:), then:
12186         if ((input_position != input_size) &&
12187             (url_data[input_position] == ':')) {
12188           ada_log("SCHEME the scheme should be ",
12189                   url_data.substr(0, input_position));
12190           if constexpr (result_type_is_ada_url) {
12191             if (!url.parse_scheme(url_data.substr(0, input_position))) {
12192               return url;
12193             }
12194           } else {
12195             // we pass the colon along instead of painfully adding it back.
12196             if (!url.parse_scheme_with_colon(
12197                     url_data.substr(0, input_position + 1))) {
12198               return url;
12199             }
12200           }
12201           ada_log("SCHEME the scheme is ", url.get_protocol());
12202 
12203           // If url's scheme is "file", then:
12204           if (url.type == ada::scheme::type::FILE) {
12205             // Set state to file state.
12206             state = ada::state::FILE;
12207           }
12208           // Otherwise, if url is special, base is non-null, and base's scheme
12209           // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
12210           // != nullptr is false.
12211           else if (url.is_special() && base_url != nullptr &&
12212                    base_url->type == url.type) {
12213             // Set state to special relative or authority state.
12214             state = ada::state::SPECIAL_RELATIVE_OR_AUTHORITY;
12215           }
12216           // Otherwise, if url is special, set state to special authority
12217           // slashes state.
12218           else if (url.is_special()) {
12219             state = ada::state::SPECIAL_AUTHORITY_SLASHES;
12220           }
12221           // Otherwise, if remaining starts with an U+002F (/), set state to
12222           // path or authority state and increase pointer by 1.
12223           else if (input_position + 1 < input_size &&
12224                    url_data[input_position + 1] == '/') {
12225             state = ada::state::PATH_OR_AUTHORITY;
12226             input_position++;
12227           }
12228           // Otherwise, set url's path to the empty string and set state to
12229           // opaque path state.
12230           else {
12231             state = ada::state::OPAQUE_PATH;
12232           }
12233         }
12234         // Otherwise, if state override is not given, set buffer to the empty
12235         // string, state to no scheme state, and start over (from the first code
12236         // point in input).
12237         else {
12238           state = ada::state::NO_SCHEME;
12239           input_position = 0;
12240           break;
12241         }
12242         input_position++;
12243         break;
12244       }
12245       case ada::state::NO_SCHEME: {
12246         ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
12247         // If base is null, or base has an opaque path and c is not U+0023 (#),
12248         // validation error, return failure.
12249         if (base_url == nullptr ||
12250             (base_url->has_opaque_path && !fragment.has_value())) {
12251           ada_log("NO_SCHEME validation error");
12252           url.is_valid = false;
12253           return url;
12254         }
12255         // Otherwise, if base has an opaque path and c is U+0023 (#),
12256         // set url's scheme to base's scheme, url's path to base's path, url's
12257         // query to base's query, and set state to fragment state.
12258         else if (base_url->has_opaque_path && fragment.has_value() &&
12259                  input_position == input_size) {
12260           ada_log("NO_SCHEME opaque base with fragment");
12261           url.copy_scheme(*base_url);
12262           url.has_opaque_path = base_url->has_opaque_path;
12263 
12264           if constexpr (result_type_is_ada_url) {
12265             url.path = base_url->path;
12266             url.query = base_url->query;
12267           } else {
12268             url.update_base_pathname(base_url->get_pathname());
12269             url.update_base_search(base_url->get_search());
12270           }
12271           url.update_unencoded_base_hash(*fragment);
12272           return url;
12273         }
12274         // Otherwise, if base's scheme is not "file", set state to relative
12275         // state and decrease pointer by 1.
12276         else if (base_url->type != ada::scheme::type::FILE) {
12277           ada_log("NO_SCHEME non-file relative path");
12278           state = ada::state::RELATIVE_SCHEME;
12279         }
12280         // Otherwise, set state to file state and decrease pointer by 1.
12281         else {
12282           ada_log("NO_SCHEME file base type");
12283           state = ada::state::FILE;
12284         }
12285         break;
12286       }
12287       case ada::state::AUTHORITY: {
12288         ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
12289         // most URLs have no @. Having no @ tells us that we don't have to worry
12290         // about AUTHORITY. Of course, we could have @ and still not have to
12291         // worry about AUTHORITY.
12292         // TODO: Instead of just collecting a bool, collect the location of the
12293         // '@' and do something useful with it.
12294         // TODO: We could do various processing early on, using a single pass
12295         // over the string to collect information about it, e.g., telling us
12296         // whether there is a @ and if so, where (or how many).
12297         const bool contains_ampersand =
12298             (url_data.find('@', input_position) != std::string_view::npos);
12299 
12300         if (!contains_ampersand) {
12301           state = ada::state::HOST;
12302           break;
12303         }
12304         bool at_sign_seen{false};
12305         bool password_token_seen{false};
12306         /**
12307          * We expect something of the sort...
12308          * https://user:pass@example.com:1234/foo/bar?baz#quux
12309          * --------^
12310          */
12311         do {
12312           std::string_view view = helpers::substring(url_data, input_position);
12313           // The delimiters are @, /, ? \\.
12314           size_t location =
12315               url.is_special() ? helpers::find_authority_delimiter_special(view)
12316                                : helpers::find_authority_delimiter(view);
12317           std::string_view authority_view(view.data(), location);
12318           size_t end_of_authority = input_position + authority_view.size();
12319           // If c is U+0040 (@), then:
12320           if ((end_of_authority != input_size) &&
12321               (url_data[end_of_authority] == '@')) {
12322             // If atSignSeen is true, then prepend "%40" to buffer.
12323             if (at_sign_seen) {
12324               if (password_token_seen) {
12325                 if constexpr (result_type_is_ada_url) {
12326                   url.password += "%40";
12327                 } else {
12328                   url.append_base_password("%40");
12329                 }
12330               } else {
12331                 if constexpr (result_type_is_ada_url) {
12332                   url.username += "%40";
12333                 } else {
12334                   url.append_base_username("%40");
12335                 }
12336               }
12337             }
12338 
12339             at_sign_seen = true;
12340 
12341             if (!password_token_seen) {
12342               size_t password_token_location = authority_view.find(':');
12343               password_token_seen =
12344                   password_token_location != std::string_view::npos;
12345 
12346               if (!password_token_seen) {
12347                 if constexpr (result_type_is_ada_url) {
12348                   url.username += unicode::percent_encode(
12349                       authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12350                 } else {
12351                   url.append_base_username(unicode::percent_encode(
12352                       authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12353                 }
12354               } else {
12355                 if constexpr (result_type_is_ada_url) {
12356                   url.username += unicode::percent_encode(
12357                       authority_view.substr(0, password_token_location),
12358                       character_sets::USERINFO_PERCENT_ENCODE);
12359                   url.password += unicode::percent_encode(
12360                       authority_view.substr(password_token_location + 1),
12361                       character_sets::USERINFO_PERCENT_ENCODE);
12362                 } else {
12363                   url.append_base_username(unicode::percent_encode(
12364                       authority_view.substr(0, password_token_location),
12365                       character_sets::USERINFO_PERCENT_ENCODE));
12366                   url.append_base_password(unicode::percent_encode(
12367                       authority_view.substr(password_token_location + 1),
12368                       character_sets::USERINFO_PERCENT_ENCODE));
12369                 }
12370               }
12371             } else {
12372               if constexpr (result_type_is_ada_url) {
12373                 url.password += unicode::percent_encode(
12374                     authority_view, character_sets::USERINFO_PERCENT_ENCODE);
12375               } else {
12376                 url.append_base_password(unicode::percent_encode(
12377                     authority_view, character_sets::USERINFO_PERCENT_ENCODE));
12378               }
12379             }
12380           }
12381           // Otherwise, if one of the following is true:
12382           // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12383           // - url is special and c is U+005C (\)
12384           else if (end_of_authority == input_size ||
12385                    url_data[end_of_authority] == '/' ||
12386                    url_data[end_of_authority] == '?' ||
12387                    (url.is_special() && url_data[end_of_authority] == '\\')) {
12388             // If atSignSeen is true and authority_view is the empty string,
12389             // validation error, return failure.
12390             if (at_sign_seen && authority_view.empty()) {
12391               url.is_valid = false;
12392               return url;
12393             }
12394             state = ada::state::HOST;
12395             break;
12396           }
12397           if (end_of_authority == input_size) {
12398             if (fragment.has_value()) {
12399               url.update_unencoded_base_hash(*fragment);
12400             }
12401             return url;
12402           }
12403           input_position = end_of_authority + 1;
12404         } while (true);
12405 
12406         break;
12407       }
12408       case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
12409         ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
12410                 helpers::substring(url_data, input_position));
12411 
12412         // If c is U+002F (/) and remaining starts with U+002F (/),
12413         // then set state to special authority ignore slashes state and increase
12414         // pointer by 1.
12415         std::string_view view = helpers::substring(url_data, input_position);
12416         if (ada::checkers::begins_with(view, "//")) {
12417           state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12418           input_position += 2;
12419         } else {
12420           // Otherwise, validation error, set state to relative state and
12421           // decrease pointer by 1.
12422           state = ada::state::RELATIVE_SCHEME;
12423         }
12424 
12425         break;
12426       }
12427       case ada::state::PATH_OR_AUTHORITY: {
12428         ada_log("PATH_OR_AUTHORITY ",
12429                 helpers::substring(url_data, input_position));
12430 
12431         // If c is U+002F (/), then set state to authority state.
12432         if ((input_position != input_size) &&
12433             (url_data[input_position] == '/')) {
12434           state = ada::state::AUTHORITY;
12435           input_position++;
12436         } else {
12437           // Otherwise, set state to path state, and decrease pointer by 1.
12438           state = ada::state::PATH;
12439         }
12440 
12441         break;
12442       }
12443       case ada::state::RELATIVE_SCHEME: {
12444         ada_log("RELATIVE_SCHEME ",
12445                 helpers::substring(url_data, input_position));
12446 
12447         // Set url's scheme to base's scheme.
12448         url.copy_scheme(*base_url);
12449 
12450         // If c is U+002F (/), then set state to relative slash state.
12451         if ((input_position != input_size) &&
12452             (url_data[input_position] == '/')) {
12453           ada_log(
12454               "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
12455               "slash state");
12456           state = ada::state::RELATIVE_SLASH;
12457         } else if (url.is_special() && (input_position != input_size) &&
12458                    (url_data[input_position] == '\\')) {
12459           // Otherwise, if url is special and c is U+005C (\), validation error,
12460           // set state to relative slash state.
12461           ada_log(
12462               "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
12463               "error, set state to relative slash state");
12464           state = ada::state::RELATIVE_SLASH;
12465         } else {
12466           ada_log("RELATIVE_SCHEME otherwise");
12467           // Set url's username to base's username, url's password to base's
12468           // password, url's host to base's host, url's port to base's port,
12469           // url's path to a clone of base's path, and url's query to base's
12470           // query.
12471           if constexpr (result_type_is_ada_url) {
12472             url.username = base_url->username;
12473             url.password = base_url->password;
12474             url.host = base_url->host;
12475             url.port = base_url->port;
12476             // cloning the base path includes cloning the has_opaque_path flag
12477             url.has_opaque_path = base_url->has_opaque_path;
12478             url.path = base_url->path;
12479             url.query = base_url->query;
12480           } else {
12481             url.update_base_authority(base_url->get_href(),
12482                                       base_url->get_components());
12483             // TODO: Get rid of set_hostname and replace it with
12484             // update_base_hostname
12485             url.set_hostname(base_url->get_hostname());
12486             url.update_base_port(base_url->retrieve_base_port());
12487             // cloning the base path includes cloning the has_opaque_path flag
12488             url.has_opaque_path = base_url->has_opaque_path;
12489             url.update_base_pathname(base_url->get_pathname());
12490             url.update_base_search(base_url->get_search());
12491           }
12492 
12493           url.has_opaque_path = base_url->has_opaque_path;
12494 
12495           // If c is U+003F (?), then set url's query to the empty string, and
12496           // state to query state.
12497           if ((input_position != input_size) &&
12498               (url_data[input_position] == '?')) {
12499             state = ada::state::QUERY;
12500           }
12501           // Otherwise, if c is not the EOF code point:
12502           else if (input_position != input_size) {
12503             // Set url's query to null.
12504             url.clear_search();
12505             if constexpr (result_type_is_ada_url) {
12506               // Shorten url's path.
12507               helpers::shorten_path(url.path, url.type);
12508             } else {
12509               std::string_view path = url.get_pathname();
12510               if (helpers::shorten_path(path, url.type)) {
12511                 url.update_base_pathname(std::string(path));
12512               }
12513             }
12514             // Set state to path state and decrease pointer by 1.
12515             state = ada::state::PATH;
12516             break;
12517           }
12518         }
12519         input_position++;
12520         break;
12521       }
12522       case ada::state::RELATIVE_SLASH: {
12523         ada_log("RELATIVE_SLASH ",
12524                 helpers::substring(url_data, input_position));
12525 
12526         // If url is special and c is U+002F (/) or U+005C (\), then:
12527         if (url.is_special() && (input_position != input_size) &&
12528             (url_data[input_position] == '/' ||
12529              url_data[input_position] == '\\')) {
12530           // Set state to special authority ignore slashes state.
12531           state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12532         }
12533         // Otherwise, if c is U+002F (/), then set state to authority state.
12534         else if ((input_position != input_size) &&
12535                  (url_data[input_position] == '/')) {
12536           state = ada::state::AUTHORITY;
12537         }
12538         // Otherwise, set
12539         // - url's username to base's username,
12540         // - url's password to base's password,
12541         // - url's host to base's host,
12542         // - url's port to base's port,
12543         // - state to path state, and then, decrease pointer by 1.
12544         else {
12545           if constexpr (result_type_is_ada_url) {
12546             url.username = base_url->username;
12547             url.password = base_url->password;
12548             url.host = base_url->host;
12549             url.port = base_url->port;
12550           } else {
12551             url.update_base_authority(base_url->get_href(),
12552                                       base_url->get_components());
12553             // TODO: Get rid of set_hostname and replace it with
12554             // update_base_hostname
12555             url.set_hostname(base_url->get_hostname());
12556             url.update_base_port(base_url->retrieve_base_port());
12557           }
12558           state = ada::state::PATH;
12559           break;
12560         }
12561 
12562         input_position++;
12563         break;
12564       }
12565       case ada::state::SPECIAL_AUTHORITY_SLASHES: {
12566         ada_log("SPECIAL_AUTHORITY_SLASHES ",
12567                 helpers::substring(url_data, input_position));
12568 
12569         // If c is U+002F (/) and remaining starts with U+002F (/),
12570         // then set state to special authority ignore slashes state and increase
12571         // pointer by 1.
12572         state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
12573         std::string_view view = helpers::substring(url_data, input_position);
12574         if (ada::checkers::begins_with(view, "//")) {
12575           input_position += 2;
12576         }
12577 
12578         [[fallthrough]];
12579       }
12580       case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
12581         ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
12582                 helpers::substring(url_data, input_position));
12583 
12584         // If c is neither U+002F (/) nor U+005C (\), then set state to
12585         // authority state and decrease pointer by 1.
12586         while ((input_position != input_size) &&
12587                ((url_data[input_position] == '/') ||
12588                 (url_data[input_position] == '\\'))) {
12589           input_position++;
12590         }
12591         state = ada::state::AUTHORITY;
12592 
12593         break;
12594       }
12595       case ada::state::QUERY: {
12596         ada_log("QUERY ", helpers::substring(url_data, input_position));
12597         // Let queryPercentEncodeSet be the special-query percent-encode set if
12598         // url is special; otherwise the query percent-encode set.
12599         const uint8_t* query_percent_encode_set =
12600             url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12601                              : ada::character_sets::QUERY_PERCENT_ENCODE;
12602 
12603         // Percent-encode after encoding, with encoding, buffer, and
12604         // queryPercentEncodeSet, and append the result to url's query.
12605         url.update_base_search(helpers::substring(url_data, input_position),
12606                                query_percent_encode_set);
12607         ada_log("QUERY update_base_search completed ");
12608         if (fragment.has_value()) {
12609           url.update_unencoded_base_hash(*fragment);
12610         }
12611         return url;
12612       }
12613       case ada::state::HOST: {
12614         ada_log("HOST ", helpers::substring(url_data, input_position));
12615 
12616         std::string_view host_view =
12617             helpers::substring(url_data, input_position);
12618         auto [location, found_colon] =
12619             helpers::get_host_delimiter_location(url.is_special(), host_view);
12620         input_position = (location != std::string_view::npos)
12621                              ? input_position + location
12622                              : input_size;
12623         // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12624         // Note: the 'found_colon' value is true if and only if a colon was
12625         // encountered while not inside brackets.
12626         if (found_colon) {
12627           // If buffer is the empty string, validation error, return failure.
12628           // Let host be the result of host parsing buffer with url is not
12629           // special.
12630           ada_log("HOST parsing ", host_view);
12631           if (!url.parse_host(host_view)) {
12632             return url;
12633           }
12634           ada_log("HOST parsing results in ", url.get_hostname());
12635           // Set url's host to host, buffer to the empty string, and state to
12636           // port state.
12637           state = ada::state::PORT;
12638           input_position++;
12639         }
12640         // Otherwise, if one of the following is true:
12641         // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12642         // - url is special and c is U+005C (\)
12643         // The get_host_delimiter_location function either brings us to
12644         // the colon outside of the bracket, or to one of those characters.
12645         else {
12646           // If url is special and host_view is the empty string, validation
12647           // error, return failure.
12648           if (url.is_special() && host_view.empty()) {
12649             url.is_valid = false;
12650             return url;
12651           }
12652           ada_log("HOST parsing ", host_view, " href=", url.get_href());
12653           // Let host be the result of host parsing host_view with url is not
12654           // special.
12655           if (host_view.empty()) {
12656             url.update_base_hostname("");
12657           } else if (!url.parse_host(host_view)) {
12658             return url;
12659           }
12660           ada_log("HOST parsing results in ", url.get_hostname(),
12661                   " href=", url.get_href());
12662 
12663           // Set url's host to host, and state to path start state.
12664           state = ada::state::PATH_START;
12665         }
12666 
12667         break;
12668       }
12669       case ada::state::OPAQUE_PATH: {
12670         ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
12671         std::string_view view = helpers::substring(url_data, input_position);
12672         // If c is U+003F (?), then set url's query to the empty string and
12673         // state to query state.
12674         size_t location = view.find('?');
12675         if (location != std::string_view::npos) {
12676           view.remove_suffix(view.size() - location);
12677           state = ada::state::QUERY;
12678           input_position += location + 1;
12679         } else {
12680           input_position = input_size + 1;
12681         }
12682         url.has_opaque_path = true;
12683         // This is a really unlikely scenario in real world. We should not seek
12684         // to optimize it.
12685         url.update_base_pathname(unicode::percent_encode(
12686             view, character_sets::C0_CONTROL_PERCENT_ENCODE));
12687         break;
12688       }
12689       case ada::state::PORT: {
12690         ada_log("PORT ", helpers::substring(url_data, input_position));
12691         std::string_view port_view =
12692             helpers::substring(url_data, input_position);
12693         size_t consumed_bytes = url.parse_port(port_view, true);
12694         input_position += consumed_bytes;
12695         if (!url.is_valid) {
12696           return url;
12697         }
12698         state = state::PATH_START;
12699         [[fallthrough]];
12700       }
12701       case ada::state::PATH_START: {
12702         ada_log("PATH_START ", helpers::substring(url_data, input_position));
12703 
12704         // If url is special, then:
12705         if (url.is_special()) {
12706           // Set state to path state.
12707           state = ada::state::PATH;
12708 
12709           // Optimization: Avoiding going into PATH state improves the
12710           // performance of urls ending with /.
12711           if (input_position == input_size) {
12712             url.update_base_pathname("/");
12713             if (fragment.has_value()) {
12714               url.update_unencoded_base_hash(*fragment);
12715             }
12716             return url;
12717           }
12718           // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
12719           // by 1. We know that (input_position == input_size) is impossible
12720           // here, because of the previous if-check.
12721           if ((url_data[input_position] != '/') &&
12722               (url_data[input_position] != '\\')) {
12723             break;
12724           }
12725         }
12726         // Otherwise, if state override is not given and c is U+003F (?),
12727         // set url's query to the empty string and state to query state.
12728         else if ((input_position != input_size) &&
12729                  (url_data[input_position] == '?')) {
12730           state = ada::state::QUERY;
12731         }
12732         // Otherwise, if c is not the EOF code point:
12733         else if (input_position != input_size) {
12734           // Set state to path state.
12735           state = ada::state::PATH;
12736 
12737           // If c is not U+002F (/), then decrease pointer by 1.
12738           if (url_data[input_position] != '/') {
12739             break;
12740           }
12741         }
12742 
12743         input_position++;
12744         break;
12745       }
12746       case ada::state::PATH: {
12747         std::string_view view = helpers::substring(url_data, input_position);
12748         ada_log("PATH ", helpers::substring(url_data, input_position));
12749 
12750         // Most time, we do not need percent encoding.
12751         // Furthermore, we can immediately locate the '?'.
12752         size_t locofquestionmark = view.find('?');
12753         if (locofquestionmark != std::string_view::npos) {
12754           state = ada::state::QUERY;
12755           view.remove_suffix(view.size() - locofquestionmark);
12756           input_position += locofquestionmark + 1;
12757         } else {
12758           input_position = input_size + 1;
12759         }
12760         if constexpr (result_type_is_ada_url) {
12761           helpers::parse_prepared_path(view, url.type, url.path);
12762         } else {
12763           url.consume_prepared_path(view);
12764           ADA_ASSERT_TRUE(url.validate());
12765         }
12766         break;
12767       }
12768       case ada::state::FILE_SLASH: {
12769         ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
12770 
12771         // If c is U+002F (/) or U+005C (\), then:
12772         if ((input_position != input_size) &&
12773             (url_data[input_position] == '/' ||
12774              url_data[input_position] == '\\')) {
12775           ada_log("FILE_SLASH c is U+002F or U+005C");
12776           // Set state to file host state.
12777           state = ada::state::FILE_HOST;
12778           input_position++;
12779         } else {
12780           ada_log("FILE_SLASH otherwise");
12781           // If base is non-null and base's scheme is "file", then:
12782           // Note: it is unsafe to do base_url->scheme unless you know that
12783           // base_url_has_value() is true.
12784           if (base_url != nullptr &&
12785               base_url->type == ada::scheme::type::FILE) {
12786             // Set url's host to base's host.
12787             if constexpr (result_type_is_ada_url) {
12788               url.host = base_url->host;
12789             } else {
12790               // TODO: Optimization opportunity.
12791               url.set_host(base_url->get_host());
12792             }
12793             // If the code point substring from pointer to the end of input does
12794             // not start with a Windows drive letter and base's path[0] is a
12795             // normalized Windows drive letter, then append base's path[0] to
12796             // url's path.
12797             if (!base_url->get_pathname().empty()) {
12798               if (!checkers::is_windows_drive_letter(
12799                       helpers::substring(url_data, input_position))) {
12800                 std::string_view first_base_url_path =
12801                     base_url->get_pathname().substr(1);
12802                 size_t loc = first_base_url_path.find('/');
12803                 if (loc != std::string_view::npos) {
12804                   helpers::resize(first_base_url_path, loc);
12805                 }
12806                 if (checkers::is_normalized_windows_drive_letter(
12807                         first_base_url_path)) {
12808                   if constexpr (result_type_is_ada_url) {
12809                     url.path += '/';
12810                     url.path += first_base_url_path;
12811                   } else {
12812                     url.append_base_pathname(
12813                         helpers::concat("/", first_base_url_path));
12814                   }
12815                 }
12816               }
12817             }
12818           }
12819 
12820           // Set state to path state, and decrease pointer by 1.
12821           state = ada::state::PATH;
12822         }
12823 
12824         break;
12825       }
12826       case ada::state::FILE_HOST: {
12827         std::string_view view = helpers::substring(url_data, input_position);
12828         ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
12829 
12830         size_t location = view.find_first_of("/\\?");
12831         std::string_view file_host_buffer(
12832             view.data(),
12833             (location != std::string_view::npos) ? location : view.size());
12834 
12835         if (checkers::is_windows_drive_letter(file_host_buffer)) {
12836           state = ada::state::PATH;
12837         } else if (file_host_buffer.empty()) {
12838           // Set url's host to the empty string.
12839           if constexpr (result_type_is_ada_url) {
12840             url.host = "";
12841           } else {
12842             url.update_base_hostname("");
12843           }
12844           // Set state to path start state.
12845           state = ada::state::PATH_START;
12846         } else {
12847           size_t consumed_bytes = file_host_buffer.size();
12848           input_position += consumed_bytes;
12849           // Let host be the result of host parsing buffer with url is not
12850           // special.
12851           if (!url.parse_host(file_host_buffer)) {
12852             return url;
12853           }
12854 
12855           if constexpr (result_type_is_ada_url) {
12856             // If host is "localhost", then set host to the empty string.
12857             if (url.host.has_value() && url.host.value() == "localhost") {
12858               url.host = "";
12859             }
12860           } else {
12861             if (url.get_hostname() == "localhost") {
12862               url.update_base_hostname("");
12863             }
12864           }
12865 
12866           // Set buffer to the empty string and state to path start state.
12867           state = ada::state::PATH_START;
12868         }
12869 
12870         break;
12871       }
12872       case ada::state::FILE: {
12873         ada_log("FILE ", helpers::substring(url_data, input_position));
12874         std::string_view file_view =
12875             helpers::substring(url_data, input_position);
12876 
12877         url.set_protocol_as_file();
12878         if constexpr (result_type_is_ada_url) {
12879           // Set url's host to the empty string.
12880           url.host = "";
12881         } else {
12882           url.update_base_hostname("");
12883         }
12884         // If c is U+002F (/) or U+005C (\), then:
12885         if (input_position != input_size &&
12886             (url_data[input_position] == '/' ||
12887              url_data[input_position] == '\\')) {
12888           ada_log("FILE c is U+002F or U+005C");
12889           // Set state to file slash state.
12890           state = ada::state::FILE_SLASH;
12891         }
12892         // Otherwise, if base is non-null and base's scheme is "file":
12893         else if (base_url != nullptr &&
12894                  base_url->type == ada::scheme::type::FILE) {
12895           // Set url's host to base's host, url's path to a clone of base's
12896           // path, and url's query to base's query.
12897           ada_log("FILE base non-null");
12898           if constexpr (result_type_is_ada_url) {
12899             url.host = base_url->host;
12900             url.path = base_url->path;
12901             url.query = base_url->query;
12902           } else {
12903             // TODO: Get rid of set_hostname and replace it with
12904             // update_base_hostname
12905             url.set_hostname(base_url->get_hostname());
12906             url.update_base_pathname(base_url->get_pathname());
12907             url.update_base_search(base_url->get_search());
12908           }
12909           url.has_opaque_path = base_url->has_opaque_path;
12910 
12911           // If c is U+003F (?), then set url's query to the empty string and
12912           // state to query state.
12913           if (input_position != input_size && url_data[input_position] == '?') {
12914             state = ada::state::QUERY;
12915           }
12916           // Otherwise, if c is not the EOF code point:
12917           else if (input_position != input_size) {
12918             // Set url's query to null.
12919             url.clear_search();
12920             // If the code point substring from pointer to the end of input does
12921             // not start with a Windows drive letter, then shorten url's path.
12922             if (!checkers::is_windows_drive_letter(file_view)) {
12923               if constexpr (result_type_is_ada_url) {
12924                 helpers::shorten_path(url.path, url.type);
12925               } else {
12926                 std::string_view path = url.get_pathname();
12927                 if (helpers::shorten_path(path, url.type)) {
12928                   url.update_base_pathname(std::string(path));
12929                 }
12930               }
12931             }
12932             // Otherwise:
12933             else {
12934               // Set url's path to an empty list.
12935               url.clear_pathname();
12936               url.has_opaque_path = true;
12937             }
12938 
12939             // Set state to path state and decrease pointer by 1.
12940             state = ada::state::PATH;
12941             break;
12942           }
12943         }
12944         // Otherwise, set state to path state, and decrease pointer by 1.
12945         else {
12946           ada_log("FILE go to path");
12947           state = ada::state::PATH;
12948           break;
12949         }
12950 
12951         input_position++;
12952         break;
12953       }
12954       default:
12955         ada::unreachable();
12956     }
12957   }
12958   if (fragment.has_value()) {
12959     url.update_unencoded_base_hash(*fragment);
12960   }
12961   return url;
12962 }
12963 
12964 template url parse_url<url>(std::string_view user_input,
12965                             const url* base_url = nullptr);
12966 template url_aggregator parse_url<url_aggregator>(
12967     std::string_view user_input, const url_aggregator* base_url = nullptr);
12968 
12969 }  // namespace ada::parser
12970 /* end file src/parser.cpp */
12971 /* begin file src/url_components.cpp */
12972 
12973 #include <numeric>
12974 #include <string>
12975 
12976 namespace ada {
12977 
check_offset_consistency() const12978 bool url_components::check_offset_consistency() const noexcept {
12979   /**
12980    * https://user:pass@example.com:1234/foo/bar?baz#quux
12981    *       |     |    |          | ^^^^|       |   |
12982    *       |     |    |          | |   |       |   `----- hash_start
12983    *       |     |    |          | |   |       `--------- search_start
12984    *       |     |    |          | |   `----------------- pathname_start
12985    *       |     |    |          | `--------------------- port
12986    *       |     |    |          `----------------------- host_end
12987    *       |     |    `---------------------------------- host_start
12988    *       |     `--------------------------------------- username_end
12989    *       `--------------------------------------------- protocol_end
12990    */
12991   // These conditions can be made more strict.
12992   uint32_t index = 0;
12993 
12994   if (protocol_end == url_components::omitted) {
12995     return false;
12996   }
12997   if (protocol_end < index) {
12998     return false;
12999   }
13000   index = protocol_end;
13001 
13002   if (username_end == url_components::omitted) {
13003     return false;
13004   }
13005   if (username_end < index) {
13006     return false;
13007   }
13008   index = username_end;
13009 
13010   if (host_start == url_components::omitted) {
13011     return false;
13012   }
13013   if (host_start < index) {
13014     return false;
13015   }
13016   index = host_start;
13017 
13018   if (port != url_components::omitted) {
13019     if (port > 0xffff) {
13020       return false;
13021     }
13022     uint32_t port_length = helpers::fast_digit_count(port) + 1;
13023     if (index + port_length < index) {
13024       return false;
13025     }
13026     index += port_length;
13027   }
13028 
13029   if (pathname_start == url_components::omitted) {
13030     return false;
13031   }
13032   if (pathname_start < index) {
13033     return false;
13034   }
13035   index = pathname_start;
13036 
13037   if (search_start != url_components::omitted) {
13038     if (search_start < index) {
13039       return false;
13040     }
13041     index = search_start;
13042   }
13043 
13044   if (hash_start != url_components::omitted) {
13045     if (hash_start < index) {
13046       return false;
13047     }
13048     index = hash_start;
13049   }
13050 
13051   return true;
13052 }
13053 
to_string() const13054 std::string url_components::to_string() const {
13055   std::string answer;
13056   auto back = std::back_insert_iterator(answer);
13057   answer.append("{\n");
13058 
13059   answer.append("\t\"protocol_end\":\"");
13060   helpers::encode_json(std::to_string(protocol_end), back);
13061   answer.append("\",\n");
13062 
13063   answer.append("\t\"username_end\":\"");
13064   helpers::encode_json(std::to_string(username_end), back);
13065   answer.append("\",\n");
13066 
13067   answer.append("\t\"host_start\":\"");
13068   helpers::encode_json(std::to_string(host_start), back);
13069   answer.append("\",\n");
13070 
13071   answer.append("\t\"host_end\":\"");
13072   helpers::encode_json(std::to_string(host_end), back);
13073   answer.append("\",\n");
13074 
13075   answer.append("\t\"port\":\"");
13076   helpers::encode_json(std::to_string(port), back);
13077   answer.append("\",\n");
13078 
13079   answer.append("\t\"pathname_start\":\"");
13080   helpers::encode_json(std::to_string(pathname_start), back);
13081   answer.append("\",\n");
13082 
13083   answer.append("\t\"search_start\":\"");
13084   helpers::encode_json(std::to_string(search_start), back);
13085   answer.append("\",\n");
13086 
13087   answer.append("\t\"hash_start\":\"");
13088   helpers::encode_json(std::to_string(hash_start), back);
13089   answer.append("\",\n");
13090 
13091   answer.append("\n}");
13092   return answer;
13093 }
13094 
13095 }  // namespace ada
13096 /* end file src/url_components.cpp */
13097 /* begin file src/url_aggregator.cpp */
13098 
13099 #include <string>
13100 #include <string_view>
13101 
13102 namespace ada {
13103 template <bool has_state_override>
parse_scheme_with_colon(const std::string_view input_with_colon)13104 [[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13105     const std::string_view input_with_colon) {
13106   ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13107   ADA_ASSERT_TRUE(validate());
13108   ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13109   std::string_view input{input_with_colon};
13110   input.remove_suffix(1);
13111   auto parsed_type = ada::scheme::get_scheme_type(input);
13112   bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13113   /**
13114    * In the common case, we will immediately recognize a special scheme (e.g.,
13115    *http, https), in which case, we can go really fast.
13116    **/
13117   if (is_input_special) {  // fast path!!!
13118     if (has_state_override) {
13119       // If url's scheme is not a special scheme and buffer is a special scheme,
13120       // then return.
13121       if (is_special() != is_input_special) {
13122         return true;
13123       }
13124 
13125       // If url includes credentials or has a non-null port, and buffer is
13126       // "file", then return.
13127       if ((has_credentials() || components.port != url_components::omitted) &&
13128           parsed_type == ada::scheme::type::FILE) {
13129         return true;
13130       }
13131 
13132       // If url's scheme is "file" and its host is an empty host, then return.
13133       // An empty host is the empty string.
13134       if (type == ada::scheme::type::FILE &&
13135           components.host_start == components.host_end) {
13136         return true;
13137       }
13138     }
13139 
13140     type = parsed_type;
13141     set_scheme_from_view_with_colon(input_with_colon);
13142 
13143     if (has_state_override) {
13144       // This is uncommon.
13145       uint16_t urls_scheme_port = get_special_port();
13146 
13147       // If url's port is url's scheme's default port, then set url's port to
13148       // null.
13149       if (components.port == urls_scheme_port) {
13150         clear_port();
13151       }
13152     }
13153   } else {  // slow path
13154     std::string _buffer = std::string(input);
13155     // Next function is only valid if the input is ASCII and returns false
13156     // otherwise, but it seems that we always have ascii content so we do not
13157     // need to check the return value.
13158     unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13159 
13160     if (has_state_override) {
13161       // If url's scheme is a special scheme and buffer is not a special scheme,
13162       // then return. If url's scheme is not a special scheme and buffer is a
13163       // special scheme, then return.
13164       if (is_special() != ada::scheme::is_special(_buffer)) {
13165         return true;
13166       }
13167 
13168       // If url includes credentials or has a non-null port, and buffer is
13169       // "file", then return.
13170       if ((has_credentials() || components.port != url_components::omitted) &&
13171           _buffer == "file") {
13172         return true;
13173       }
13174 
13175       // If url's scheme is "file" and its host is an empty host, then return.
13176       // An empty host is the empty string.
13177       if (type == ada::scheme::type::FILE &&
13178           components.host_start == components.host_end) {
13179         return true;
13180       }
13181     }
13182 
13183     set_scheme(_buffer);
13184 
13185     if (has_state_override) {
13186       // This is uncommon.
13187       uint16_t urls_scheme_port = get_special_port();
13188 
13189       // If url's port is url's scheme's default port, then set url's port to
13190       // null.
13191       if (components.port == urls_scheme_port) {
13192         clear_port();
13193       }
13194     }
13195   }
13196   ADA_ASSERT_TRUE(validate());
13197   return true;
13198 }
13199 
copy_scheme(const url_aggregator & u)13200 inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
13201   ada_log("url_aggregator::copy_scheme ", u.buffer);
13202   ADA_ASSERT_TRUE(validate());
13203   // next line could overflow but unsigned arithmetic has well-defined
13204   // overflows.
13205   uint32_t new_difference = u.components.protocol_end - components.protocol_end;
13206   type = u.type;
13207   buffer.erase(0, components.protocol_end);
13208   buffer.insert(0, u.get_protocol());
13209   components.protocol_end = u.components.protocol_end;
13210 
13211   // No need to update the components
13212   if (new_difference == 0) {
13213     return;
13214   }
13215 
13216   // Update the rest of the components.
13217   components.username_end += new_difference;
13218   components.host_start += new_difference;
13219   components.host_end += new_difference;
13220   components.pathname_start += new_difference;
13221   if (components.search_start != url_components::omitted) {
13222     components.search_start += new_difference;
13223   }
13224   if (components.hash_start != url_components::omitted) {
13225     components.hash_start += new_difference;
13226   }
13227   ADA_ASSERT_TRUE(validate());
13228 }
13229 
set_scheme_from_view_with_colon(std::string_view new_scheme_with_colon)13230 inline void url_aggregator::set_scheme_from_view_with_colon(
13231     std::string_view new_scheme_with_colon) noexcept {
13232   ada_log("url_aggregator::set_scheme_from_view_with_colon ",
13233           new_scheme_with_colon);
13234   ADA_ASSERT_TRUE(validate());
13235   ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
13236                   new_scheme_with_colon.back() == ':');
13237   // next line could overflow but unsigned arithmetic has well-defined
13238   // overflows.
13239   uint32_t new_difference =
13240       uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
13241 
13242   if (buffer.empty()) {
13243     buffer.append(new_scheme_with_colon);
13244   } else {
13245     buffer.erase(0, components.protocol_end);
13246     buffer.insert(0, new_scheme_with_colon);
13247   }
13248   components.protocol_end += new_difference;
13249 
13250   // Update the rest of the components.
13251   components.username_end += new_difference;
13252   components.host_start += new_difference;
13253   components.host_end += new_difference;
13254   components.pathname_start += new_difference;
13255   if (components.search_start != url_components::omitted) {
13256     components.search_start += new_difference;
13257   }
13258   if (components.hash_start != url_components::omitted) {
13259     components.hash_start += new_difference;
13260   }
13261   ADA_ASSERT_TRUE(validate());
13262 }
13263 
set_scheme(std::string_view new_scheme)13264 inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
13265   ada_log("url_aggregator::set_scheme ", new_scheme);
13266   ADA_ASSERT_TRUE(validate());
13267   ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
13268   // next line could overflow but unsigned arithmetic has well-defined
13269   // overflows.
13270   uint32_t new_difference =
13271       uint32_t(new_scheme.size()) - components.protocol_end + 1;
13272 
13273   type = ada::scheme::get_scheme_type(new_scheme);
13274   if (buffer.empty()) {
13275     buffer.append(helpers::concat(new_scheme, ":"));
13276   } else {
13277     buffer.erase(0, components.protocol_end);
13278     buffer.insert(0, helpers::concat(new_scheme, ":"));
13279   }
13280   components.protocol_end = uint32_t(new_scheme.size() + 1);
13281 
13282   // Update the rest of the components.
13283   components.username_end += new_difference;
13284   components.host_start += new_difference;
13285   components.host_end += new_difference;
13286   components.pathname_start += new_difference;
13287   if (components.search_start != url_components::omitted) {
13288     components.search_start += new_difference;
13289   }
13290   if (components.hash_start != url_components::omitted) {
13291     components.hash_start += new_difference;
13292   }
13293   ADA_ASSERT_TRUE(validate());
13294 }
13295 
set_protocol(const std::string_view input)13296 bool url_aggregator::set_protocol(const std::string_view input) {
13297   ada_log("url_aggregator::set_protocol ", input);
13298   ADA_ASSERT_TRUE(validate());
13299   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13300   std::string view(input);
13301   helpers::remove_ascii_tab_or_newline(view);
13302   if (view.empty()) {
13303     return true;
13304   }
13305 
13306   // Schemes should start with alpha values.
13307   if (!checkers::is_alpha(view[0])) {
13308     return false;
13309   }
13310 
13311   view.append(":");
13312 
13313   std::string::iterator pointer =
13314       std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
13315 
13316   if (pointer != view.end() && *pointer == ':') {
13317     return parse_scheme_with_colon<true>(
13318         std::string_view(view.data(), pointer - view.begin() + 1));
13319   }
13320   return false;
13321 }
13322 
set_username(const std::string_view input)13323 bool url_aggregator::set_username(const std::string_view input) {
13324   ada_log("url_aggregator::set_username '", input, "' ");
13325   ADA_ASSERT_TRUE(validate());
13326   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13327   if (cannot_have_credentials_or_port()) {
13328     return false;
13329   }
13330   size_t idx = ada::unicode::percent_encode_index(
13331       input, character_sets::USERINFO_PERCENT_ENCODE);
13332   if (idx == input.size()) {
13333     update_base_username(input);
13334   } else {
13335     // We only create a temporary string if we have to!
13336     update_base_username(ada::unicode::percent_encode(
13337         input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13338   }
13339   ADA_ASSERT_TRUE(validate());
13340   return true;
13341 }
13342 
set_password(const std::string_view input)13343 bool url_aggregator::set_password(const std::string_view input) {
13344   ada_log("url_aggregator::set_password '", input, "'");
13345   ADA_ASSERT_TRUE(validate());
13346   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13347   if (cannot_have_credentials_or_port()) {
13348     return false;
13349   }
13350   size_t idx = ada::unicode::percent_encode_index(
13351       input, character_sets::USERINFO_PERCENT_ENCODE);
13352   if (idx == input.size()) {
13353     update_base_password(input);
13354   } else {
13355     // We only create a temporary string if we have to!
13356     update_base_password(ada::unicode::percent_encode(
13357         input, character_sets::USERINFO_PERCENT_ENCODE, idx));
13358   }
13359   ADA_ASSERT_TRUE(validate());
13360   return true;
13361 }
13362 
set_port(const std::string_view input)13363 bool url_aggregator::set_port(const std::string_view input) {
13364   ada_log("url_aggregator::set_port ", input);
13365   ADA_ASSERT_TRUE(validate());
13366   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13367   if (cannot_have_credentials_or_port()) {
13368     return false;
13369   }
13370   std::string trimmed(input);
13371   helpers::remove_ascii_tab_or_newline(trimmed);
13372   if (trimmed.empty()) {
13373     clear_port();
13374     return true;
13375   }
13376   // Input should not start with control characters.
13377   if (ada::unicode::is_c0_control_or_space(trimmed.front())) {
13378     return false;
13379   }
13380   // Input should contain at least one ascii digit.
13381   if (input.find_first_of("0123456789") == std::string_view::npos) {
13382     return false;
13383   }
13384 
13385   // Revert changes if parse_port fails.
13386   uint32_t previous_port = components.port;
13387   parse_port(trimmed);
13388   if (is_valid) {
13389     return true;
13390   }
13391   update_base_port(previous_port);
13392   is_valid = true;
13393   ADA_ASSERT_TRUE(validate());
13394   return false;
13395 }
13396 
set_pathname(const std::string_view input)13397 bool url_aggregator::set_pathname(const std::string_view input) {
13398   ada_log("url_aggregator::set_pathname ", input);
13399   ADA_ASSERT_TRUE(validate());
13400   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13401   if (has_opaque_path) {
13402     return false;
13403   }
13404   clear_pathname();
13405   parse_path(input);
13406   if (checkers::begins_with(input, "//") && !has_authority() &&
13407       !has_dash_dot()) {
13408     buffer.insert(components.pathname_start, "/.");
13409     components.pathname_start += 2;
13410   }
13411   ADA_ASSERT_TRUE(validate());
13412   return true;
13413 }
13414 
parse_path(std::string_view input)13415 ada_really_inline void url_aggregator::parse_path(std::string_view input) {
13416   ada_log("url_aggregator::parse_path ", input);
13417   ADA_ASSERT_TRUE(validate());
13418   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13419   std::string tmp_buffer;
13420   std::string_view internal_input;
13421   if (unicode::has_tabs_or_newline(input)) {
13422     tmp_buffer = input;
13423     // Optimization opportunity: Instead of copying and then pruning, we could
13424     // just directly build the string from user_input.
13425     helpers::remove_ascii_tab_or_newline(tmp_buffer);
13426     internal_input = tmp_buffer;
13427   } else {
13428     internal_input = input;
13429   }
13430 
13431   // If url is special, then:
13432   if (is_special()) {
13433     if (internal_input.empty()) {
13434       update_base_pathname("/");
13435     } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13436       consume_prepared_path(internal_input.substr(1));
13437     } else {
13438       consume_prepared_path(internal_input);
13439     }
13440   } else if (!internal_input.empty()) {
13441     if (internal_input[0] == '/') {
13442       consume_prepared_path(internal_input.substr(1));
13443     } else {
13444       consume_prepared_path(internal_input);
13445     }
13446   } else {
13447     // Non-special URLs with an empty host can have their paths erased
13448     // Path-only URLs cannot have their paths erased
13449     if (components.host_start == components.host_end && !has_authority()) {
13450       update_base_pathname("/");
13451     }
13452   }
13453   ADA_ASSERT_TRUE(validate());
13454 }
13455 
set_search(const std::string_view input)13456 void url_aggregator::set_search(const std::string_view input) {
13457   ada_log("url_aggregator::set_search ", input);
13458   ADA_ASSERT_TRUE(validate());
13459   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13460   if (input.empty()) {
13461     clear_search();
13462     helpers::strip_trailing_spaces_from_opaque_path(*this);
13463     return;
13464   }
13465 
13466   std::string new_value;
13467   new_value = input[0] == '?' ? input.substr(1) : input;
13468   helpers::remove_ascii_tab_or_newline(new_value);
13469 
13470   auto query_percent_encode_set =
13471       is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13472                    : ada::character_sets::QUERY_PERCENT_ENCODE;
13473 
13474   update_base_search(new_value, query_percent_encode_set);
13475   ADA_ASSERT_TRUE(validate());
13476 }
13477 
set_hash(const std::string_view input)13478 void url_aggregator::set_hash(const std::string_view input) {
13479   ada_log("url_aggregator::set_hash ", input);
13480   ADA_ASSERT_TRUE(validate());
13481   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13482   if (input.empty()) {
13483     if (components.hash_start != url_components::omitted) {
13484       buffer.resize(components.hash_start);
13485       components.hash_start = url_components::omitted;
13486     }
13487     helpers::strip_trailing_spaces_from_opaque_path(*this);
13488     return;
13489   }
13490 
13491   std::string new_value;
13492   new_value = input[0] == '#' ? input.substr(1) : input;
13493   helpers::remove_ascii_tab_or_newline(new_value);
13494   update_unencoded_base_hash(new_value);
13495   ADA_ASSERT_TRUE(validate());
13496 }
13497 
set_href(const std::string_view input)13498 bool url_aggregator::set_href(const std::string_view input) {
13499   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13500   ada_log("url_aggregator::set_href ", input, "[", input.size(), " bytes]");
13501   ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
13502   ada_log("url_aggregator::set_href, success :", out.has_value());
13503 
13504   if (out) {
13505     ada_log("url_aggregator::set_href, parsed ", out->to_string());
13506     // TODO: Figure out why the following line puts test to never finish.
13507     *this = *out;
13508   }
13509 
13510   return out.has_value();
13511 }
13512 
parse_host(std::string_view input)13513 ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
13514   ada_log("url_aggregator:parse_host ", input, "[", input.size(), " bytes]");
13515   ADA_ASSERT_TRUE(validate());
13516   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13517   if (input.empty()) {
13518     return is_valid = false;
13519   }  // technically unnecessary.
13520   // If input starts with U+005B ([), then:
13521   if (input[0] == '[') {
13522     // If input does not end with U+005D (]), validation error, return failure.
13523     if (input.back() != ']') {
13524       return is_valid = false;
13525     }
13526     ada_log("parse_host ipv6");
13527 
13528     // Return the result of IPv6 parsing input with its leading U+005B ([) and
13529     // trailing U+005D (]) removed.
13530     input.remove_prefix(1);
13531     input.remove_suffix(1);
13532     return parse_ipv6(input);
13533   }
13534 
13535   // If isNotSpecial is true, then return the result of opaque-host parsing
13536   // input.
13537   if (!is_special()) {
13538     return parse_opaque_host(input);
13539   }
13540   // Let domain be the result of running UTF-8 decode without BOM on the
13541   // percent-decoding of input. Let asciiDomain be the result of running domain
13542   // to ASCII with domain and false. The most common case is an ASCII input, in
13543   // which case we do not need to call the expensive 'to_ascii' if a few
13544   // conditions are met: no '%' and no 'xn-' subsequence.
13545 
13546   // Often, the input does not contain any forbidden code points, and no upper
13547   // case ASCII letter, then we can just copy it to the buffer. We want to
13548   // optimize for such a common case.
13549   uint8_t is_forbidden_or_upper =
13550       unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
13551                                                              input.size());
13552   // Minor optimization opportunity:
13553   // contains_forbidden_domain_code_point_or_upper could be extend to check for
13554   // the presence of characters that cannot appear in the ipv4 address and we
13555   // could also check whether x and n and - are present, and so we could skip
13556   // some of the checks below. However, the gains are likely to be small, and
13557   // the code would be more complex.
13558   if (is_forbidden_or_upper == 0 &&
13559       input.find("xn-") == std::string_view::npos) {
13560     // fast path
13561     update_base_hostname(input);
13562     if (checkers::is_ipv4(get_hostname())) {
13563       ada_log("parse_host fast path ipv4");
13564       return parse_ipv4(get_hostname());
13565     }
13566     ada_log("parse_host fast path ", get_hostname());
13567     return true;
13568   }
13569   // We have encountered at least one forbidden code point or the input contains
13570   // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
13571   // conversion.
13572 
13573   ada_log("parse_host calling to_ascii");
13574   std::optional<std::string> host = std::string(get_hostname());
13575   is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13576   if (!is_valid) {
13577     ada_log("parse_host to_ascii returns false");
13578     return is_valid = false;
13579   }
13580 
13581   if (std::any_of(host.value().begin(), host.value().end(),
13582                   ada::unicode::is_forbidden_domain_code_point)) {
13583     return is_valid = false;
13584   }
13585 
13586   // If asciiDomain ends in a number, then return the result of IPv4 parsing
13587   // asciiDomain.
13588   if (checkers::is_ipv4(host.value())) {
13589     ada_log("parse_host got ipv4", *host);
13590     return parse_ipv4(host.value());
13591   }
13592 
13593   update_base_hostname(host.value());
13594   ADA_ASSERT_TRUE(validate());
13595   return true;
13596 }
13597 
13598 template <bool override_hostname>
set_host_or_hostname(const std::string_view input)13599 bool url_aggregator::set_host_or_hostname(const std::string_view input) {
13600   ada_log("url_aggregator::set_host_or_hostname ", input);
13601   ADA_ASSERT_TRUE(validate());
13602   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13603   if (has_opaque_path) {
13604     return false;
13605   }
13606 
13607   std::string previous_host = std::string(get_hostname());
13608   uint32_t previous_port = components.port;
13609 
13610   size_t host_end_pos = input.find('#');
13611   std::string _host(input.data(), host_end_pos != std::string_view::npos
13612                                       ? host_end_pos
13613                                       : input.size());
13614   helpers::remove_ascii_tab_or_newline(_host);
13615   std::string_view new_host(_host);
13616 
13617   // If url's scheme is "file", then set state to file host state, instead of
13618   // host state.
13619   if (type != ada::scheme::type::FILE) {
13620     std::string_view host_view(_host.data(), _host.length());
13621     auto [location, found_colon] =
13622         helpers::get_host_delimiter_location(is_special(), host_view);
13623 
13624     // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13625     // Note: the 'found_colon' value is true if and only if a colon was
13626     // encountered while not inside brackets.
13627     if (found_colon) {
13628       if (override_hostname) {
13629         return false;
13630       }
13631       std::string_view sub_buffer = new_host.substr(location + 1);
13632       if (!sub_buffer.empty()) {
13633         set_port(sub_buffer);
13634       }
13635     }
13636     // If url is special and host_view is the empty string, validation error,
13637     // return failure. Otherwise, if state override is given, host_view is the
13638     // empty string, and either url includes credentials or url's port is
13639     // non-null, return.
13640     else if (host_view.empty() &&
13641              (is_special() || has_credentials() ||
13642               components.port != url_components::omitted)) {
13643       return false;
13644     }
13645 
13646     // Let host be the result of host parsing host_view with url is not special.
13647     if (host_view.empty()) {
13648       if (has_hostname()) {
13649         clear_hostname();  // easy!
13650       } else if (has_dash_dot()) {
13651         add_authority_slashes_if_needed();
13652         delete_dash_dot();
13653       }
13654       return true;
13655     }
13656 
13657     bool succeeded = parse_host(host_view);
13658     if (!succeeded) {
13659       update_base_hostname(previous_host);
13660       update_base_port(previous_port);
13661     } else if (has_dash_dot()) {
13662       // Should remove dash_dot from pathname
13663       delete_dash_dot();
13664     }
13665     return succeeded;
13666   }
13667 
13668   size_t location = new_host.find_first_of("/\\?");
13669   if (location != std::string_view::npos) {
13670     new_host.remove_suffix(new_host.length() - location);
13671   }
13672 
13673   if (new_host.empty()) {
13674     // Set url's host to the empty string.
13675     clear_hostname();
13676   } else {
13677     // Let host be the result of host parsing buffer with url is not special.
13678     if (!parse_host(new_host)) {
13679       update_base_hostname(previous_host);
13680       update_base_port(previous_port);
13681       return false;
13682     }
13683 
13684     // If host is "localhost", then set host to the empty string.
13685     if (helpers::substring(buffer, components.host_start,
13686                            components.host_end) == "localhost") {
13687       clear_hostname();
13688     }
13689   }
13690   ADA_ASSERT_TRUE(validate());
13691   return true;
13692 }
13693 
set_host(const std::string_view input)13694 bool url_aggregator::set_host(const std::string_view input) {
13695   ada_log("url_aggregator::set_host '", input, "'");
13696   ADA_ASSERT_TRUE(validate());
13697   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13698   return set_host_or_hostname<false>(input);
13699 }
13700 
set_hostname(const std::string_view input)13701 bool url_aggregator::set_hostname(const std::string_view input) {
13702   ada_log("url_aggregator::set_hostname '", input, "'");
13703   ADA_ASSERT_TRUE(validate());
13704   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
13705   return set_host_or_hostname<true>(input);
13706 }
13707 
get_origin() const13708 [[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
13709   ada_log("url_aggregator::get_origin");
13710   if (is_special()) {
13711     // Return a new opaque origin.
13712     if (type == scheme::FILE) {
13713       return "null";
13714     }
13715 
13716     return helpers::concat(get_protocol(), "//", get_host());
13717   }
13718 
13719   if (get_protocol() == "blob:") {
13720     std::string_view path = get_pathname();
13721     if (!path.empty()) {
13722       auto out = ada::parse<ada::url_aggregator>(path);
13723       if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
13724         // If pathURL's scheme is not "http" and not "https", then return a
13725         // new opaque origin.
13726         return helpers::concat(out->get_protocol(), "//", out->get_host());
13727       }
13728     }
13729   }
13730 
13731   // Return a new opaque origin.
13732   return "null";
13733 }
13734 
get_username() const13735 [[nodiscard]] std::string_view url_aggregator::get_username() const noexcept {
13736   ada_log("url_aggregator::get_username");
13737   if (has_non_empty_username()) {
13738     return helpers::substring(buffer, components.protocol_end + 2,
13739                               components.username_end);
13740   }
13741   return "";
13742 }
13743 
get_password() const13744 [[nodiscard]] std::string_view url_aggregator::get_password() const noexcept {
13745   ada_log("url_aggregator::get_password");
13746   if (has_non_empty_password()) {
13747     return helpers::substring(buffer, components.username_end + 1,
13748                               components.host_start);
13749   }
13750   return "";
13751 }
13752 
get_port() const13753 [[nodiscard]] std::string_view url_aggregator::get_port() const noexcept {
13754   ada_log("url_aggregator::get_port");
13755   if (components.port == url_components::omitted) {
13756     return "";
13757   }
13758   return helpers::substring(buffer, components.host_end + 1,
13759                             components.pathname_start);
13760 }
13761 
get_hash() const13762 [[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept {
13763   ada_log("url_aggregator::get_hash");
13764   // If this's URL's fragment is either null or the empty string, then return
13765   // the empty string. Return U+0023 (#), followed by this's URL's fragment.
13766   if (components.hash_start == url_components::omitted) {
13767     return "";
13768   }
13769   if (buffer.size() - components.hash_start <= 1) {
13770     return "";
13771   }
13772   return helpers::substring(buffer, components.hash_start);
13773 }
13774 
get_host() const13775 [[nodiscard]] std::string_view url_aggregator::get_host() const noexcept {
13776   ada_log("url_aggregator::get_host");
13777   // Technically, we should check if there is a hostname, but
13778   // the code below works even if there isn't.
13779   // if(!has_hostname()) { return ""; }
13780   size_t start = components.host_start;
13781   if (components.host_end > components.host_start &&
13782       buffer[components.host_start] == '@') {
13783     start++;
13784   }
13785   // if we have an empty host, then the space between components.host_end and
13786   // components.pathname_start may be occupied by /.
13787   if (start == components.host_end) {
13788     return std::string_view();
13789   }
13790   return helpers::substring(buffer, start, components.pathname_start);
13791 }
13792 
get_hostname() const13793 [[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept {
13794   ada_log("url_aggregator::get_hostname");
13795   // Technically, we should check if there is a hostname, but
13796   // the code below works even if there isn't.
13797   // if(!has_hostname()) { return ""; }
13798   size_t start = components.host_start;
13799   // So host_start is not where the host begins.
13800   if (components.host_end > components.host_start &&
13801       buffer[components.host_start] == '@') {
13802     start++;
13803   }
13804   return helpers::substring(buffer, start, components.host_end);
13805 }
13806 
get_pathname() const13807 [[nodiscard]] std::string_view url_aggregator::get_pathname() const noexcept {
13808   ada_log("url_aggregator::get_pathname pathname_start = ",
13809           components.pathname_start, " buffer.size() = ", buffer.size(),
13810           " components.search_start = ", components.search_start,
13811           " components.hash_start = ", components.hash_start);
13812   uint32_t ending_index = uint32_t(buffer.size());
13813   if (components.search_start != url_components::omitted) {
13814     ending_index = components.search_start;
13815   } else if (components.hash_start != url_components::omitted) {
13816     ending_index = components.hash_start;
13817   }
13818   return helpers::substring(buffer, components.pathname_start, ending_index);
13819 }
13820 
get_search() const13821 [[nodiscard]] std::string_view url_aggregator::get_search() const noexcept {
13822   ada_log("url_aggregator::get_search");
13823   // If this's URL's query is either null or the empty string, then return the
13824   // empty string. Return U+003F (?), followed by this's URL's query.
13825   if (components.search_start == url_components::omitted) {
13826     return "";
13827   }
13828   uint32_t ending_index = uint32_t(buffer.size());
13829   if (components.hash_start != url_components::omitted) {
13830     ending_index = components.hash_start;
13831   }
13832   if (ending_index - components.search_start <= 1) {
13833     return "";
13834   }
13835   return helpers::substring(buffer, components.search_start, ending_index);
13836 }
13837 
get_protocol() const13838 [[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept {
13839   ada_log("url_aggregator::get_protocol");
13840   return helpers::substring(buffer, 0, components.protocol_end);
13841 }
13842 
to_string() const13843 std::string ada::url_aggregator::to_string() const {
13844   ada_log("url_aggregator::to_string buffer:", buffer, "[", buffer.size(),
13845           " bytes]");
13846   if (!is_valid) {
13847     return "null";
13848   }
13849 
13850   std::string answer;
13851   auto back = std::back_insert_iterator(answer);
13852   answer.append("{\n");
13853 
13854   answer.append("\t\"buffer\":\"");
13855   helpers::encode_json(buffer, back);
13856   answer.append("\",\n");
13857 
13858   answer.append("\t\"protocol\":\"");
13859   helpers::encode_json(get_protocol(), back);
13860   answer.append("\",\n");
13861 
13862   if (has_credentials()) {
13863     answer.append("\t\"username\":\"");
13864     helpers::encode_json(get_username(), back);
13865     answer.append("\",\n");
13866     answer.append("\t\"password\":\"");
13867     helpers::encode_json(get_password(), back);
13868     answer.append("\",\n");
13869   }
13870 
13871   answer.append("\t\"host\":\"");
13872   helpers::encode_json(get_host(), back);
13873   answer.append("\",\n");
13874 
13875   answer.append("\t\"path\":\"");
13876   helpers::encode_json(get_pathname(), back);
13877   answer.append("\",\n");
13878   answer.append("\t\"opaque path\":");
13879   answer.append((has_opaque_path ? "true" : "false"));
13880   answer.append(",\n");
13881 
13882   if (components.search_start != url_components::omitted) {
13883     answer.append("\t\"query\":\"");
13884     helpers::encode_json(get_search(), back);
13885     answer.append("\",\n");
13886   }
13887   if (components.hash_start != url_components::omitted) {
13888     answer.append("\t\"fragment\":\"");
13889     helpers::encode_json(get_hash(), back);
13890     answer.append("\",\n");
13891   }
13892 
13893   auto convert_offset_to_string = [](uint32_t offset) -> std::string {
13894     if (offset == url_components::omitted) {
13895       return "null";
13896     } else {
13897       return std::to_string(offset);
13898     }
13899   };
13900 
13901   answer.append("\t\"protocol_end\":");
13902   answer.append(convert_offset_to_string(components.protocol_end));
13903   answer.append(",\n");
13904 
13905   answer.append("\t\"username_end\":");
13906   answer.append(convert_offset_to_string(components.username_end));
13907   answer.append(",\n");
13908 
13909   answer.append("\t\"host_start\":");
13910   answer.append(convert_offset_to_string(components.host_start));
13911   answer.append(",\n");
13912 
13913   answer.append("\t\"host_end\":");
13914   answer.append(convert_offset_to_string(components.host_end));
13915   answer.append(",\n");
13916 
13917   answer.append("\t\"port\":");
13918   answer.append(convert_offset_to_string(components.port));
13919   answer.append(",\n");
13920 
13921   answer.append("\t\"pathname_start\":");
13922   answer.append(convert_offset_to_string(components.pathname_start));
13923   answer.append(",\n");
13924 
13925   answer.append("\t\"search_start\":");
13926   answer.append(convert_offset_to_string(components.search_start));
13927   answer.append(",\n");
13928 
13929   answer.append("\t\"hash_start\":");
13930   answer.append(convert_offset_to_string(components.hash_start));
13931   answer.append("\n}");
13932 
13933   return answer;
13934 }
13935 
has_valid_domain() const13936 [[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
13937   if (components.host_start == components.host_end) {
13938     return false;
13939   }
13940   return checkers::verify_dns_length(get_hostname());
13941 }
13942 
parse_ipv4(std::string_view input)13943 bool url_aggregator::parse_ipv4(std::string_view input) {
13944   ada_log("parse_ipv4 ", input, "[", input.size(),
13945           " bytes], overlaps with buffer: ",
13946           helpers::overlaps(input, buffer) ? "yes" : "no");
13947   ADA_ASSERT_TRUE(validate());
13948   const bool trailing_dot = (input.back() == '.');
13949   if (trailing_dot) {
13950     input.remove_suffix(1);
13951   }
13952   size_t digit_count{0};
13953   int pure_decimal_count = 0;  // entries that are decimal
13954   uint64_t ipv4{0};
13955   // we could unroll for better performance?
13956   for (; (digit_count < 4) && !(input.empty()); digit_count++) {
13957     uint32_t
13958         segment_result{};  // If any number exceeds 32 bits, we have an error.
13959     bool is_hex = checkers::has_hex_prefix(input);
13960     if (is_hex && ((input.length() == 2) ||
13961                    ((input.length() > 2) && (input[2] == '.')))) {
13962       // special case
13963       segment_result = 0;
13964       input.remove_prefix(2);
13965     } else {
13966       std::from_chars_result r;
13967       if (is_hex) {
13968         r = std::from_chars(input.data() + 2, input.data() + input.size(),
13969                             segment_result, 16);
13970       } else if ((input.length() >= 2) && input[0] == '0' &&
13971                  checkers::is_digit(input[1])) {
13972         r = std::from_chars(input.data() + 1, input.data() + input.size(),
13973                             segment_result, 8);
13974       } else {
13975         pure_decimal_count++;
13976         r = std::from_chars(input.data(), input.data() + input.size(),
13977                             segment_result, 10);
13978       }
13979       if (r.ec != std::errc()) {
13980         return is_valid = false;
13981       }
13982       input.remove_prefix(r.ptr - input.data());
13983     }
13984     if (input.empty()) {
13985       // We have the last value.
13986       // At this stage, ipv4 contains digit_count*8 bits.
13987       // So we have 32-digit_count*8 bits left.
13988       if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) {
13989         return is_valid = false;
13990       }
13991       ipv4 <<= (32 - digit_count * 8);
13992       ipv4 |= segment_result;
13993       goto final;
13994     } else {
13995       // There is more, so that the value must no be larger than 255
13996       // and we must have a '.'.
13997       if ((segment_result > 255) || (input[0] != '.')) {
13998         return is_valid = false;
13999       }
14000       ipv4 <<= 8;
14001       ipv4 |= segment_result;
14002       input.remove_prefix(1);  // remove '.'
14003     }
14004   }
14005   if ((digit_count != 4) || (!input.empty())) {
14006     return is_valid = false;
14007   }
14008 final:
14009   ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14010           " host: ", get_host());
14011 
14012   // We could also check r.ptr to see where the parsing ended.
14013   if (pure_decimal_count == 4 && !trailing_dot) {
14014     // The original input was already all decimal and we validated it. So we
14015     // don't need to do anything.
14016   } else {
14017     // Optimization opportunity: Get rid of unnecessary string return in ipv4
14018     // serializer.
14019     // TODO: This is likely a bug because it goes back update_base_hostname, not
14020     // what we want to do.
14021     update_base_hostname(
14022         ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14023   }
14024   ADA_ASSERT_TRUE(validate());
14025   return true;
14026 }
14027 
parse_ipv6(std::string_view input)14028 bool url_aggregator::parse_ipv6(std::string_view input) {
14029   // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14030   ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]");
14031   ADA_ASSERT_TRUE(validate());
14032   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14033   if (input.empty()) {
14034     return is_valid = false;
14035   }
14036   // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14037   std::array<uint16_t, 8> address{};
14038 
14039   // Let pieceIndex be 0.
14040   int piece_index = 0;
14041 
14042   // Let compress be null.
14043   std::optional<int> compress{};
14044 
14045   // Let pointer be a pointer for input.
14046   std::string_view::iterator pointer = input.begin();
14047 
14048   // If c is U+003A (:), then:
14049   if (input[0] == ':') {
14050     // If remaining does not start with U+003A (:), validation error, return
14051     // failure.
14052     if (input.size() == 1 || input[1] != ':') {
14053       ada_log("parse_ipv6 starts with : but the rest does not start with :");
14054       return is_valid = false;
14055     }
14056 
14057     // Increase pointer by 2.
14058     pointer += 2;
14059 
14060     // Increase pieceIndex by 1 and then set compress to pieceIndex.
14061     compress = ++piece_index;
14062   }
14063 
14064   // While c is not the EOF code point:
14065   while (pointer != input.end()) {
14066     // If pieceIndex is 8, validation error, return failure.
14067     if (piece_index == 8) {
14068       ada_log("parse_ipv6 piece_index == 8");
14069       return is_valid = false;
14070     }
14071 
14072     // If c is U+003A (:), then:
14073     if (*pointer == ':') {
14074       // If compress is non-null, validation error, return failure.
14075       if (compress.has_value()) {
14076         ada_log("parse_ipv6 compress is non-null");
14077         return is_valid = false;
14078       }
14079 
14080       // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
14081       // then continue.
14082       pointer++;
14083       compress = ++piece_index;
14084       continue;
14085     }
14086 
14087     // Let value and length be 0.
14088     uint16_t value = 0, length = 0;
14089 
14090     // While length is less than 4 and c is an ASCII hex digit,
14091     // set value to value times 0x10 + c interpreted as hexadecimal number, and
14092     // increase pointer and length by 1.
14093     while (length < 4 && pointer != input.end() &&
14094            unicode::is_ascii_hex_digit(*pointer)) {
14095       // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14096       value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
14097       pointer++;
14098       length++;
14099     }
14100 
14101     // If c is U+002E (.), then:
14102     if (pointer != input.end() && *pointer == '.') {
14103       // If length is 0, validation error, return failure.
14104       if (length == 0) {
14105         ada_log("parse_ipv6 length is 0");
14106         return is_valid = false;
14107       }
14108 
14109       // Decrease pointer by length.
14110       pointer -= length;
14111 
14112       // If pieceIndex is greater than 6, validation error, return failure.
14113       if (piece_index > 6) {
14114         ada_log("parse_ipv6 piece_index > 6");
14115         return is_valid = false;
14116       }
14117 
14118       // Let numbersSeen be 0.
14119       int numbers_seen = 0;
14120 
14121       // While c is not the EOF code point:
14122       while (pointer != input.end()) {
14123         // Let ipv4Piece be null.
14124         std::optional<uint16_t> ipv4_piece{};
14125 
14126         // If numbersSeen is greater than 0, then:
14127         if (numbers_seen > 0) {
14128           // If c is a U+002E (.) and numbersSeen is less than 4, then increase
14129           // pointer by 1.
14130           if (*pointer == '.' && numbers_seen < 4) {
14131             pointer++;
14132           } else {
14133             // Otherwise, validation error, return failure.
14134             ada_log("parse_ipv6 Otherwise, validation error, return failure");
14135             return is_valid = false;
14136           }
14137         }
14138 
14139         // If c is not an ASCII digit, validation error, return failure.
14140         if (pointer == input.end() || !checkers::is_digit(*pointer)) {
14141           ada_log(
14142               "parse_ipv6 If c is not an ASCII digit, validation error, return "
14143               "failure");
14144           return is_valid = false;
14145         }
14146 
14147         // While c is an ASCII digit:
14148         while (pointer != input.end() && checkers::is_digit(*pointer)) {
14149           // Let number be c interpreted as decimal number.
14150           int number = *pointer - '0';
14151 
14152           // If ipv4Piece is null, then set ipv4Piece to number.
14153           if (!ipv4_piece.has_value()) {
14154             ipv4_piece = number;
14155           }
14156           // Otherwise, if ipv4Piece is 0, validation error, return failure.
14157           else if (ipv4_piece == 0) {
14158             ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
14159             return is_valid = false;
14160           }
14161           // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
14162           else {
14163             ipv4_piece = *ipv4_piece * 10 + number;
14164           }
14165 
14166           // If ipv4Piece is greater than 255, validation error, return failure.
14167           if (ipv4_piece > 255) {
14168             ada_log("parse_ipv6 ipv4_piece > 255");
14169             return is_valid = false;
14170           }
14171 
14172           // Increase pointer by 1.
14173           pointer++;
14174         }
14175 
14176         // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
14177         // ipv4Piece.
14178         // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14179         address[piece_index] =
14180             uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
14181 
14182         // Increase numbersSeen by 1.
14183         numbers_seen++;
14184 
14185         // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
14186         if (numbers_seen == 2 || numbers_seen == 4) {
14187           piece_index++;
14188         }
14189       }
14190 
14191       // If numbersSeen is not 4, validation error, return failure.
14192       if (numbers_seen != 4) {
14193         return is_valid = false;
14194       }
14195 
14196       // Break.
14197       break;
14198     }
14199     // Otherwise, if c is U+003A (:):
14200     else if ((pointer != input.end()) && (*pointer == ':')) {
14201       // Increase pointer by 1.
14202       pointer++;
14203 
14204       // If c is the EOF code point, validation error, return failure.
14205       if (pointer == input.end()) {
14206         ada_log(
14207             "parse_ipv6 If c is the EOF code point, validation error, return "
14208             "failure");
14209         return is_valid = false;
14210       }
14211     }
14212     // Otherwise, if c is not the EOF code point, validation error, return
14213     // failure.
14214     else if (pointer != input.end()) {
14215       ada_log(
14216           "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
14217           "error, return failure");
14218       return is_valid = false;
14219     }
14220 
14221     // Set address[pieceIndex] to value.
14222     address[piece_index] = value;
14223 
14224     // Increase pieceIndex by 1.
14225     piece_index++;
14226   }
14227 
14228   // If compress is non-null, then:
14229   if (compress.has_value()) {
14230     // Let swaps be pieceIndex - compress.
14231     int swaps = piece_index - *compress;
14232 
14233     // Set pieceIndex to 7.
14234     piece_index = 7;
14235 
14236     // While pieceIndex is not 0 and swaps is greater than 0,
14237     // swap address[pieceIndex] with address[compress + swaps - 1], and then
14238     // decrease both pieceIndex and swaps by 1.
14239     while (piece_index != 0 && swaps > 0) {
14240       std::swap(address[piece_index], address[*compress + swaps - 1]);
14241       piece_index--;
14242       swaps--;
14243     }
14244   }
14245   // Otherwise, if compress is null and pieceIndex is not 8, validation error,
14246   // return failure.
14247   else if (piece_index != 8) {
14248     ada_log(
14249         "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
14250         "error, return failure");
14251     return is_valid = false;
14252   }
14253   // TODO: Optimization opportunity: Get rid of unnecessary string creation.
14254   // TODO: This is likely a bug because it goes back update_base_hostname, not
14255   // what we want to do.
14256   update_base_hostname(ada::serializers::ipv6(address));
14257   ada_log("parse_ipv6 ", get_hostname());
14258   ADA_ASSERT_TRUE(validate());
14259   return true;
14260 }
14261 
parse_opaque_host(std::string_view input)14262 bool url_aggregator::parse_opaque_host(std::string_view input) {
14263   ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]");
14264   ADA_ASSERT_TRUE(validate());
14265   ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14266   if (std::any_of(input.begin(), input.end(),
14267                   ada::unicode::is_forbidden_host_code_point)) {
14268     return is_valid = false;
14269   }
14270 
14271   // Return the result of running UTF-8 percent-encode on input using the C0
14272   // control percent-encode set.
14273   size_t idx = ada::unicode::percent_encode_index(
14274       input, character_sets::C0_CONTROL_PERCENT_ENCODE);
14275   if (idx == input.size()) {
14276     update_base_hostname(input);
14277   } else {
14278     // We only create a temporary string if we need to.
14279     update_base_hostname(ada::unicode::percent_encode(
14280         input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
14281   }
14282   ADA_ASSERT_TRUE(validate());
14283   return true;
14284 }
14285 
to_diagram() const14286 std::string url_aggregator::to_diagram() const {
14287   if (!is_valid) {
14288     return "invalid";
14289   }
14290   std::string answer;
14291   answer.append(buffer);
14292   answer.append(" [");
14293   answer.append(std::to_string(buffer.size()));
14294   answer.append(" bytes]");
14295   answer.append("\n");
14296   // first line
14297   std::string line1;
14298   line1.resize(buffer.size(), ' ');
14299   if (components.hash_start != url_components::omitted) {
14300     line1[components.hash_start] = '|';
14301   }
14302   if (components.search_start != url_components::omitted) {
14303     line1[components.search_start] = '|';
14304   }
14305   if (components.pathname_start != buffer.size()) {
14306     line1[components.pathname_start] = '|';
14307   }
14308   if (components.host_end != buffer.size()) {
14309     line1[components.host_end] = '|';
14310   }
14311   if (components.host_start != buffer.size()) {
14312     line1[components.host_start] = '|';
14313   }
14314   if (components.username_end != buffer.size()) {
14315     line1[components.username_end] = '|';
14316   }
14317   if (components.protocol_end != buffer.size()) {
14318     line1[components.protocol_end] = '|';
14319   }
14320   answer.append(line1);
14321   answer.append("\n");
14322 
14323   std::string line2 = line1;
14324   if (components.hash_start != url_components::omitted) {
14325     line2[components.hash_start] = '`';
14326     line1[components.hash_start] = ' ';
14327 
14328     for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
14329       line2[i] = '-';
14330     }
14331     line2.append(" hash_start");
14332     answer.append(line2);
14333     answer.append("\n");
14334   }
14335 
14336   std::string line3 = line1;
14337   if (components.search_start != url_components::omitted) {
14338     line3[components.search_start] = '`';
14339     line1[components.search_start] = ' ';
14340 
14341     for (size_t i = components.search_start + 1; i < line3.size(); i++) {
14342       line3[i] = '-';
14343     }
14344     line3.append(" search_start ");
14345     line3.append(std::to_string(components.search_start));
14346     answer.append(line3);
14347     answer.append("\n");
14348   }
14349 
14350   std::string line4 = line1;
14351   if (components.pathname_start != buffer.size()) {
14352     line4[components.pathname_start] = '`';
14353     line1[components.pathname_start] = ' ';
14354     for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
14355       line4[i] = '-';
14356     }
14357     line4.append(" pathname_start ");
14358     line4.append(std::to_string(components.pathname_start));
14359     answer.append(line4);
14360     answer.append("\n");
14361   }
14362 
14363   std::string line5 = line1;
14364   if (components.host_end != buffer.size()) {
14365     line5[components.host_end] = '`';
14366     line1[components.host_end] = ' ';
14367 
14368     for (size_t i = components.host_end + 1; i < line5.size(); i++) {
14369       line5[i] = '-';
14370     }
14371     line5.append(" host_end ");
14372     line5.append(std::to_string(components.host_end));
14373     answer.append(line5);
14374     answer.append("\n");
14375   }
14376 
14377   std::string line6 = line1;
14378   if (components.host_start != buffer.size()) {
14379     line6[components.host_start] = '`';
14380     line1[components.host_start] = ' ';
14381 
14382     for (size_t i = components.host_start + 1; i < line6.size(); i++) {
14383       line6[i] = '-';
14384     }
14385     line6.append(" host_start ");
14386     line6.append(std::to_string(components.host_start));
14387     answer.append(line6);
14388     answer.append("\n");
14389   }
14390 
14391   std::string line7 = line1;
14392   if (components.username_end != buffer.size()) {
14393     line7[components.username_end] = '`';
14394     line1[components.username_end] = ' ';
14395 
14396     for (size_t i = components.username_end + 1; i < line7.size(); i++) {
14397       line7[i] = '-';
14398     }
14399     line7.append(" username_end ");
14400     line7.append(std::to_string(components.username_end));
14401     answer.append(line7);
14402     answer.append("\n");
14403   }
14404 
14405   std::string line8 = line1;
14406   if (components.protocol_end != buffer.size()) {
14407     line8[components.protocol_end] = '`';
14408     line1[components.protocol_end] = ' ';
14409 
14410     for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
14411       line8[i] = '-';
14412     }
14413     line8.append(" protocol_end ");
14414     line8.append(std::to_string(components.protocol_end));
14415     answer.append(line8);
14416     answer.append("\n");
14417   }
14418 
14419   if (components.hash_start == url_components::omitted) {
14420     answer.append("note: hash omitted\n");
14421   }
14422   if (components.search_start == url_components::omitted) {
14423     answer.append("note: search omitted\n");
14424   }
14425   if (components.protocol_end > buffer.size()) {
14426     answer.append("warning: protocol_end overflows\n");
14427   }
14428   if (components.username_end > buffer.size()) {
14429     answer.append("warning: username_end overflows\n");
14430   }
14431   if (components.host_start > buffer.size()) {
14432     answer.append("warning: host_start overflows\n");
14433   }
14434   if (components.host_end > buffer.size()) {
14435     answer.append("warning: host_end overflows\n");
14436   }
14437   if (components.pathname_start > buffer.size()) {
14438     answer.append("warning: pathname_start overflows\n");
14439   }
14440   return answer;
14441 }
14442 
validate() const14443 bool url_aggregator::validate() const noexcept {
14444   if (!is_valid) {
14445     return true;
14446   }
14447   if (!components.check_offset_consistency()) {
14448     ada_log("url_aggregator::validate inconsistent components \n",
14449             to_diagram());
14450     return false;
14451   }
14452   // We have a credible components struct, but let us investivate more
14453   // carefully:
14454   /**
14455    * https://user:pass@example.com:1234/foo/bar?baz#quux
14456    *       |     |    |          | ^^^^|       |   |
14457    *       |     |    |          | |   |       |   `----- hash_start
14458    *       |     |    |          | |   |       `--------- search_start
14459    *       |     |    |          | |   `----------------- pathname_start
14460    *       |     |    |          | `--------------------- port
14461    *       |     |    |          `----------------------- host_end
14462    *       |     |    `---------------------------------- host_start
14463    *       |     `--------------------------------------- username_end
14464    *       `--------------------------------------------- protocol_end
14465    */
14466   if (components.protocol_end == url_components::omitted) {
14467     ada_log("url_aggregator::validate omitted protocol_end \n", to_diagram());
14468     return false;
14469   }
14470   if (components.username_end == url_components::omitted) {
14471     ada_log("url_aggregator::validate omitted username_end \n", to_diagram());
14472     return false;
14473   }
14474   if (components.host_start == url_components::omitted) {
14475     ada_log("url_aggregator::validate omitted host_start \n", to_diagram());
14476     return false;
14477   }
14478   if (components.host_end == url_components::omitted) {
14479     ada_log("url_aggregator::validate omitted host_end \n", to_diagram());
14480     return false;
14481   }
14482   if (components.pathname_start == url_components::omitted) {
14483     ada_log("url_aggregator::validate omitted pathname_start \n", to_diagram());
14484     return false;
14485   }
14486 
14487   if (components.protocol_end > buffer.size()) {
14488     ada_log("url_aggregator::validate protocol_end overflow \n", to_diagram());
14489     return false;
14490   }
14491   if (components.username_end > buffer.size()) {
14492     ada_log("url_aggregator::validate username_end overflow \n", to_diagram());
14493     return false;
14494   }
14495   if (components.host_start > buffer.size()) {
14496     ada_log("url_aggregator::validate host_start overflow \n", to_diagram());
14497     return false;
14498   }
14499   if (components.host_end > buffer.size()) {
14500     ada_log("url_aggregator::validate host_end overflow \n", to_diagram());
14501     return false;
14502   }
14503   if (components.pathname_start > buffer.size()) {
14504     ada_log("url_aggregator::validate pathname_start overflow \n",
14505             to_diagram());
14506     return false;
14507   }
14508 
14509   if (components.protocol_end > 0) {
14510     if (buffer[components.protocol_end - 1] != ':') {
14511       ada_log(
14512           "url_aggregator::validate missing : at the end of the protocol \n",
14513           to_diagram());
14514       return false;
14515     }
14516   }
14517 
14518   if (components.username_end != buffer.size() &&
14519       components.username_end > components.protocol_end + 2) {
14520     if (buffer[components.username_end] != ':' &&
14521         buffer[components.username_end] != '@') {
14522       ada_log(
14523           "url_aggregator::validate missing : or @ at the end of the username "
14524           "\n",
14525           to_diagram());
14526       return false;
14527     }
14528   }
14529 
14530   if (components.host_start != buffer.size()) {
14531     if (components.host_start > components.username_end) {
14532       if (buffer[components.host_start] != '@') {
14533         ada_log(
14534             "url_aggregator::validate missing @ at the end of the password \n",
14535             to_diagram());
14536         return false;
14537       }
14538     } else if (components.host_start == components.username_end &&
14539                components.host_end > components.host_start) {
14540       if (components.host_start == components.protocol_end + 2) {
14541         if (buffer[components.protocol_end] != '/' ||
14542             buffer[components.protocol_end + 1] != '/') {
14543           ada_log(
14544               "url_aggregator::validate missing // between protocol and host "
14545               "\n",
14546               to_diagram());
14547           return false;
14548         }
14549       } else {
14550         if (components.host_start > components.protocol_end &&
14551             buffer[components.host_start] != '@') {
14552           ada_log(
14553               "url_aggregator::validate missing @ at the end of the username "
14554               "\n",
14555               to_diagram());
14556           return false;
14557         }
14558       }
14559     } else {
14560       if (components.host_end != components.host_start) {
14561         ada_log("url_aggregator::validate expected omitted host \n",
14562                 to_diagram());
14563         return false;
14564       }
14565     }
14566   }
14567   if (components.host_end != buffer.size() &&
14568       components.pathname_start > components.host_end) {
14569     if (components.pathname_start == components.host_end + 2 &&
14570         buffer[components.host_end] == '/' &&
14571         buffer[components.host_end + 1] == '.') {
14572       if (components.pathname_start + 1 >= buffer.size() ||
14573           buffer[components.pathname_start] != '/' ||
14574           buffer[components.pathname_start + 1] != '/') {
14575         ada_log(
14576             "url_aggregator::validate expected the path to begin with // \n",
14577             to_diagram());
14578         return false;
14579       }
14580     } else if (buffer[components.host_end] != ':') {
14581       ada_log("url_aggregator::validate missing : at the port \n",
14582               to_diagram());
14583       return false;
14584     }
14585   }
14586   if (components.pathname_start != buffer.size() &&
14587       components.pathname_start < components.search_start &&
14588       components.pathname_start < components.hash_start && !has_opaque_path) {
14589     if (buffer[components.pathname_start] != '/') {
14590       ada_log("url_aggregator::validate missing / at the path \n",
14591               to_diagram());
14592       return false;
14593     }
14594   }
14595   if (components.search_start != url_components::omitted) {
14596     if (buffer[components.search_start] != '?') {
14597       ada_log("url_aggregator::validate missing ? at the search \n",
14598               to_diagram());
14599       return false;
14600     }
14601   }
14602   if (components.hash_start != url_components::omitted) {
14603     if (buffer[components.hash_start] != '#') {
14604       ada_log("url_aggregator::validate missing # at the hash \n",
14605               to_diagram());
14606       return false;
14607     }
14608   }
14609 
14610   return true;
14611 }
14612 
delete_dash_dot()14613 void url_aggregator::delete_dash_dot() {
14614   ada_log("url_aggregator::delete_dash_dot");
14615   ADA_ASSERT_TRUE(validate());
14616   ADA_ASSERT_TRUE(has_dash_dot());
14617   buffer.erase(components.host_end, 2);
14618   components.pathname_start -= 2;
14619   if (components.search_start != url_components::omitted) {
14620     components.search_start -= 2;
14621   }
14622   if (components.hash_start != url_components::omitted) {
14623     components.hash_start -= 2;
14624   }
14625   ADA_ASSERT_TRUE(validate());
14626   ADA_ASSERT_TRUE(!has_dash_dot());
14627 }
14628 
consume_prepared_path(std::string_view input)14629 inline void url_aggregator::consume_prepared_path(std::string_view input) {
14630   ada_log("url_aggregator::consume_prepared_path ", input);
14631   /***
14632    * This is largely duplicated code from helpers::parse_prepared_path, which is
14633    * unfortunate. This particular function is nearly identical, except that it
14634    * is a method on url_aggregator. The idea is that the trivial path (which is
14635    * very common) merely appends to the buffer. This is the same trivial path as
14636    * with helpers::parse_prepared_path, except that we have the additional check
14637    * for is_at_path(). Otherwise, we grab a copy of the current path and we
14638    * modify it, and then insert it back into the buffer.
14639    */
14640   uint8_t accumulator = checkers::path_signature(input);
14641   // Let us first detect a trivial case.
14642   // If it is special, we check that we have no dot, no %,  no \ and no
14643   // character needing percent encoding. Otherwise, we check that we have no %,
14644   // no dot, and no character needing percent encoding.
14645   constexpr uint8_t need_encoding = 1;
14646   constexpr uint8_t backslash_char = 2;
14647   constexpr uint8_t dot_char = 4;
14648   constexpr uint8_t percent_char = 8;
14649   bool special = type != ada::scheme::NOT_SPECIAL;
14650   bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
14651                                       checkers::is_windows_drive_letter(input));
14652   bool trivial_path =
14653       (special ? (accumulator == 0)
14654                : ((accumulator & (need_encoding | dot_char | percent_char)) ==
14655                   0)) &&
14656       (!may_need_slow_file_handling);
14657   if (accumulator == dot_char && !may_need_slow_file_handling) {
14658     // '4' means that we have at least one dot, but nothing that requires
14659     // percent encoding or decoding. The only part that is not trivial is
14660     // that we may have single dots and double dots path segments.
14661     // If we have such segments, then we either have a path that begins
14662     // with '.' (easy to check), or we have the sequence './'.
14663     // Note: input cannot be empty, it must at least contain one character ('.')
14664     // Note: we know that '\' is not present.
14665     if (input[0] != '.') {
14666       size_t slashdot = input.find("/.");
14667       if (slashdot == std::string_view::npos) {  // common case
14668         trivial_path = true;
14669       } else {  // uncommon
14670         // only three cases matter: /./, /.. or a final /
14671         trivial_path =
14672             !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
14673               input[slashdot + 2] == '/');
14674       }
14675     }
14676   }
14677   if (trivial_path && is_at_path()) {
14678     ada_log("parse_path trivial");
14679     buffer += '/';
14680     buffer += input;
14681     return;
14682   }
14683   std::string path = std::string(get_pathname());
14684   // We are going to need to look a bit at the path, but let us see if we can
14685   // ignore percent encoding *and* backslashes *and* percent characters.
14686   // Except for the trivial case, this is likely to capture 99% of paths out
14687   // there.
14688   bool fast_path =
14689       (special &&
14690        (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
14691       (type != ada::scheme::type::FILE);
14692   if (fast_path) {
14693     ada_log("parse_prepared_path fast");
14694     // Here we don't need to worry about \ or percent encoding.
14695     // We also do not have a file protocol. We might have dots, however,
14696     // but dots must as appear as '.', and they cannot be encoded because
14697     // the symbol '%' is not present.
14698     size_t previous_location = 0;  // We start at 0.
14699     do {
14700       size_t new_location = input.find('/', previous_location);
14701       // std::string_view path_view = input;
14702       //  We process the last segment separately:
14703       if (new_location == std::string_view::npos) {
14704         std::string_view path_view = input.substr(previous_location);
14705         if (path_view == "..") {  // The path ends with ..
14706           // e.g., if you receive ".." with an empty path, you go to "/".
14707           if (path.empty()) {
14708             path = '/';
14709             update_base_pathname(path);
14710             return;
14711           }
14712           // Fast case where we have nothing to do:
14713           if (path.back() == '/') {
14714             update_base_pathname(path);
14715             return;
14716           }
14717           // If you have the path "/joe/myfriend",
14718           // then you delete 'myfriend'.
14719           path.resize(path.rfind('/') + 1);
14720           update_base_pathname(path);
14721           return;
14722         }
14723         path += '/';
14724         if (path_view != ".") {
14725           path.append(path_view);
14726         }
14727         update_base_pathname(path);
14728         return;
14729       } else {
14730         // This is a non-final segment.
14731         std::string_view path_view =
14732             input.substr(previous_location, new_location - previous_location);
14733         previous_location = new_location + 1;
14734         if (path_view == "..") {
14735           size_t last_delimiter = path.rfind('/');
14736           if (last_delimiter != std::string::npos) {
14737             path.erase(last_delimiter);
14738           }
14739         } else if (path_view != ".") {
14740           path += '/';
14741           path.append(path_view);
14742         }
14743       }
14744     } while (true);
14745   } else {
14746     ada_log("parse_path slow");
14747     // we have reached the general case
14748     bool needs_percent_encoding = (accumulator & 1);
14749     std::string path_buffer_tmp;
14750     do {
14751       size_t location = (special && (accumulator & 2))
14752                             ? input.find_first_of("/\\")
14753                             : input.find('/');
14754       std::string_view path_view = input;
14755       if (location != std::string_view::npos) {
14756         path_view.remove_suffix(path_view.size() - location);
14757         input.remove_prefix(location + 1);
14758       }
14759       // path_buffer is either path_view or it might point at a percent encoded
14760       // temporary string.
14761       std::string_view path_buffer =
14762           (needs_percent_encoding &&
14763            ada::unicode::percent_encode<false>(
14764                path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
14765               ? path_buffer_tmp
14766               : path_view;
14767       if (unicode::is_double_dot_path_segment(path_buffer)) {
14768         if ((helpers::shorten_path(path, type) || special) &&
14769             location == std::string_view::npos) {
14770           path += '/';
14771         }
14772       } else if (unicode::is_single_dot_path_segment(path_buffer) &&
14773                  (location == std::string_view::npos)) {
14774         path += '/';
14775       }
14776       // Otherwise, if path_buffer is not a single-dot path segment, then:
14777       else if (!unicode::is_single_dot_path_segment(path_buffer)) {
14778         // If url's scheme is "file", url's path is empty, and path_buffer is a
14779         // Windows drive letter, then replace the second code point in
14780         // path_buffer with U+003A (:).
14781         if (type == ada::scheme::type::FILE && path.empty() &&
14782             checkers::is_windows_drive_letter(path_buffer)) {
14783           path += '/';
14784           path += path_buffer[0];
14785           path += ':';
14786           path_buffer.remove_prefix(2);
14787           path.append(path_buffer);
14788         } else {
14789           // Append path_buffer to url's path.
14790           path += '/';
14791           path.append(path_buffer);
14792         }
14793       }
14794       if (location == std::string_view::npos) {
14795         update_base_pathname(path);
14796         return;
14797       }
14798     } while (true);
14799   }
14800 }
14801 }  // namespace ada
14802 /* end file src/url_aggregator.cpp */
14803 /* begin file src/ada_c.cpp */
14804 
get_instance(void * result)14805 ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
14806   return *(ada::result<ada::url_aggregator>*)result;
14807 }
14808 
14809 extern "C" {
14810 typedef void* ada_url;
14811 
14812 struct ada_string {
14813   const char* data;
14814   size_t length;
14815 };
14816 
14817 struct ada_owned_string {
14818   const char* data;
14819   size_t length;
14820 };
14821 
ada_string_create(const char * data,size_t length)14822 ada_string ada_string_create(const char* data, size_t length) {
14823   ada_string out{};
14824   out.data = data;
14825   out.length = length;
14826   return out;
14827 }
14828 
14829 struct ada_url_components {
14830   /*
14831    * By using 32-bit integers, we implicitly assume that the URL string
14832    * cannot exceed 4 GB.
14833    *
14834    * https://user:pass@example.com:1234/foo/bar?baz#quux
14835    *       |     |    |          | ^^^^|       |   |
14836    *       |     |    |          | |   |       |   `----- hash_start
14837    *       |     |    |          | |   |       `--------- search_start
14838    *       |     |    |          | |   `----------------- pathname_start
14839    *       |     |    |          | `--------------------- port
14840    *       |     |    |          `----------------------- host_end
14841    *       |     |    `---------------------------------- host_start
14842    *       |     `--------------------------------------- username_end
14843    *       `--------------------------------------------- protocol_end
14844    */
14845   uint32_t protocol_end;
14846   /**
14847    * Username end is not `omitted` by default (-1) to make username and password
14848    * getters less costly to implement.
14849    */
14850   uint32_t username_end;
14851   uint32_t host_start;
14852   uint32_t host_end;
14853   uint32_t port;
14854   uint32_t pathname_start;
14855   uint32_t search_start;
14856   uint32_t hash_start;
14857 };
14858 
ada_parse(const char * input,size_t length)14859 ada_url ada_parse(const char* input, size_t length) noexcept {
14860   return new ada::result<ada::url_aggregator>(
14861       ada::parse<ada::url_aggregator>(std::string_view(input, length)));
14862 }
14863 
ada_parse_with_base(const char * input,size_t input_length,const char * base,size_t base_length)14864 ada_url ada_parse_with_base(const char* input, size_t input_length,
14865                             const char* base, size_t base_length) noexcept {
14866   auto base_out =
14867       ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
14868 
14869   if (!base_out) {
14870     return new ada::result<ada::url_aggregator>(base_out);
14871   }
14872 
14873   return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
14874       std::string_view(input, input_length), &base_out.value()));
14875 }
14876 
ada_can_parse(const char * input,size_t length)14877 bool ada_can_parse(const char* input, size_t length) noexcept {
14878   return ada::can_parse(std::string_view(input, length));
14879 }
14880 
ada_can_parse_with_base(const char * input,size_t input_length,const char * base,size_t base_length)14881 bool ada_can_parse_with_base(const char* input, size_t input_length,
14882                              const char* base, size_t base_length) noexcept {
14883   auto base_view = std::string_view(base, base_length);
14884   return ada::can_parse(std::string_view(input, input_length), &base_view);
14885 }
14886 
ada_free(ada_url result)14887 void ada_free(ada_url result) noexcept {
14888   ada::result<ada::url_aggregator>* r =
14889       (ada::result<ada::url_aggregator>*)result;
14890   delete r;
14891 }
14892 
ada_is_valid(ada_url result)14893 bool ada_is_valid(ada_url result) noexcept {
14894   ada::result<ada::url_aggregator>& r = get_instance(result);
14895   return r.has_value();
14896 }
14897 
14898 // caller must free the result with ada_free_owned_string
ada_get_origin(ada_url result)14899 ada_owned_string ada_get_origin(ada_url result) noexcept {
14900   ada::result<ada::url_aggregator>& r = get_instance(result);
14901   ada_owned_string owned;
14902   if (!r) {
14903     owned.data = nullptr;
14904     owned.length = 0;
14905     return owned;
14906   }
14907   std::string out = r->get_origin();
14908   owned.length = out.size();
14909   owned.data = new char[owned.length];
14910   memcpy((void*)owned.data, out.data(), owned.length);
14911   return owned;
14912 }
14913 
ada_free_owned_string(ada_owned_string owned)14914 void ada_free_owned_string(ada_owned_string owned) noexcept {
14915   delete[] owned.data;
14916   owned.data = nullptr;
14917   owned.length = 0;
14918 }
14919 
ada_get_href(ada_url result)14920 ada_string ada_get_href(ada_url result) noexcept {
14921   ada::result<ada::url_aggregator>& r = get_instance(result);
14922   if (!r) {
14923     return ada_string_create(NULL, 0);
14924   }
14925   std::string_view out = r->get_href();
14926   return ada_string_create(out.data(), out.length());
14927 }
14928 
ada_get_username(ada_url result)14929 ada_string ada_get_username(ada_url result) noexcept {
14930   ada::result<ada::url_aggregator>& r = get_instance(result);
14931   if (!r) {
14932     return ada_string_create(NULL, 0);
14933   }
14934   std::string_view out = r->get_username();
14935   return ada_string_create(out.data(), out.length());
14936 }
14937 
ada_get_password(ada_url result)14938 ada_string ada_get_password(ada_url result) noexcept {
14939   ada::result<ada::url_aggregator>& r = get_instance(result);
14940   if (!r) {
14941     return ada_string_create(NULL, 0);
14942   }
14943   std::string_view out = r->get_password();
14944   return ada_string_create(out.data(), out.length());
14945 }
14946 
ada_get_port(ada_url result)14947 ada_string ada_get_port(ada_url result) noexcept {
14948   ada::result<ada::url_aggregator>& r = get_instance(result);
14949   if (!r) {
14950     return ada_string_create(NULL, 0);
14951   }
14952   std::string_view out = r->get_port();
14953   return ada_string_create(out.data(), out.length());
14954 }
14955 
ada_get_hash(ada_url result)14956 ada_string ada_get_hash(ada_url result) noexcept {
14957   ada::result<ada::url_aggregator>& r = get_instance(result);
14958   if (!r) {
14959     return ada_string_create(NULL, 0);
14960   }
14961   std::string_view out = r->get_hash();
14962   return ada_string_create(out.data(), out.length());
14963 }
14964 
ada_get_host(ada_url result)14965 ada_string ada_get_host(ada_url result) noexcept {
14966   ada::result<ada::url_aggregator>& r = get_instance(result);
14967   if (!r) {
14968     return ada_string_create(NULL, 0);
14969   }
14970   std::string_view out = r->get_host();
14971   return ada_string_create(out.data(), out.length());
14972 }
14973 
ada_get_hostname(ada_url result)14974 ada_string ada_get_hostname(ada_url result) noexcept {
14975   ada::result<ada::url_aggregator>& r = get_instance(result);
14976   if (!r) {
14977     return ada_string_create(NULL, 0);
14978   }
14979   std::string_view out = r->get_hostname();
14980   return ada_string_create(out.data(), out.length());
14981 }
14982 
ada_get_pathname(ada_url result)14983 ada_string ada_get_pathname(ada_url result) noexcept {
14984   ada::result<ada::url_aggregator>& r = get_instance(result);
14985   if (!r) {
14986     return ada_string_create(NULL, 0);
14987   }
14988   std::string_view out = r->get_pathname();
14989   return ada_string_create(out.data(), out.length());
14990 }
14991 
ada_get_search(ada_url result)14992 ada_string ada_get_search(ada_url result) noexcept {
14993   ada::result<ada::url_aggregator>& r = get_instance(result);
14994   if (!r) {
14995     return ada_string_create(NULL, 0);
14996   }
14997   std::string_view out = r->get_search();
14998   return ada_string_create(out.data(), out.length());
14999 }
15000 
ada_get_protocol(ada_url result)15001 ada_string ada_get_protocol(ada_url result) noexcept {
15002   ada::result<ada::url_aggregator>& r = get_instance(result);
15003   if (!r) {
15004     return ada_string_create(NULL, 0);
15005   }
15006   std::string_view out = r->get_protocol();
15007   return ada_string_create(out.data(), out.length());
15008 }
15009 
ada_set_href(ada_url result,const char * input,size_t length)15010 bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
15011   ada::result<ada::url_aggregator>& r = get_instance(result);
15012   if (!r) {
15013     return false;
15014   }
15015   return r->set_href(std::string_view(input, length));
15016 }
15017 
ada_set_host(ada_url result,const char * input,size_t length)15018 bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
15019   ada::result<ada::url_aggregator>& r = get_instance(result);
15020   if (!r) {
15021     return false;
15022   }
15023   return r->set_host(std::string_view(input, length));
15024 }
15025 
ada_set_hostname(ada_url result,const char * input,size_t length)15026 bool ada_set_hostname(ada_url result, const char* input,
15027                       size_t length) noexcept {
15028   ada::result<ada::url_aggregator>& r = get_instance(result);
15029   if (!r) {
15030     return false;
15031   }
15032   return r->set_hostname(std::string_view(input, length));
15033 }
15034 
ada_set_protocol(ada_url result,const char * input,size_t length)15035 bool ada_set_protocol(ada_url result, const char* input,
15036                       size_t length) noexcept {
15037   ada::result<ada::url_aggregator>& r = get_instance(result);
15038   if (!r) {
15039     return false;
15040   }
15041   return r->set_protocol(std::string_view(input, length));
15042 }
15043 
ada_set_username(ada_url result,const char * input,size_t length)15044 bool ada_set_username(ada_url result, const char* input,
15045                       size_t length) noexcept {
15046   ada::result<ada::url_aggregator>& r = get_instance(result);
15047   if (!r) {
15048     return false;
15049   }
15050   return r->set_username(std::string_view(input, length));
15051 }
15052 
ada_set_password(ada_url result,const char * input,size_t length)15053 bool ada_set_password(ada_url result, const char* input,
15054                       size_t length) noexcept {
15055   ada::result<ada::url_aggregator>& r = get_instance(result);
15056   if (!r) {
15057     return false;
15058   }
15059   return r->set_password(std::string_view(input, length));
15060 }
15061 
ada_set_port(ada_url result,const char * input,size_t length)15062 bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
15063   ada::result<ada::url_aggregator>& r = get_instance(result);
15064   if (!r) {
15065     return false;
15066   }
15067   return r->set_port(std::string_view(input, length));
15068 }
15069 
ada_set_pathname(ada_url result,const char * input,size_t length)15070 bool ada_set_pathname(ada_url result, const char* input,
15071                       size_t length) noexcept {
15072   ada::result<ada::url_aggregator>& r = get_instance(result);
15073   if (!r) {
15074     return false;
15075   }
15076   return r->set_pathname(std::string_view(input, length));
15077 }
15078 
ada_set_search(ada_url result,const char * input,size_t length)15079 void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
15080   ada::result<ada::url_aggregator>& r = get_instance(result);
15081   if (r) {
15082     r->set_search(std::string_view(input, length));
15083   }
15084 }
15085 
ada_set_hash(ada_url result,const char * input,size_t length)15086 void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
15087   ada::result<ada::url_aggregator>& r = get_instance(result);
15088   if (r) {
15089     r->set_hash(std::string_view(input, length));
15090   }
15091 }
15092 
ada_has_credentials(ada_url result)15093 bool ada_has_credentials(ada_url result) noexcept {
15094   ada::result<ada::url_aggregator>& r = get_instance(result);
15095   if (!r) {
15096     return false;
15097   }
15098   return r->has_credentials();
15099 }
15100 
ada_has_empty_hostname(ada_url result)15101 bool ada_has_empty_hostname(ada_url result) noexcept {
15102   ada::result<ada::url_aggregator>& r = get_instance(result);
15103   if (!r) {
15104     return false;
15105   }
15106   return r->has_empty_hostname();
15107 }
15108 
ada_has_hostname(ada_url result)15109 bool ada_has_hostname(ada_url result) noexcept {
15110   ada::result<ada::url_aggregator>& r = get_instance(result);
15111   if (!r) {
15112     return false;
15113   }
15114   return r->has_hostname();
15115 }
15116 
ada_has_non_empty_username(ada_url result)15117 bool ada_has_non_empty_username(ada_url result) noexcept {
15118   ada::result<ada::url_aggregator>& r = get_instance(result);
15119   if (!r) {
15120     return false;
15121   }
15122   return r->has_non_empty_username();
15123 }
15124 
ada_has_non_empty_password(ada_url result)15125 bool ada_has_non_empty_password(ada_url result) noexcept {
15126   ada::result<ada::url_aggregator>& r = get_instance(result);
15127   if (!r) {
15128     return false;
15129   }
15130   return r->has_non_empty_password();
15131 }
15132 
ada_has_port(ada_url result)15133 bool ada_has_port(ada_url result) noexcept {
15134   ada::result<ada::url_aggregator>& r = get_instance(result);
15135   if (!r) {
15136     return false;
15137   }
15138   return r->has_port();
15139 }
15140 
ada_has_password(ada_url result)15141 bool ada_has_password(ada_url result) noexcept {
15142   ada::result<ada::url_aggregator>& r = get_instance(result);
15143   if (!r) {
15144     return false;
15145   }
15146   return r->has_password();
15147 }
15148 
ada_has_hash(ada_url result)15149 bool ada_has_hash(ada_url result) noexcept {
15150   ada::result<ada::url_aggregator>& r = get_instance(result);
15151   if (!r) {
15152     return false;
15153   }
15154   return r->has_hash();
15155 }
15156 
ada_has_search(ada_url result)15157 bool ada_has_search(ada_url result) noexcept {
15158   ada::result<ada::url_aggregator>& r = get_instance(result);
15159   if (!r) {
15160     return false;
15161   }
15162   return r->has_search();
15163 }
15164 
15165 // returns a pointer to the internal url_aggregator::url_components
ada_get_components(ada_url result)15166 const ada_url_components* ada_get_components(ada_url result) noexcept {
15167   static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
15168   ada::result<ada::url_aggregator>& r = get_instance(result);
15169   if (!r) {
15170     return nullptr;
15171   }
15172   return reinterpret_cast<const ada_url_components*>(&r->get_components());
15173 }
15174 
ada_idna_to_unicode(const char * input,size_t length)15175 ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
15176   std::string out = ada::idna::to_unicode(std::string_view(input, length));
15177   ada_owned_string owned{};
15178   owned.length = out.length();
15179   owned.data = new char[owned.length];
15180   memcpy((void*)owned.data, out.data(), owned.length);
15181   return owned;
15182 }
15183 
ada_idna_to_ascii(const char * input,size_t length)15184 ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
15185   std::string out = ada::idna::to_ascii(std::string_view(input, length));
15186   ada_owned_string owned{};
15187   owned.length = out.size();
15188   owned.data = new char[owned.length];
15189   memcpy((void*)owned.data, out.data(), owned.length);
15190   return owned;
15191 }
15192 
15193 }  // extern "C"
15194 /* end file src/ada_c.cpp */
15195 /* end file src/ada.cpp */
15196