Coverage Report

Created: 2026-02-14 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source
1
/* auto-generated on 2026-02-06 15:50:02 -0500. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
6
#include <algorithm>
7
#include <array>
8
#include <string_view>
9
10
namespace ada::checkers {
11
12
0
ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept {
13
  // The string is not empty and does not contain upper case ASCII characters.
14
  //
15
  // Optimization. To be considered as a possible ipv4, the string must end
16
  // with 'x' or a lowercase hex character.
17
  // Most of the time, this will be false so this simple check will save a lot
18
  // of effort.
19
  // If the address ends with a dot, we need to prune it (special case).
20
0
  if (view.ends_with('.')) {
21
0
    view.remove_suffix(1);
22
0
    if (view.empty()) {
23
0
      return false;
24
0
    }
25
0
  }
26
0
  char last_char = view.back();
27
0
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
0
                       (last_char >= 'a' && last_char <= 'f') ||
29
0
                       last_char == 'x';
30
0
  if (!possible_ipv4) {
31
0
    return false;
32
0
  }
33
  // From the last character, find the last dot.
34
0
  size_t last_dot = view.rfind('.');
35
0
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
0
    view = view.substr(last_dot + 1);
38
0
  }
39
  /** Optimization opportunity: we have basically identified the last number of
40
     the ipv4 if we return true here. We might as well parse it and have at
41
     least one number parsed when we get to parse_ipv4. */
42
0
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
0
    return true;
44
0
  }
45
  // It could be hex (0x), but not if there is a single character.
46
0
  if (view.size() == 1) {
47
0
    return false;
48
0
  }
49
  // It must start with 0x.
50
0
  if (!view.starts_with("0x")) {
51
0
    return false;
52
0
  }
53
  // We must allow "0x".
54
0
  if (view.size() == 2) {
55
0
    return true;
56
0
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
0
  view.remove_prefix(2);
60
0
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
0
}
62
63
// for use with path_signature, we include all characters that need percent
64
// encoding.
65
static constexpr std::array<uint8_t, 256> path_signature_table =
66
    []() consteval {
67
      std::array<uint8_t, 256> result{};
68
      for (size_t i = 0; i < 256; i++) {
69
        if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
70
            i == 0x3f || i == 0x5e || i == 0x60 || i == 0x7b || i == 0x7d ||
71
            i > 0x7e) {
72
          result[i] = 1;
73
        } else if (i == 0x25) {
74
          result[i] = 8;
75
        } else if (i == 0x2e) {
76
          result[i] = 4;
77
        } else if (i == 0x5c) {
78
          result[i] = 2;
79
        } else {
80
          result[i] = 0;
81
        }
82
      }
83
      return result;
84
    }();
85
86
ada_really_inline constexpr uint8_t path_signature(
87
0
    std::string_view input) noexcept {
88
  // The path percent-encode set is the query percent-encode set and U+003F (?),
89
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
90
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
91
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
92
  // controls and all code points greater than U+007E (~).
93
0
  size_t i = 0;
94
0
  uint8_t accumulator{};
95
0
  for (; i + 7 < input.size(); i += 8) {
96
0
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
0
                           path_signature_table[uint8_t(input[i + 1])] |
98
0
                           path_signature_table[uint8_t(input[i + 2])] |
99
0
                           path_signature_table[uint8_t(input[i + 3])] |
100
0
                           path_signature_table[uint8_t(input[i + 4])] |
101
0
                           path_signature_table[uint8_t(input[i + 5])] |
102
0
                           path_signature_table[uint8_t(input[i + 6])] |
103
0
                           path_signature_table[uint8_t(input[i + 7])]);
104
0
  }
105
0
  for (; i < input.size(); i++) {
106
0
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
0
  }
108
0
  return accumulator;
109
0
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
0
    std::string_view input) noexcept {
113
0
  if (input.back() == '.') {
114
0
    if (input.size() > 254) return false;
115
0
  } else if (input.size() > 253)
116
0
    return false;
117
118
0
  size_t start = 0;
119
0
  while (start < input.size()) {
120
0
    auto dot_location = input.find('.', start);
121
    // If not found, it's likely the end of the domain
122
0
    if (dot_location == std::string_view::npos) dot_location = input.size();
123
124
0
    auto label_size = dot_location - start;
125
0
    if (label_size > 63 || label_size == 0) return false;
126
127
0
    start = dot_location + 1;
128
0
  }
129
130
0
  return true;
131
0
}
132
}  // namespace ada::checkers
133
/* end file src/checkers.cpp */
134
/* begin file src/unicode.cpp */
135
136
137
ADA_PUSH_DISABLE_ALL_WARNINGS
138
/* begin file src/ada_idna.cpp */
139
// NOLINTBEGIN: this is an auto-generated file
140
/* auto-generated on 2026-01-30 12:00:02 -0500. Do not edit! */
141
/* begin file src/idna.cpp */
142
/* begin file src/unicode_transcoding.cpp */
143
144
#include <algorithm>
145
#include <cstdint>
146
#include <cstring>
147
148
namespace ada::idna {
149
150
2.42k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
151
2.42k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
152
2.42k
  size_t pos = 0;
153
2.42k
  const char32_t* start{utf32_output};
154
33.2k
  while (pos < len) {
155
    // try to convert the next block of 16 ASCII bytes
156
30.9k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
157
                            // bytes, check that they are ascii
158
19.7k
      uint64_t v1;
159
19.7k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
160
19.7k
      uint64_t v2;
161
19.7k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
162
19.7k
      uint64_t v{v1 | v2};
163
19.7k
      if ((v & 0x8080808080808080) == 0) {
164
817
        size_t final_pos = pos + 16;
165
13.8k
        while (pos < final_pos) {
166
13.0k
          *utf32_output++ = char32_t(buf[pos]);
167
13.0k
          pos++;
168
13.0k
        }
169
817
        continue;
170
817
      }
171
19.7k
    }
172
30.1k
    uint8_t leading_byte = data[pos];  // leading byte
173
30.1k
    if (leading_byte < 0b10000000) {
174
      // converting one ASCII byte !!!
175
13.2k
      *utf32_output++ = char32_t(leading_byte);
176
13.2k
      pos++;
177
16.9k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
178
      // We have a two-byte UTF-8
179
3.68k
      if (pos + 1 >= len) {
180
11
        return 0;
181
11
      }  // minimal bound checking
182
3.67k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
183
21
        return 0;
184
21
      }
185
      // range check
186
3.65k
      uint32_t code_point =
187
3.65k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
188
3.65k
      if (code_point < 0x80 || 0x7ff < code_point) {
189
3
        return 0;
190
3
      }
191
3.65k
      *utf32_output++ = char32_t(code_point);
192
3.65k
      pos += 2;
193
13.2k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
194
      // We have a three-byte UTF-8
195
12.7k
      if (pos + 2 >= len) {
196
11
        return 0;
197
11
      }  // minimal bound checking
198
199
12.7k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
200
9
        return 0;
201
9
      }
202
12.7k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
203
4
        return 0;
204
4
      }
205
      // range check
206
12.7k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
207
12.7k
                            (data[pos + 1] & 0b00111111) << 6 |
208
12.7k
                            (data[pos + 2] & 0b00111111);
209
12.7k
      if (code_point < 0x800 || 0xffff < code_point ||
210
12.7k
          (0xd7ff < code_point && code_point < 0xe000)) {
211
7
        return 0;
212
7
      }
213
12.7k
      *utf32_output++ = char32_t(code_point);
214
12.7k
      pos += 3;
215
12.7k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
216
      // we have a 4-byte UTF-8 word.
217
437
      if (pos + 3 >= len) {
218
12
        return 0;
219
12
      }  // minimal bound checking
220
425
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
221
7
        return 0;
222
7
      }
223
418
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
224
1
        return 0;
225
1
      }
226
417
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
227
4
        return 0;
228
4
      }
229
230
      // range check
231
413
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
232
413
                            (data[pos + 1] & 0b00111111) << 12 |
233
413
                            (data[pos + 2] & 0b00111111) << 6 |
234
413
                            (data[pos + 3] & 0b00111111);
235
413
      if (code_point <= 0xffff || 0x10ffff < code_point) {
236
10
        return 0;
237
10
      }
238
403
      *utf32_output++ = char32_t(code_point);
239
403
      pos += 4;
240
403
    } else {
241
73
      return 0;
242
73
    }
243
30.1k
  }
244
2.25k
  return utf32_output - start;
245
2.42k
}
246
247
2.34k
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
248
  // We are not BOM aware.
249
2.34k
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
250
2.34k
  size_t counter{0};
251
12.5k
  for (size_t i = 0; i != len; ++i) {
252
10.2k
    ++counter;                                      // ASCII
253
10.2k
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
254
10.2k
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
255
10.2k
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
256
10.2k
  }
257
2.34k
  return counter;
258
2.34k
}
259
260
2.42k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
261
2.42k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
262
77.7k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
263
    // -65 is 0b10111111, anything larger in two-complement's
264
    // should start a new code point.
265
77.7k
    return c > -65;
266
77.7k
  });
267
2.42k
}
268
269
2.34k
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
270
2.34k
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
271
2.34k
  size_t pos = 0;
272
2.34k
  const char* start{utf8_output};
273
11.2k
  while (pos < len) {
274
    // try to convert the next block of 2 ASCII characters
275
9.10k
    if (pos + 2 <= len) {  // if it is safe to read 8 more
276
                           // bytes, check that they are ascii
277
7.13k
      uint64_t v;
278
7.13k
      std::memcpy(&v, data + pos, sizeof(uint64_t));
279
7.13k
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
280
864
        *utf8_output++ = char(buf[pos]);
281
864
        *utf8_output++ = char(buf[pos + 1]);
282
864
        pos += 2;
283
864
        continue;
284
864
      }
285
7.13k
    }
286
8.24k
    uint32_t word = data[pos];
287
8.24k
    if ((word & 0xFFFFFF80) == 0) {
288
      // will generate one UTF-8 bytes
289
325
      *utf8_output++ = char(word);
290
325
      pos++;
291
7.91k
    } else if ((word & 0xFFFFF800) == 0) {
292
      // will generate two UTF-8 bytes
293
      // we have 0b110XXXXX 0b10XXXXXX
294
3.11k
      *utf8_output++ = char((word >> 6) | 0b11000000);
295
3.11k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
296
3.11k
      pos++;
297
4.80k
    } else if ((word & 0xFFFF0000) == 0) {
298
      // will generate three UTF-8 bytes
299
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
300
1.86k
      if (word >= 0xD800 && word <= 0xDFFF) {
301
49
        return 0;
302
49
      }
303
1.81k
      *utf8_output++ = char((word >> 12) | 0b11100000);
304
1.81k
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
305
1.81k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
306
1.81k
      pos++;
307
2.94k
    } else {
308
      // will generate four UTF-8 bytes
309
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
310
      // 0b10XXXXXX
311
2.94k
      if (word > 0x10FFFF) {
312
165
        return 0;
313
165
      }
314
2.78k
      *utf8_output++ = char((word >> 18) | 0b11110000);
315
2.78k
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
316
2.78k
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
317
2.78k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
318
2.78k
      pos++;
319
2.78k
    }
320
8.24k
  }
321
2.13k
  return utf8_output - start;
322
2.34k
}
323
}  // namespace ada::idna
324
/* end file src/unicode_transcoding.cpp */
325
/* begin file src/mapping.cpp */
326
327
#include <algorithm>
328
#include <array>
329
#include <string>
330
331
/* begin file src/mapping_tables.cpp */
332
// IDNA  17.0.0
333
334
// clang-format off
335
#ifndef ADA_IDNA_TABLES_H
336
#define ADA_IDNA_TABLES_H
337
#include <cstdint>
338
339
namespace ada::idna {
340
341
const uint32_t mappings[5264] =
342
{
343
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
344
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
345
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
346
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
347
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
348
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
349
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
350
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
351
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
352
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
353
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
354
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
355
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
356
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
357
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
358
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
359
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
360
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
361
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
362
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
363
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
364
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
365
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
366
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
367
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
368
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
369
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
370
  1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243,
371
  1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271,
372
  1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
373
  1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327,
374
  1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390,
375
  1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404,
376
  1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652,
377
  1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364,
378
  2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492,
379
  2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876,
380
  2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916,
381
  4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018,
382
  3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001,
383
  4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525,
384
  11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537,
385
  11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549,
386
  11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104,
387
  5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310,
388
  4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325,
389
  4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339,
390
  4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604,
391
  7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671,
392
  625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689,
393
  7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717,
394
  7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745,
395
  7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773,
396
  7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801,
397
  7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829,
398
  97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861,
399
  7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889,
400
  7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917,
401
  7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940,
402
  7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972,
403
  7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002,
404
  8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038,
405
  8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953,
406
  7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974,
407
  953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953,
408
  8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32,
409
  787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32,
410
  787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788,
411
  769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969,
412
  953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245,
413
  8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55,
414
  56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99,
415
  47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491,
416
  102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51,
417
  50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260,
418
  54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105,
419
  105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120,
420
  120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750,
421
  8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49,
422
  55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40,
423
  53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49,
424
  49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49,
425
  54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97,
426
  41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41,
427
  40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40,
428
  110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116,
429
  41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41,
430
  58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318,
431
  11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330,
432
  11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342,
433
  11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354,
434
  11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379,
435
  11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409,
436
  11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433,
437
  11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457,
438
  11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481,
439
  11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968,
440
  20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866,
441
  20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340,
442
  21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823,
443
  22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049,
444
  24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515,
445
  25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352,
446
  26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700,
447
  28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916,
448
  29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446,
449
  30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566,
450
  32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267,
451
  33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915,
452
  35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275,
453
  36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272,
454
  38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913,
455
  39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730,
456
  39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701,
457
  40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316,
458
  21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354,
459
  4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359,
460
  4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450,
461
  4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464,
462
  4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569,
463
  4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398,
464
  4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488,
465
  4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969,
466
  22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358,
467
  41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367,
468
  41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40,
469
  45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500,
470
  41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40,
471
  54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968,
472
  41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40,
473
  19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779,
474
  41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40,
475
  26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001,
476
  41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40,
477
  30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241,
478
  41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50,
479
  52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280,
480
  44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889,
481
  27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48,
482
  52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51,
483
  26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48,
484
  26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116,
485
  100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471,
486
  12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494,
487
  12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518,
488
  12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644,
489
  12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450,
490
  12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457,
491
  12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531,
492
  12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459,
493
  12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462,
494
  12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525,
495
  12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461,
496
  12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476,
497
  12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490,
498
  12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512,
499
  12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540,
500
  12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452,
501
  12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524,
502
  12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499,
503
  12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483,
504
  12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506,
505
  12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540,
506
  12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507,
507
  12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452,
508
  12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510,
509
  12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522,
510
  12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489,
511
  12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521,
512
  12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488,
513
  12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857,
514
  54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50,
515
  28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857,
516
  49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51,
517
  28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112,
518
  99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644,
519
  22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97,
520
  107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110,
521
  102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104,
522
  122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109,
523
  109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109,
524
  51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97,
525
  109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100,
526
  8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956,
527
  118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107,
528
  969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110,
529
  107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111,
530
  108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725,
531
  109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085,
532
  56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085,
533
  49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57,
534
  26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085,
535
  50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48,
536
  26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575,
537
  42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599,
538
  42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641,
539
  42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799,
540
  42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825,
541
  42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849,
542
  42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881,
543
  42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913,
544
  42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941,
545
  42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42959, 42961, 42963,
546
  42965, 42967, 42969, 42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027,
547
  5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041,
548
  5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055,
549
  5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069,
550
  5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083,
551
  5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097,
552
  5098, 5099, 5100, 5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865,
553
  21895, 22856, 25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889,
554
  29662, 33853, 37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651,
555
  34253, 35172, 25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919,
556
  21214, 25796, 27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860,
557
  31103, 32160, 33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034,
558
  38647, 22744, 23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956,
559
  20940, 31260, 32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575,
560
  30064, 21271, 30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465,
561
  33865, 35498, 27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753,
562
  31975, 33391, 35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530,
563
  40599, 40654, 26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833,
564
  31178, 32244, 32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010,
565
  24265, 24565, 25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666,
566
  32838, 37428, 38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698,
567
  23534, 23615, 26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611,
568
  27969, 28316, 29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138,
569
  36650, 24459, 24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877,
570
  29702, 30178, 32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298,
571
  38563, 40023, 40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160,
572
  33590, 21050, 20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275,
573
  20800, 21952, 22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742,
574
  31934, 34322, 35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398,
575
  20711, 20813, 21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724,
576
  24936, 24974, 25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227,
577
  29730, 30865, 31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265,
578
  32321, 32626, 32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104,
579
  36790, 38627, 38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805,
580
  20864, 21191, 21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274,
581
  24281, 24425, 24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942,
582
  26395, 26454, 28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237,
583
  30239, 30427, 30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775,
584
  34681, 35137, 35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524,
585
  38875, 38923, 39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832,
586
  163539, 40771, 40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396,
587
  1381, 1396, 1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499,
588
  1500, 1501, 1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474,
589
  1488, 1463, 1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468,
590
  1493, 1468, 1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468,
591
  1502, 1468, 1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468,
592
  1512, 1468, 1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500,
593
  1649, 1659, 1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677,
594
  1676, 1678, 1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726,
595
  1746, 1747, 1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749,
596
  1574, 1608, 1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574,
597
  1580, 1574, 1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576,
598
  1605, 1576, 1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578,
599
  1609, 1578, 1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580,
600
  1605, 1581, 1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587,
601
  1582, 1587, 1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590,
602
  1605, 1591, 1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594,
603
  1605, 1601, 1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602,
604
  1581, 1602, 1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603,
605
  1582, 1603, 1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604,
606
  1582, 1604, 1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605,
607
  1610, 1606, 1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607,
608
  1580, 1607, 1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584,
609
  1648, 1585, 1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32,
610
  1615, 1617, 32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606,
611
  1576, 1585, 1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585,
612
  1579, 1586, 1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585,
613
  1610, 1586, 1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607,
614
  1606, 1607, 1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614,
615
  1617, 1600, 1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593,
616
  1610, 1594, 1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581,
617
  1609, 1580, 1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590,
618
  1610, 1588, 1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590,
619
  1585, 1575, 1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582,
620
  1605, 1578, 1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581,
621
  1605, 1609, 1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581,
622
  1587, 1605, 1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581,
623
  1605, 1588, 1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590,
624
  1582, 1605, 1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605,
625
  1593, 1605, 1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605,
626
  1609, 1601, 1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604,
627
  1581, 1610, 1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581,
628
  1605, 1581, 1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580,
629
  1582, 1607, 1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606,
630
  1580, 1605, 1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605,
631
  1576, 1582, 1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582,
632
  1609, 1578, 1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580,
633
  1605, 1609, 1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610,
634
  1604, 1580, 1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605,
635
  1610, 1602, 1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606,
636
  1580, 1581, 1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610,
637
  1581, 1580, 1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582,
638
  1610, 1606, 1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607,
639
  1575, 1603, 1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587,
640
  1608, 1604, 1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589,
641
  1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587,
642
  1604, 1605, 1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604,
643
  44, 12289, 12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298,
644
  12299, 12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64,
645
  32, 1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572,
646
  1573, 1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630,
647
  12539, 12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595,
648
  9632, 9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609,
649
  66610, 66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621,
650
  66622, 66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633,
651
  66634, 66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781,
652
  66782, 66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793,
653
  66794, 66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805,
654
  66806, 66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972,
655
  66973, 66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985,
656
  66986, 66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998,
657
  66999, 67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600,
658
  606, 681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630,
659
  630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448,
660
  449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807,
661
  68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819,
662
  68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
663
  68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843,
664
  68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980,
665
  68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992,
666
  68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878,
667
  71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890,
668
  71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902,
669
  71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802,
670
  93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814,
671
  93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 93883, 93884, 93885,
672
  93886, 93887, 93888, 93889, 93890, 93891, 93892, 93893, 93894, 93895, 93896, 93897,
673
  93898, 93899, 93900, 93901, 93902, 93903, 93904, 93905, 93906, 93907, 119127, 119141,
674
  119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141,
675
  119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226,
676
  119141, 119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151,
677
  119226, 119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222,
678
  125223, 125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232,
679
  125233, 125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242,
680
  125243, 125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697,
681
  1647, 48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57,
682
  44, 12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119,
683
  99, 109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299,
684
  20132, 26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561,
685
  28436, 25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106,
686
  21942, 37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308,
687
  23433, 12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308,
688
  21213, 12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320,
689
  20411, 20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497,
690
  20839, 132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111,
691
  13589, 21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471,
692
  133987, 21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843,
693
  21859, 21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516,
694
  22541, 22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872,
695
  136938, 23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491,
696
  23512, 23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875,
697
  138726, 23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434,
698
  139651, 14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056,
699
  156122, 24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012,
700
  24775, 24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300,
701
  25424, 142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894,
702
  25705, 25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112,
703
  15076, 20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177,
704
  26618, 26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059,
705
  27355, 15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507,
706
  146170, 27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718,
707
  27956, 28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614,
708
  28729, 28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395,
709
  29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605,
710
  16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679,
711
  30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494,
712
  30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211,
713
  16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935,
714
  154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325,
715
  17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963,
716
  32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607,
717
  157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457,
718
  33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738,
719
  33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148,
720
  159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440,
721
  34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031,
722
  35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011,
723
  36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330,
724
  165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909,
725
  166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474,
726
  19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209,
727
  39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704,
728
  172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568,
729
730
};
731
const uint32_t table[8198][2] =
732
{
733
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
734
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
735
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
736
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
737
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
738
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
739
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
740
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
741
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
742
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
743
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
744
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
745
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
746
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
747
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
748
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
749
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
750
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
751
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
752
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
753
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
754
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
755
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
756
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
757
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
758
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
759
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
760
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
761
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
762
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
763
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
764
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
765
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
766
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
767
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
768
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
769
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
770
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
771
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
772
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
773
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
774
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
775
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
776
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
777
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
778
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
779
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
780
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
781
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
782
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
783
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
784
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
785
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
786
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
787
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
788
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
789
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
790
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
791
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
792
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
793
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
794
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
795
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
796
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
797
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
798
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
799
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
800
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
801
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
802
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
803
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
804
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
805
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
806
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
807
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
808
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
809
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
810
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
811
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
812
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
813
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
814
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
815
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
816
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
817
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
818
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
819
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
820
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
821
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
822
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
823
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
824
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
825
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
826
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
827
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
828
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
829
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
830
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
831
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
832
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
833
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
834
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
835
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
836
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
837
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
838
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
839
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
840
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
841
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
842
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
843
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
844
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
845
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
846
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
847
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
848
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
849
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
850
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
851
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
852
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
853
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
854
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
855
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
856
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
857
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
858
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
859
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
860
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
861
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
862
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
863
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
864
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
865
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
866
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
867
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
868
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
869
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
870
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
871
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
872
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
873
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
874
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
875
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
876
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
877
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
878
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
879
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
880
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
881
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
882
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
883
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
884
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
885
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
886
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
887
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
888
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
889
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
890
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
891
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
892
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
893
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
894
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
895
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
896
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
897
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
898
  {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531},
899
  {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043},
900
  {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555},
901
  {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067},
902
  {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579},
903
  {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091},
904
  {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603},
905
  {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115},
906
  {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627},
907
  {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139},
908
  {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651},
909
  {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163},
910
  {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675},
911
  {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187},
912
  {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699},
913
  {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211},
914
  {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723},
915
  {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235},
916
  {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747},
917
  {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259},
918
  {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771},
919
  {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283},
920
  {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795},
921
  {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307},
922
  {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819},
923
  {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331},
924
  {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843},
925
  {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2},
926
  {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123},
927
  {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147},
928
  {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171},
929
  {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195},
930
  {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219},
931
  {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243},
932
  {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267},
933
  {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291},
934
  {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315},
935
  {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1},
936
  {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1},
937
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
938
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
939
  {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323},
940
  {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2},
941
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
942
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
943
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
944
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
945
  {2144, 1}, {2155, 2}, {2160, 1}, {2192, 2},
946
  {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859},
947
  {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907},
948
  {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1},
949
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
950
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
951
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
952
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
953
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
954
  {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2},
955
  {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1},
956
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
957
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
958
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
959
  {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003},
960
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
961
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
962
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
963
  {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539},
964
  {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2},
965
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
966
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
967
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
968
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
969
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
970
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
971
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
972
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
973
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
974
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
975
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
976
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
977
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
978
  {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1},
979
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
980
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
981
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
982
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
983
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
984
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
985
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
986
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
987
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
988
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
989
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
990
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
991
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
992
  {3163, 2}, {3164, 1}, {3166, 2}, {3168, 1},
993
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
994
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
995
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
996
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
997
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
998
  {3287, 2}, {3292, 1}, {3295, 2}, {3296, 1},
999
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
1000
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
1001
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
1002
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
1003
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
1004
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
1005
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
1006
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
1007
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
1008
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
1009
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
1010
  {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1},
1011
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1012
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1013
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1014
  {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1},
1015
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1016
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611},
1017
  {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1},
1018
  {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1},
1019
  {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1},
1020
  {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1},
1021
  {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1},
1022
  {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1},
1023
  {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267},
1024
  {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1},
1025
  {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1},
1026
  {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1},
1027
  {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1},
1028
  {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1},
1029
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1030
  {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171},
1031
  {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195},
1032
  {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219},
1033
  {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243},
1034
  {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267},
1035
  {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291},
1036
  {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315},
1037
  {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339},
1038
  {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363},
1039
  {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131},
1040
  {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1},
1041
  {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1},
1042
  {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1},
1043
  {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1},
1044
  {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1},
1045
  {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1},
1046
  {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1},
1047
  {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1},
1048
  {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1},
1049
  {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1},
1050
  {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1},
1051
  {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411},
1052
  {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2},
1053
  {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2},
1054
  {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2},
1055
  {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2},
1056
  {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2},
1057
  {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0},
1058
  {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2},
1059
  {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0},
1060
  {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2},
1061
  {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2},
1062
  {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2},
1063
  {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2},
1064
  {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2},
1065
  {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2},
1066
  {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2},
1067
  {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2},
1068
  {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2},
1069
  {6816, 1}, {6830, 2}, {6832, 1}, {6878, 2},
1070
  {6880, 1}, {6892, 2}, {6912, 1}, {6989, 2},
1071
  {6990, 1}, {7156, 2}, {7164, 1}, {7224, 2},
1072
  {7227, 1}, {7242, 2}, {7245, 1}, {7296, 16867075},
1073
  {7297, 16867587}, {7298, 16870147}, {7299, 16870915}, {7300, 16871171},
1074
  {7302, 16873219}, {7303, 16875011}, {7304, 16946435}, {7305, 16946691},
1075
  {7306, 1}, {7307, 2}, {7312, 16946947}, {7313, 16947203},
1076
  {7314, 16947459}, {7315, 16947715}, {7316, 16947971}, {7317, 16948227},
1077
  {7318, 16948483}, {7319, 16948739}, {7320, 16948995}, {7321, 16949251},
1078
  {7322, 16949507}, {7323, 16949763}, {7324, 16944643}, {7325, 16950019},
1079
  {7326, 16950275}, {7327, 16950531}, {7328, 16950787}, {7329, 16951043},
1080
  {7330, 16951299}, {7331, 16951555}, {7332, 16951811}, {7333, 16952067},
1081
  {7334, 16952323}, {7335, 16952579}, {7336, 16952835}, {7337, 16953091},
1082
  {7338, 16953347}, {7339, 16953603}, {7340, 16953859}, {7341, 16954115},
1083
  {7342, 16954371}, {7343, 16954627}, {7344, 16954883}, {7345, 16955139},
1084
  {7346, 16955395}, {7347, 16955651}, {7348, 16955907}, {7349, 16956163},
1085
  {7350, 16956419}, {7351, 16956675}, {7352, 16956931}, {7353, 16957187},
1086
  {7354, 16957443}, {7355, 2}, {7357, 16957699}, {7358, 16957955},
1087
  {7359, 16958211}, {7360, 1}, {7368, 2}, {7376, 1},
1088
  {7419, 2}, {7424, 1}, {7468, 16777219}, {7469, 16791043},
1089
  {7470, 16777475}, {7471, 1}, {7472, 16777987}, {7473, 16778243},
1090
  {7474, 16816131}, {7475, 16778755}, {7476, 16779011}, {7477, 16779267},
1091
  {7478, 16779523}, {7479, 16779779}, {7480, 16780035}, {7481, 16780291},
1092
  {7482, 16780547}, {7483, 1}, {7484, 16780803}, {7485, 16835843},
1093
  {7486, 16781059}, {7487, 16781571}, {7488, 16782083}, {7489, 16782339},
1094
  {7490, 16782851}, {7491, 16777219}, {7492, 16958467}, {7493, 16958723},
1095
  {7494, 16958979}, {7495, 16777475}, {7496, 16777987}, {7497, 16778243},
1096
  {7498, 16816387}, {7499, 16816643}, {7500, 16959235}, {7501, 16778755},
1097
  {7502, 1}, {7503, 16779779}, {7504, 16780291}, {7505, 16807171},
1098
  {7506, 16780803}, {7507, 16814851}, {7508, 16959491}, {7509, 16959747},
1099
  {7510, 16781059}, {7511, 16782083}, {7512, 16782339}, {7513, 16960003},
1100
  {7514, 16818435}, {7515, 16782595}, {7516, 16960259}, {7517, 16851971},
1101
  {7518, 16852227}, {7519, 16852483}, {7520, 16856323}, {7521, 16856579},
1102
  {7522, 16779267}, {7523, 16781571}, {7524, 16782339}, {7525, 16782595},
1103
  {7526, 16851971}, {7527, 16852227}, {7528, 16855299}, {7529, 16856323},
1104
  {7530, 16856579}, {7531, 1}, {7544, 16869891}, {7545, 1},
1105
  {7579, 16960515}, {7580, 16777731}, {7581, 16960771}, {7582, 16793603},
1106
  {7583, 16959235}, {7584, 16778499}, {7585, 16961027}, {7586, 16961283},
1107
  {7587, 16961539}, {7588, 16817923}, {7589, 16817667}, {7590, 16961795},
1108
  {7591, 16962051}, {7592, 16962307}, {7593, 16962563}, {7594, 16962819},
1109
  {7595, 16963075}, {7596, 16963331}, {7597, 16963587}, {7598, 16818691},
1110
  {7599, 16963843}, {7600, 16964099}, {7601, 16818947}, {7602, 16964355},
1111
  {7603, 16964611}, {7604, 16820483}, {7605, 16964867}, {7606, 16839683},
1112
  {7607, 16821507}, {7608, 16965123}, {7609, 16821763}, {7610, 16839939},
1113
  {7611, 16783619}, {7612, 16965379}, {7613, 16965635}, {7614, 16822531},
1114
  {7615, 16853507}, {7616, 1}, {7680, 16965891}, {7681, 1},
1115
  {7682, 16966147}, {7683, 1}, {7684, 16966403}, {7685, 1},
1116
  {7686, 16966659}, {7687, 1}, {7688, 16966915}, {7689, 1},
1117
  {7690, 16967171}, {7691, 1}, {7692, 16967427}, {7693, 1},
1118
  {7694, 16967683}, {7695, 1}, {7696, 16967939}, {7697, 1},
1119
  {7698, 16968195}, {7699, 1}, {7700, 16968451}, {7701, 1},
1120
  {7702, 16968707}, {7703, 1}, {7704, 16968963}, {7705, 1},
1121
  {7706, 16969219}, {7707, 1}, {7708, 16969475}, {7709, 1},
1122
  {7710, 16969731}, {7711, 1}, {7712, 16969987}, {7713, 1},
1123
  {7714, 16970243}, {7715, 1}, {7716, 16970499}, {7717, 1},
1124
  {7718, 16970755}, {7719, 1}, {7720, 16971011}, {7721, 1},
1125
  {7722, 16971267}, {7723, 1}, {7724, 16971523}, {7725, 1},
1126
  {7726, 16971779}, {7727, 1}, {7728, 16972035}, {7729, 1},
1127
  {7730, 16972291}, {7731, 1}, {7732, 16972547}, {7733, 1},
1128
  {7734, 16972803}, {7735, 1}, {7736, 16973059}, {7737, 1},
1129
  {7738, 16973315}, {7739, 1}, {7740, 16973571}, {7741, 1},
1130
  {7742, 16973827}, {7743, 1}, {7744, 16974083}, {7745, 1},
1131
  {7746, 16974339}, {7747, 1}, {7748, 16974595}, {7749, 1},
1132
  {7750, 16974851}, {7751, 1}, {7752, 16975107}, {7753, 1},
1133
  {7754, 16975363}, {7755, 1}, {7756, 16975619}, {7757, 1},
1134
  {7758, 16975875}, {7759, 1}, {7760, 16976131}, {7761, 1},
1135
  {7762, 16976387}, {7763, 1}, {7764, 16976643}, {7765, 1},
1136
  {7766, 16976899}, {7767, 1}, {7768, 16977155}, {7769, 1},
1137
  {7770, 16977411}, {7771, 1}, {7772, 16977667}, {7773, 1},
1138
  {7774, 16977923}, {7775, 1}, {7776, 16978179}, {7777, 1},
1139
  {7778, 16978435}, {7779, 1}, {7780, 16978691}, {7781, 1},
1140
  {7782, 16978947}, {7783, 1}, {7784, 16979203}, {7785, 1},
1141
  {7786, 16979459}, {7787, 1}, {7788, 16979715}, {7789, 1},
1142
  {7790, 16979971}, {7791, 1}, {7792, 16980227}, {7793, 1},
1143
  {7794, 16980483}, {7795, 1}, {7796, 16980739}, {7797, 1},
1144
  {7798, 16980995}, {7799, 1}, {7800, 16981251}, {7801, 1},
1145
  {7802, 16981507}, {7803, 1}, {7804, 16981763}, {7805, 1},
1146
  {7806, 16982019}, {7807, 1}, {7808, 16982275}, {7809, 1},
1147
  {7810, 16982531}, {7811, 1}, {7812, 16982787}, {7813, 1},
1148
  {7814, 16983043}, {7815, 1}, {7816, 16983299}, {7817, 1},
1149
  {7818, 16983555}, {7819, 1}, {7820, 16983811}, {7821, 1},
1150
  {7822, 16984067}, {7823, 1}, {7824, 16984323}, {7825, 1},
1151
  {7826, 16984579}, {7827, 1}, {7828, 16984835}, {7829, 1},
1152
  {7834, 33762307}, {7835, 16978179}, {7836, 1}, {7838, 16985603},
1153
  {7839, 1}, {7840, 16985859}, {7841, 1}, {7842, 16986115},
1154
  {7843, 1}, {7844, 16986371}, {7845, 1}, {7846, 16986627},
1155
  {7847, 1}, {7848, 16986883}, {7849, 1}, {7850, 16987139},
1156
  {7851, 1}, {7852, 16987395}, {7853, 1}, {7854, 16987651},
1157
  {7855, 1}, {7856, 16987907}, {7857, 1}, {7858, 16988163},
1158
  {7859, 1}, {7860, 16988419}, {7861, 1}, {7862, 16988675},
1159
  {7863, 1}, {7864, 16988931}, {7865, 1}, {7866, 16989187},
1160
  {7867, 1}, {7868, 16989443}, {7869, 1}, {7870, 16989699},
1161
  {7871, 1}, {7872, 16989955}, {7873, 1}, {7874, 16990211},
1162
  {7875, 1}, {7876, 16990467}, {7877, 1}, {7878, 16990723},
1163
  {7879, 1}, {7880, 16990979}, {7881, 1}, {7882, 16991235},
1164
  {7883, 1}, {7884, 16991491}, {7885, 1}, {7886, 16991747},
1165
  {7887, 1}, {7888, 16992003}, {7889, 1}, {7890, 16992259},
1166
  {7891, 1}, {7892, 16992515}, {7893, 1}, {7894, 16992771},
1167
  {7895, 1}, {7896, 16993027}, {7897, 1}, {7898, 16993283},
1168
  {7899, 1}, {7900, 16993539}, {7901, 1}, {7902, 16993795},
1169
  {7903, 1}, {7904, 16994051}, {7905, 1}, {7906, 16994307},
1170
  {7907, 1}, {7908, 16994563}, {7909, 1}, {7910, 16994819},
1171
  {7911, 1}, {7912, 16995075}, {7913, 1}, {7914, 16995331},
1172
  {7915, 1}, {7916, 16995587}, {7917, 1}, {7918, 16995843},
1173
  {7919, 1}, {7920, 16996099}, {7921, 1}, {7922, 16996355},
1174
  {7923, 1}, {7924, 16996611}, {7925, 1}, {7926, 16996867},
1175
  {7927, 1}, {7928, 16997123}, {7929, 1}, {7930, 16997379},
1176
  {7931, 1}, {7932, 16997635}, {7933, 1}, {7934, 16997891},
1177
  {7935, 1}, {7944, 16998147}, {7945, 16998403}, {7946, 16998659},
1178
  {7947, 16998915}, {7948, 16999171}, {7949, 16999427}, {7950, 16999683},
1179
  {7951, 16999939}, {7952, 1}, {7958, 2}, {7960, 17000195},
1180
  {7961, 17000451}, {7962, 17000707}, {7963, 17000963}, {7964, 17001219},
1181
  {7965, 17001475}, {7966, 2}, {7968, 1}, {7976, 17001731},
1182
  {7977, 17001987}, {7978, 17002243}, {7979, 17002499}, {7980, 17002755},
1183
  {7981, 17003011}, {7982, 17003267}, {7983, 17003523}, {7984, 1},
1184
  {7992, 17003779}, {7993, 17004035}, {7994, 17004291}, {7995, 17004547},
1185
  {7996, 17004803}, {7997, 17005059}, {7998, 17005315}, {7999, 17005571},
1186
  {8000, 1}, {8006, 2}, {8008, 17005827}, {8009, 17006083},
1187
  {8010, 17006339}, {8011, 17006595}, {8012, 17006851}, {8013, 17007107},
1188
  {8014, 2}, {8016, 1}, {8024, 2}, {8025, 17007363},
1189
  {8026, 2}, {8027, 17007619}, {8028, 2}, {8029, 17007875},
1190
  {8030, 2}, {8031, 17008131}, {8032, 1}, {8040, 17008387},
1191
  {8041, 17008643}, {8042, 17008899}, {8043, 17009155}, {8044, 17009411},
1192
  {8045, 17009667}, {8046, 17009923}, {8047, 17010179}, {8048, 1},
1193
  {8049, 16849923}, {8050, 1}, {8051, 16850179}, {8052, 1},
1194
  {8053, 16850435}, {8054, 1}, {8055, 16850691}, {8056, 1},
1195
  {8057, 16850947}, {8058, 1}, {8059, 16851203}, {8060, 1},
1196
  {8061, 16851459}, {8062, 2}, {8064, 33787651}, {8065, 33788163},
1197
  {8066, 33788675}, {8067, 33789187}, {8068, 33789699}, {8069, 33790211},
1198
  {8070, 33790723}, {8071, 33791235}, {8072, 33787651}, {8073, 33788163},
1199
  {8074, 33788675}, {8075, 33789187}, {8076, 33789699}, {8077, 33790211},
1200
  {8078, 33790723}, {8079, 33791235}, {8080, 33791747}, {8081, 33792259},
1201
  {8082, 33792771}, {8083, 33793283}, {8084, 33793795}, {8085, 33794307},
1202
  {8086, 33794819}, {8087, 33795331}, {8088, 33791747}, {8089, 33792259},
1203
  {8090, 33792771}, {8091, 33793283}, {8092, 33793795}, {8093, 33794307},
1204
  {8094, 33794819}, {8095, 33795331}, {8096, 33795843}, {8097, 33796355},
1205
  {8098, 33796867}, {8099, 33797379}, {8100, 33797891}, {8101, 33798403},
1206
  {8102, 33798915}, {8103, 33799427}, {8104, 33795843}, {8105, 33796355},
1207
  {8106, 33796867}, {8107, 33797379}, {8108, 33797891}, {8109, 33798403},
1208
  {8110, 33798915}, {8111, 33799427}, {8112, 1}, {8114, 33799939},
1209
  {8115, 33800451}, {8116, 33800963}, {8117, 2}, {8118, 1},
1210
  {8119, 33801475}, {8120, 17024771}, {8121, 17025027}, {8122, 17022723},
1211
  {8123, 16849923}, {8124, 33800451}, {8125, 33802499}, {8126, 16846851},
1212
  {8127, 33802499}, {8128, 33803011}, {8129, 50580739}, {8130, 33804291},
1213
  {8131, 33804803}, {8132, 33805315}, {8133, 2}, {8134, 1},
1214
  {8135, 33805827}, {8136, 17029123}, {8137, 16850179}, {8138, 17027075},
1215
  {8139, 16850435}, {8140, 33804803}, {8141, 50583811}, {8142, 50584579},
1216
  {8143, 50585347}, {8144, 1}, {8147, 17031683}, {8148, 2},
1217
  {8150, 1}, {8152, 17031939}, {8153, 17032195}, {8154, 17032451},
1218
  {8155, 16850691}, {8156, 2}, {8157, 50587139}, {8158, 50587907},
1219
  {8159, 50588675}, {8160, 1}, {8163, 17035011}, {8164, 1},
1220
  {8168, 17035267}, {8169, 17035523}, {8170, 17035779}, {8171, 16851203},
1221
  {8172, 17036035}, {8173, 50590723}, {8174, 50403587}, {8175, 17037059},
1222
  {8176, 2}, {8178, 33814531}, {8179, 33815043}, {8180, 33815555},
1223
  {8181, 2}, {8182, 1}, {8183, 33816067}, {8184, 17039363},
1224
  {8185, 16850947}, {8186, 17037315}, {8187, 16851459}, {8188, 33815043},
1225
  {8189, 33562883}, {8190, 33809923}, {8191, 2}, {8192, 16783875},
1226
  {8203, 0}, {8204, 1}, {8206, 2}, {8208, 1},
1227
  {8209, 17039619}, {8210, 1}, {8215, 33817091}, {8216, 1},
1228
  {8228, 2}, {8231, 1}, {8232, 2}, {8239, 16783875},
1229
  {8240, 1}, {8243, 33817603}, {8244, 50595331}, {8245, 1},
1230
  {8246, 33818883}, {8247, 50596611}, {8248, 1}, {8252, 33820163},
1231
  {8253, 1}, {8254, 33820675}, {8255, 1}, {8263, 33821187},
1232
  {8264, 33821699}, {8265, 33822211}, {8266, 1}, {8279, 67372035},
1233
  {8280, 1}, {8287, 16783875}, {8288, 0}, {8293, 2},
1234
  {8298, 0}, {8304, 17045507}, {8305, 16779267}, {8306, 2},
1235
  {8308, 16787715}, {8309, 17045763}, {8310, 17046019}, {8311, 17046275},
1236
  {8312, 17046531}, {8313, 17046787}, {8314, 17047043}, {8315, 17047299},
1237
  {8316, 17047555}, {8317, 17047811}, {8318, 17048067}, {8319, 16780547},
1238
  {8320, 17045507}, {8321, 16786947}, {8322, 16785155}, {8323, 16785411},
1239
  {8324, 16787715}, {8325, 17045763}, {8326, 17046019}, {8327, 17046275},
1240
  {8328, 17046531}, {8329, 17046787}, {8330, 17047043}, {8331, 17047299},
1241
  {8332, 17047555}, {8333, 17047811}, {8334, 17048067}, {8335, 2},
1242
  {8336, 16777219}, {8337, 16778243}, {8338, 16780803}, {8339, 16783107},
1243
  {8340, 16816387}, {8341, 16779011}, {8342, 16779779}, {8343, 16780035},
1244
  {8344, 16780291}, {8345, 16780547}, {8346, 16781059}, {8347, 16781827},
1245
  {8348, 16782083}, {8349, 2}, {8352, 1}, {8360, 33558787},
1246
  {8361, 1}, {8386, 2}, {8400, 1}, {8433, 2},
1247
  {8448, 50602755}, {8449, 50603523}, {8450, 16777731}, {8451, 33827075},
1248
  {8452, 1}, {8453, 50604803}, {8454, 50605571}, {8455, 16816643},
1249
  {8456, 1}, {8457, 33829123}, {8458, 16778755}, {8459, 16779011},
1250
  {8463, 16802051}, {8464, 16779267}, {8466, 16780035}, {8468, 1},
1251
  {8469, 16780547}, {8470, 33557763}, {8471, 1}, {8473, 16781059},
1252
  {8474, 16781315}, {8475, 16781571}, {8478, 1}, {8480, 33829635},
1253
  {8481, 50607363}, {8482, 33830915}, {8483, 1}, {8484, 16783619},
1254
  {8485, 1}, {8486, 16857091}, {8487, 1}, {8488, 16783619},
1255
  {8489, 1}, {8490, 16779779}, {8491, 16790787}, {8492, 16777475},
1256
  {8493, 16777731}, {8494, 1}, {8495, 16778243}, {8497, 16778499},
1257
  {8498, 17054211}, {8499, 16780291}, {8500, 16780803}, {8501, 17054467},
1258
  {8502, 17054723}, {8503, 17054979}, {8504, 17055235}, {8505, 16779267},
1259
  {8506, 1}, {8507, 50609923}, {8508, 16855043}, {8509, 16852227},
1260
  {8511, 16855043}, {8512, 17056259}, {8513, 1}, {8517, 16777987},
1261
  {8519, 16778243}, {8520, 16779267}, {8521, 16779523}, {8522, 1},
1262
  {8528, 50610947}, {8529, 50611715}, {8530, 67389699}, {8531, 50613507},
1263
  {8532, 50614275}, {8533, 50615043}, {8534, 50615811}, {8535, 50616579},
1264
  {8536, 50617347}, {8537, 50618115}, {8538, 50618883}, {8539, 50619651},
1265
  {8540, 50620419}, {8541, 50621187}, {8542, 50621955}, {8543, 33564419},
1266
  {8544, 16779267}, {8545, 33845507}, {8546, 50623235}, {8547, 33846787},
1267
  {8548, 16782595}, {8549, 33847299}, {8550, 50625027}, {8551, 67403011},
1268
  {8552, 33849603}, {8553, 16783107}, {8554, 33850115}, {8555, 50627843},
1269
  {8556, 16780035}, {8557, 16777731}, {8558, 16777987}, {8559, 16780291},
1270
  {8560, 16779267}, {8561, 33845507}, {8562, 50622723}, {8563, 33846787},
1271
  {8564, 16782595}, {8565, 33847299}, {8566, 50625027}, {8567, 67403011},
1272
  {8568, 33849603}, {8569, 16783107}, {8570, 33850115}, {8571, 50627843},
1273
  {8572, 16780035}, {8573, 16777731}, {8574, 16777987}, {8575, 16780291},
1274
  {8576, 1}, {8579, 17074179}, {8580, 1}, {8585, 50628867},
1275
  {8586, 1}, {8588, 2}, {8592, 1}, {8748, 33852419},
1276
  {8749, 50630147}, {8750, 1}, {8751, 33853699}, {8752, 50631427},
1277
  {8753, 1}, {9001, 17077763}, {9002, 17078019}, {9003, 1},
1278
  {9258, 2}, {9280, 1}, {9291, 2}, {9312, 16786947},
1279
  {9313, 16785155}, {9314, 16785411}, {9315, 16787715}, {9316, 17045763},
1280
  {9317, 17046019}, {9318, 17046275}, {9319, 17046531}, {9320, 17046787},
1281
  {9321, 33835779}, {9322, 33564163}, {9323, 33855491}, {9324, 33856003},
1282
  {9325, 33856515}, {9326, 33857027}, {9327, 33857539}, {9328, 33858051},
1283
  {9329, 33858563}, {9330, 33859075}, {9331, 33859587}, {9332, 50637315},
1284
  {9333, 50638083}, {9334, 50638851}, {9335, 50639619}, {9336, 50640387},
1285
  {9337, 50641155}, {9338, 50641923}, {9339, 50642691}, {9340, 50643459},
1286
  {9341, 67421443}, {9342, 67422467}, {9343, 67423491}, {9344, 67424515},
1287
  {9345, 67425539}, {9346, 67426563}, {9347, 67427587}, {9348, 67428611},
1288
  {9349, 67429635}, {9350, 67430659}, {9351, 67431683}, {9352, 2},
1289
  {9372, 50655491}, {9373, 50656259}, {9374, 50657027}, {9375, 50657795},
1290
  {9376, 50658563}, {9377, 50659331}, {9378, 50660099}, {9379, 50660867},
1291
  {9380, 50661635}, {9381, 50662403}, {9382, 50663171}, {9383, 50663939},
1292
  {9384, 50664707}, {9385, 50665475}, {9386, 50666243}, {9387, 50667011},
1293
  {9388, 50667779}, {9389, 50668547}, {9390, 50669315}, {9391, 50670083},
1294
  {9392, 50670851}, {9393, 50671619}, {9394, 50672387}, {9395, 50673155},
1295
  {9396, 50673923}, {9397, 50674691}, {9398, 16777219}, {9399, 16777475},
1296
  {9400, 16777731}, {9401, 16777987}, {9402, 16778243}, {9403, 16778499},
1297
  {9404, 16778755}, {9405, 16779011}, {9406, 16779267}, {9407, 16779523},
1298
  {9408, 16779779}, {9409, 16780035}, {9410, 16780291}, {9411, 16780547},
1299
  {9412, 16780803}, {9413, 16781059}, {9414, 16781315}, {9415, 16781571},
1300
  {9416, 16781827}, {9417, 16782083}, {9418, 16782339}, {9419, 16782595},
1301
  {9420, 16782851}, {9421, 16783107}, {9422, 16783363}, {9423, 16783619},
1302
  {9424, 16777219}, {9425, 16777475}, {9426, 16777731}, {9427, 16777987},
1303
  {9428, 16778243}, {9429, 16778499}, {9430, 16778755}, {9431, 16779011},
1304
  {9432, 16779267}, {9433, 16779523}, {9434, 16779779}, {9435, 16780035},
1305
  {9436, 16780291}, {9437, 16780547}, {9438, 16780803}, {9439, 16781059},
1306
  {9440, 16781315}, {9441, 16781571}, {9442, 16781827}, {9443, 16782083},
1307
  {9444, 16782339}, {9445, 16782595}, {9446, 16782851}, {9447, 16783107},
1308
  {9448, 16783363}, {9449, 16783619}, {9450, 17045507}, {9451, 1},
1309
  {10764, 67406851}, {10765, 1}, {10868, 50675459}, {10869, 33899011},
1310
  {10870, 50675971}, {10871, 1}, {10972, 33899523}, {10973, 1},
1311
  {11124, 2}, {11126, 1}, {11264, 17122819}, {11265, 17123075},
1312
  {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099},
1313
  {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123},
1314
  {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147},
1315
  {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171},
1316
  {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195},
1317
  {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219},
1318
  {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243},
1319
  {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267},
1320
  {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291},
1321
  {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315},
1322
  {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339},
1323
  {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107},
1324
  {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875},
1325
  {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387},
1326
  {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723},
1327
  {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1},
1328
  {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1},
1329
  {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667},
1330
  {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1},
1331
  {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1},
1332
  {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1},
1333
  {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1},
1334
  {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1},
1335
  {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1},
1336
  {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1},
1337
  {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1},
1338
  {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1},
1339
  {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1},
1340
  {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1},
1341
  {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1},
1342
  {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1},
1343
  {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1},
1344
  {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1},
1345
  {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1},
1346
  {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1},
1347
  {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1},
1348
  {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1},
1349
  {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1},
1350
  {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1},
1351
  {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1},
1352
  {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1},
1353
  {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1},
1354
  {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1},
1355
  {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1},
1356
  {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1},
1357
  {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1},
1358
  {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491},
1359
  {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2},
1360
  {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2},
1361
  {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2},
1362
  {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2},
1363
  {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2},
1364
  {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2},
1365
  {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003},
1366
  {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771},
1367
  {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795},
1368
  {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819},
1369
  {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843},
1370
  {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867},
1371
  {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891},
1372
  {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915},
1373
  {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939},
1374
  {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963},
1375
  {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987},
1376
  {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011},
1377
  {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035},
1378
  {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059},
1379
  {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083},
1380
  {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107},
1381
  {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131},
1382
  {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155},
1383
  {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179},
1384
  {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203},
1385
  {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227},
1386
  {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251},
1387
  {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275},
1388
  {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299},
1389
  {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323},
1390
  {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347},
1391
  {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371},
1392
  {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395},
1393
  {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419},
1394
  {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443},
1395
  {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467},
1396
  {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491},
1397
  {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515},
1398
  {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539},
1399
  {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563},
1400
  {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587},
1401
  {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611},
1402
  {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635},
1403
  {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659},
1404
  {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683},
1405
  {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707},
1406
  {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731},
1407
  {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755},
1408
  {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779},
1409
  {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803},
1410
  {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827},
1411
  {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851},
1412
  {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875},
1413
  {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899},
1414
  {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923},
1415
  {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947},
1416
  {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971},
1417
  {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995},
1418
  {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019},
1419
  {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2},
1420
  {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1},
1421
  {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555},
1422
  {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1},
1423
  {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795},
1424
  {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819},
1425
  {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115},
1426
  {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139},
1427
  {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163},
1428
  {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187},
1429
  {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211},
1430
  {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235},
1431
  {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259},
1432
  {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283},
1433
  {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307},
1434
  {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331},
1435
  {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355},
1436
  {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379},
1437
  {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403},
1438
  {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171},
1439
  {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195},
1440
  {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219},
1441
  {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243},
1442
  {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267},
1443
  {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291},
1444
  {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315},
1445
  {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339},
1446
  {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363},
1447
  {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387},
1448
  {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411},
1449
  {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259},
1450
  {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435},
1451
  {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283},
1452
  {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227},
1453
  {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1},
1454
  {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219},
1455
  {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291},
1456
  {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363},
1457
  {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435},
1458
  {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507},
1459
  {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579},
1460
  {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651},
1461
  {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2},
1462
  {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539},
1463
  {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611},
1464
  {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683},
1465
  {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755},
1466
  {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827},
1467
  {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899},
1468
  {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971},
1469
  {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043},
1470
  {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115},
1471
  {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963},
1472
  {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203},
1473
  {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739},
1474
  {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787},
1475
  {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811},
1476
  {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651},
1477
  {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235},
1478
  {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771},
1479
  {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491},
1480
  {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563},
1481
  {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635},
1482
  {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707},
1483
  {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643},
1484
  {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923},
1485
  {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667},
1486
  {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947},
1487
  {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755},
1488
  {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883},
1489
  {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955},
1490
  {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155},
1491
  {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923},
1492
  {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691},
1493
  {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947},
1494
  {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971},
1495
  {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099},
1496
  {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211},
1497
  {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931},
1498
  {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771},
1499
  {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819},
1500
  {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867},
1501
  {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915},
1502
  {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435},
1503
  {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035},
1504
  {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611},
1505
  {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635},
1506
  {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403},
1507
  {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427},
1508
  {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451},
1509
  {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219},
1510
  {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243},
1511
  {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267},
1512
  {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291},
1513
  {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315},
1514
  {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339},
1515
  {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363},
1516
  {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827},
1517
  {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195},
1518
  {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035},
1519
  {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619},
1520
  {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651},
1521
  {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923},
1522
  {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803},
1523
  {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211},
1524
  {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307},
1525
  {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907},
1526
  {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915},
1527
  {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187},
1528
  {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259},
1529
  {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611},
1530
  {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507},
1531
  {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835},
1532
  {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651},
1533
  {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979},
1534
  {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995},
1535
  {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379},
1536
  {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491},
1537
  {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955},
1538
  {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611},
1539
  {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659},
1540
  {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923},
1541
  {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995},
1542
  {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067},
1543
  {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139},
1544
  {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995},
1545
  {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299},
1546
  {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859},
1547
  {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907},
1548
  {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955},
1549
  {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003},
1550
  {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819},
1551
  {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867},
1552
  {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387},
1553
  {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219},
1554
  {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755},
1555
  {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803},
1556
  {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067},
1557
  {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371},
1558
  {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931},
1559
  {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435},
1560
  {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627},
1561
  {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675},
1562
  {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211},
1563
  {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259},
1564
  {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2},
1565
  {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739},
1566
  {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355},
1567
  {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803},
1568
  {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131},
1569
  {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179},
1570
  {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011},
1571
  {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763},
1572
  {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107},
1573
  {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155},
1574
  {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675},
1575
  {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747},
1576
  {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819},
1577
  {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891},
1578
  {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963},
1579
  {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035},
1580
  {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1},
1581
  {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139},
1582
  {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651},
1583
  {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163},
1584
  {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419},
1585
  {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931},
1586
  {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443},
1587
  {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955},
1588
  {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467},
1589
  {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979},
1590
  {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491},
1591
  {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003},
1592
  {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515},
1593
  {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027},
1594
  {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539},
1595
  {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051},
1596
  {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563},
1597
  {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075},
1598
  {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587},
1599
  {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099},
1600
  {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1},
1601
  {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1},
1602
  {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1},
1603
  {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1},
1604
  {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1},
1605
  {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1},
1606
  {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1},
1607
  {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1},
1608
  {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1},
1609
  {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1},
1610
  {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1},
1611
  {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1},
1612
  {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1},
1613
  {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1},
1614
  {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1},
1615
  {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1},
1616
  {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1},
1617
  {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1},
1618
  {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1},
1619
  {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1},
1620
  {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1},
1621
  {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1},
1622
  {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107},
1623
  {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619},
1624
  {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131},
1625
  {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387},
1626
  {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899},
1627
  {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411},
1628
  {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923},
1629
  {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435},
1630
  {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947},
1631
  {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475},
1632
  {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795},
1633
  {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307},
1634
  {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739},
1635
  {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251},
1636
  {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763},
1637
  {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275},
1638
  {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787},
1639
  {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1},
1640
  {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 17528067},
1641
  {42959, 1}, {42960, 17528323}, {42961, 1}, {42962, 17528579},
1642
  {42963, 1}, {42964, 17528835}, {42965, 1}, {42966, 17529091},
1643
  {42967, 1}, {42968, 17529347}, {42969, 1}, {42970, 17529603},
1644
  {42971, 1}, {42972, 17529859}, {42973, 2}, {42993, 16781827},
1645
  {42994, 16777731}, {42995, 16778499}, {42996, 16781315}, {42997, 17530115},
1646
  {42998, 1}, {43000, 16802051}, {43001, 16808195}, {43002, 1},
1647
  {43053, 2}, {43056, 1}, {43066, 2}, {43072, 1},
1648
  {43128, 2}, {43136, 1}, {43206, 2}, {43214, 1},
1649
  {43226, 2}, {43232, 1}, {43348, 2}, {43359, 1},
1650
  {43389, 2}, {43392, 1}, {43470, 2}, {43471, 1},
1651
  {43482, 2}, {43486, 1}, {43519, 2}, {43520, 1},
1652
  {43575, 2}, {43584, 1}, {43598, 2}, {43600, 1},
1653
  {43610, 2}, {43612, 1}, {43715, 2}, {43739, 1},
1654
  {43767, 2}, {43777, 1}, {43783, 2}, {43785, 1},
1655
  {43791, 2}, {43793, 1}, {43799, 2}, {43808, 1},
1656
  {43815, 2}, {43816, 1}, {43823, 2}, {43824, 1},
1657
  {43868, 17508867}, {43869, 17530371}, {43870, 17135363}, {43871, 17530627},
1658
  {43872, 1}, {43881, 17530883}, {43882, 1}, {43884, 2},
1659
  {43888, 17531139}, {43889, 17531395}, {43890, 17531651}, {43891, 17531907},
1660
  {43892, 17532163}, {43893, 17532419}, {43894, 17532675}, {43895, 17532931},
1661
  {43896, 17533187}, {43897, 17533443}, {43898, 17533699}, {43899, 17533955},
1662
  {43900, 17534211}, {43901, 17534467}, {43902, 17534723}, {43903, 17534979},
1663
  {43904, 17535235}, {43905, 17535491}, {43906, 17535747}, {43907, 17536003},
1664
  {43908, 17536259}, {43909, 17536515}, {43910, 17536771}, {43911, 17537027},
1665
  {43912, 17537283}, {43913, 17537539}, {43914, 17537795}, {43915, 17538051},
1666
  {43916, 17538307}, {43917, 17538563}, {43918, 17538819}, {43919, 17539075},
1667
  {43920, 17539331}, {43921, 17539587}, {43922, 17539843}, {43923, 17540099},
1668
  {43924, 17540355}, {43925, 17540611}, {43926, 17540867}, {43927, 17541123},
1669
  {43928, 17541379}, {43929, 17541635}, {43930, 17541891}, {43931, 17542147},
1670
  {43932, 17542403}, {43933, 17542659}, {43934, 17542915}, {43935, 17543171},
1671
  {43936, 17543427}, {43937, 17543683}, {43938, 17543939}, {43939, 17544195},
1672
  {43940, 17544451}, {43941, 17544707}, {43942, 17544963}, {43943, 17545219},
1673
  {43944, 17545475}, {43945, 17545731}, {43946, 17545987}, {43947, 17546243},
1674
  {43948, 17546499}, {43949, 17546755}, {43950, 17547011}, {43951, 17547267},
1675
  {43952, 17547523}, {43953, 17547779}, {43954, 17548035}, {43955, 17548291},
1676
  {43956, 17548547}, {43957, 17548803}, {43958, 17549059}, {43959, 17549315},
1677
  {43960, 17549571}, {43961, 17549827}, {43962, 17550083}, {43963, 17550339},
1678
  {43964, 17550595}, {43965, 17550851}, {43966, 17551107}, {43967, 17551363},
1679
  {43968, 1}, {44014, 2}, {44016, 1}, {44026, 2},
1680
  {44032, 1}, {55204, 2}, {55216, 1}, {55239, 2},
1681
  {55243, 1}, {55292, 2}, {63744, 17551619}, {63745, 17551875},
1682
  {63746, 17192707}, {63747, 17552131}, {63748, 17552387}, {63749, 17552643},
1683
  {63750, 17552899}, {63751, 17206531}, {63753, 17553155}, {63754, 17194755},
1684
  {63755, 17553411}, {63756, 17553667}, {63757, 17553923}, {63758, 17554179},
1685
  {63759, 17554435}, {63760, 17554691}, {63761, 17554947}, {63762, 17555203},
1686
  {63763, 17555459}, {63764, 17555715}, {63765, 17555971}, {63766, 17556227},
1687
  {63767, 17556483}, {63768, 17556739}, {63769, 17556995}, {63770, 17557251},
1688
  {63771, 17557507}, {63772, 17557763}, {63773, 17558019}, {63774, 17558275},
1689
  {63775, 17558531}, {63776, 17558787}, {63777, 17559043}, {63778, 17559299},
1690
  {63779, 17559555}, {63780, 17559811}, {63781, 17560067}, {63782, 17560323},
1691
  {63783, 17560579}, {63784, 17560835}, {63785, 17561091}, {63786, 17561347},
1692
  {63787, 17561603}, {63788, 17561859}, {63789, 17562115}, {63790, 17562371},
1693
  {63791, 17562627}, {63792, 17562883}, {63793, 17563139}, {63794, 17563395},
1694
  {63795, 17563651}, {63796, 17184003}, {63797, 17563907}, {63798, 17564163},
1695
  {63799, 17564419}, {63800, 17564675}, {63801, 17564931}, {63802, 17565187},
1696
  {63803, 17565443}, {63804, 17565699}, {63805, 17565955}, {63806, 17566211},
1697
  {63807, 17566467}, {63808, 17202691}, {63809, 17566723}, {63810, 17566979},
1698
  {63811, 17567235}, {63812, 17567491}, {63813, 17567747}, {63814, 17568003},
1699
  {63815, 17568259}, {63816, 17568515}, {63817, 17568771}, {63818, 17569027},
1700
  {63819, 17569283}, {63820, 17569539}, {63821, 17569795}, {63822, 17570051},
1701
  {63823, 17570307}, {63824, 17570563}, {63825, 17570819}, {63826, 17571075},
1702
  {63827, 17571331}, {63828, 17571587}, {63829, 17571843}, {63830, 17572099},
1703
  {63831, 17572355}, {63832, 17572611}, {63833, 17572867}, {63834, 17573123},
1704
  {63835, 17573379}, {63836, 17555715}, {63837, 17573635}, {63838, 17573891},
1705
  {63839, 17574147}, {63840, 17574403}, {63841, 17574659}, {63842, 17574915},
1706
  {63843, 17575171}, {63844, 17575427}, {63845, 17575683}, {63846, 17575939},
1707
  {63847, 17576195}, {63848, 17576451}, {63849, 17576707}, {63850, 17576963},
1708
  {63851, 17577219}, {63852, 17577475}, {63853, 17577731}, {63854, 17577987},
1709
  {63855, 17578243}, {63856, 17578499}, {63857, 17193219}, {63858, 17578755},
1710
  {63859, 17579011}, {63860, 17579267}, {63861, 17579523}, {63862, 17579779},
1711
  {63863, 17580035}, {63864, 17580291}, {63865, 17580547}, {63866, 17580803},
1712
  {63867, 17581059}, {63868, 17581315}, {63869, 17581571}, {63870, 17581827},
1713
  {63871, 17582083}, {63872, 17582339}, {63873, 17161731}, {63874, 17582595},
1714
  {63875, 17582851}, {63876, 17583107}, {63877, 17583363}, {63878, 17583619},
1715
  {63879, 17583875}, {63880, 17584131}, {63881, 17584387}, {63882, 17156867},
1716
  {63883, 17584643}, {63884, 17584899}, {63885, 17585155}, {63886, 17585411},
1717
  {63887, 17585667}, {63888, 17585923}, {63889, 17586179}, {63890, 17586435},
1718
  {63891, 17586691}, {63892, 17586947}, {63893, 17587203}, {63894, 17587459},
1719
  {63895, 17587715}, {63896, 17587971}, {63897, 17588227}, {63898, 17588483},
1720
  {63899, 17588739}, {63900, 17588995}, {63901, 17589251}, {63902, 17589507},
1721
  {63903, 17589763}, {63904, 17590019}, {63905, 17578243}, {63906, 17590275},
1722
  {63907, 17590531}, {63908, 17590787}, {63909, 17591043}, {63910, 17591299},
1723
  {63911, 17591555}, {63912, 17327619}, {63913, 17591811}, {63914, 17574147},
1724
  {63915, 17592067}, {63916, 17592323}, {63917, 17592579}, {63918, 17592835},
1725
  {63919, 17593091}, {63920, 17593347}, {63921, 17593603}, {63922, 17593859},
1726
  {63923, 17594115}, {63924, 17594371}, {63925, 17594627}, {63926, 17594883},
1727
  {63927, 17595139}, {63928, 17595395}, {63929, 17595651}, {63930, 17595907},
1728
  {63931, 17596163}, {63932, 17596419}, {63933, 17596675}, {63934, 17596931},
1729
  {63935, 17555715}, {63936, 17597187}, {63937, 17597443}, {63938, 17597699},
1730
  {63939, 17597955}, {63940, 17206275}, {63941, 17598211}, {63942, 17598467},
1731
  {63943, 17598723}, {63944, 17598979}, {63945, 17599235}, {63946, 17599491},
1732
  {63947, 17599747}, {63948, 17600003}, {63949, 17600259}, {63950, 17600515},
1733
  {63951, 17600771}, {63952, 17601027}, {63953, 17264899}, {63954, 17601283},
1734
  {63955, 17601539}, {63956, 17601795}, {63957, 17602051}, {63958, 17602307},
1735
  {63959, 17602563}, {63960, 17602819}, {63961, 17603075}, {63962, 17603331},
1736
  {63963, 17574659}, {63964, 17603587}, {63965, 17603843}, {63966, 17604099},
1737
  {63967, 17604355}, {63968, 17604611}, {63969, 17604867}, {63970, 17605123},
1738
  {63971, 17605379}, {63972, 17605635}, {63973, 17605891}, {63974, 17606147},
1739
  {63975, 17606403}, {63976, 17606659}, {63977, 17194499}, {63978, 17606915},
1740
  {63979, 17607171}, {63980, 17607427}, {63981, 17607683}, {63982, 17607939},
1741
  {63983, 17608195}, {63984, 17608451}, {63985, 17608707}, {63986, 17608963},
1742
  {63987, 17609219}, {63988, 17609475}, {63989, 17609731}, {63990, 17609987},
1743
  {63991, 17181955}, {63992, 17610243}, {63993, 17610499}, {63994, 17610755},
1744
  {63995, 17611011}, {63996, 17611267}, {63997, 17611523}, {63998, 17611779},
1745
  {63999, 17612035}, {64000, 17612291}, {64001, 17612547}, {64002, 17612803},
1746
  {64003, 17613059}, {64004, 17613315}, {64005, 17613571}, {64006, 17613827},
1747
  {64007, 17614083}, {64008, 17188867}, {64009, 17614339}, {64010, 17189635},
1748
  {64011, 17614595}, {64012, 17614851}, {64013, 17615107}, {64014, 1},
1749
  {64016, 17615363}, {64017, 1}, {64018, 17615619}, {64019, 1},
1750
  {64021, 17615875}, {64022, 17616131}, {64023, 17616387}, {64024, 17616643},
1751
  {64025, 17616899}, {64026, 17617155}, {64027, 17617411}, {64028, 17617667},
1752
  {64029, 17617923}, {64030, 17183747}, {64031, 1}, {64032, 17618179},
1753
  {64033, 1}, {64034, 17618435}, {64035, 1}, {64037, 17618691},
1754
  {64038, 17618947}, {64039, 1}, {64042, 17619203}, {64043, 17619459},
1755
  {64044, 17619715}, {64045, 17619971}, {64046, 17620227}, {64047, 17620483},
1756
  {64048, 17620739}, {64049, 17620995}, {64050, 17621251}, {64051, 17621507},
1757
  {64052, 17621763}, {64053, 17622019}, {64054, 17622275}, {64055, 17622531},
1758
  {64056, 17622787}, {64057, 17623043}, {64058, 17623299}, {64059, 17623555},
1759
  {64060, 17163523}, {64061, 17623811}, {64062, 17624067}, {64063, 17624323},
1760
  {64064, 17624579}, {64065, 17624835}, {64066, 17625091}, {64067, 17625347},
1761
  {64068, 17625603}, {64069, 17625859}, {64070, 17626115}, {64071, 17626371},
1762
  {64072, 17626627}, {64073, 17626883}, {64074, 17627139}, {64075, 17627395},
1763
  {64076, 17275651}, {64077, 17627651}, {64078, 17627907}, {64079, 17628163},
1764
  {64080, 17628419}, {64081, 17278723}, {64082, 17628675}, {64083, 17628931},
1765
  {64084, 17629187}, {64085, 17629443}, {64086, 17629699}, {64087, 17587459},
1766
  {64088, 17629955}, {64089, 17630211}, {64090, 17630467}, {64091, 17630723},
1767
  {64092, 17630979}, {64093, 17631235}, {64095, 17631491}, {64096, 17631747},
1768
  {64097, 17632003}, {64098, 17632259}, {64099, 17632515}, {64100, 17632771},
1769
  {64101, 17633027}, {64102, 17633283}, {64103, 17618691}, {64104, 17633539},
1770
  {64105, 17633795}, {64106, 17634051}, {64107, 17634307}, {64108, 17634563},
1771
  {64109, 17634819}, {64110, 2}, {64112, 17635075}, {64113, 17635331},
1772
  {64114, 17635587}, {64115, 17635843}, {64116, 17636099}, {64117, 17636355},
1773
  {64118, 17636611}, {64119, 17636867}, {64120, 17622275}, {64121, 17637123},
1774
  {64122, 17637379}, {64123, 17637635}, {64124, 17615363}, {64125, 17637891},
1775
  {64126, 17638147}, {64127, 17638403}, {64128, 17638659}, {64129, 17638915},
1776
  {64130, 17639171}, {64131, 17639427}, {64132, 17639683}, {64133, 17639939},
1777
  {64134, 17640195}, {64135, 17640451}, {64136, 17640707}, {64137, 17624323},
1778
  {64138, 17640963}, {64139, 17624579}, {64140, 17641219}, {64141, 17641475},
1779
  {64142, 17641731}, {64143, 17641987}, {64144, 17642243}, {64145, 17615619},
1780
  {64146, 17561091}, {64147, 17642499}, {64148, 17642755}, {64149, 17171971},
1781
  {64150, 17578499}, {64151, 17599491}, {64152, 17643011}, {64153, 17643267},
1782
  {64154, 17626371}, {64155, 17643523}, {64156, 17626627}, {64157, 17643779},
1783
  {64158, 17644035}, {64159, 17644291}, {64160, 17616131}, {64161, 17644547},
1784
  {64162, 17644803}, {64163, 17645059}, {64164, 17645315}, {64165, 17645571},
1785
  {64166, 17616387}, {64167, 17645827}, {64168, 17646083}, {64169, 17646339},
1786
  {64170, 17646595}, {64171, 17646851}, {64172, 17647107}, {64173, 17629699},
1787
  {64174, 17647363}, {64175, 17647619}, {64176, 17587459}, {64177, 17647875},
1788
  {64178, 17630723}, {64179, 17648131}, {64180, 17648387}, {64181, 17648643},
1789
  {64182, 17648899}, {64183, 17649155}, {64184, 17632003}, {64185, 17649411},
1790
  {64186, 17618435}, {64187, 17649667}, {64188, 17632259}, {64189, 17573635},
1791
  {64190, 17649923}, {64191, 17632515}, {64192, 17650179}, {64193, 17633027},
1792
  {64194, 17650435}, {64195, 17650691}, {64196, 17650947}, {64197, 17651203},
1793
  {64198, 17651459}, {64199, 17633539}, {64200, 17617667}, {64201, 17651715},
1794
  {64202, 17633795}, {64203, 17651971}, {64204, 17634051}, {64205, 17652227},
1795
  {64206, 17206531}, {64207, 17652483}, {64208, 17652739}, {64209, 17652995},
1796
  {64210, 17653251}, {64211, 17653507}, {64212, 17653763}, {64213, 17654019},
1797
  {64214, 17654275}, {64215, 17654531}, {64216, 17654787}, {64217, 17655043},
1798
  {64218, 2}, {64256, 34432515}, {64257, 34433027}, {64258, 34433539},
1799
  {64259, 51209987}, {64260, 51211267}, {64261, 33559043}, {64263, 2},
1800
  {64275, 34434819}, {64276, 34435331}, {64277, 34435843}, {64278, 34436355},
1801
  {64279, 34436867}, {64280, 2}, {64285, 34437379}, {64286, 1},
1802
  {64287, 34437891}, {64288, 17661187}, {64289, 17054467}, {64290, 17055235},
1803
  {64291, 17661443}, {64292, 17661699}, {64293, 17661955}, {64294, 17662211},
1804
  {64295, 17662467}, {64296, 17662723}, {64297, 17047043}, {64298, 34440195},
1805
  {64299, 34440707}, {64300, 51218435}, {64301, 51219203}, {64302, 34442755},
1806
  {64303, 34443267}, {64304, 34443779}, {64305, 34444291}, {64306, 34444803},
1807
  {64307, 34445315}, {64308, 34445827}, {64309, 34446339}, {64310, 34446851},
1808
  {64311, 2}, {64312, 34447363}, {64313, 34447875}, {64314, 34448387},
1809
  {64315, 34448899}, {64316, 34449411}, {64317, 2}, {64318, 34449923},
1810
  {64319, 2}, {64320, 34450435}, {64321, 34450947}, {64322, 2},
1811
  {64323, 34451459}, {64324, 34451971}, {64325, 2}, {64326, 34452483},
1812
  {64327, 34452995}, {64328, 34453507}, {64329, 34441219}, {64330, 34454019},
1813
  {64331, 34454531}, {64332, 34455043}, {64333, 34455555}, {64334, 34456067},
1814
  {64335, 34456579}, {64336, 17679875}, {64338, 17680131}, {64342, 17680387},
1815
  {64346, 17680643}, {64350, 17680899}, {64354, 17681155}, {64358, 17681411},
1816
  {64362, 17681667}, {64366, 17681923}, {64370, 17682179}, {64374, 17682435},
1817
  {64378, 17682691}, {64382, 17682947}, {64386, 17683203}, {64388, 17683459},
1818
  {64390, 17683715}, {64392, 17683971}, {64394, 17684227}, {64396, 17684483},
1819
  {64398, 17684739}, {64402, 17684995}, {64406, 17685251}, {64410, 17685507},
1820
  {64414, 17685763}, {64416, 17686019}, {64420, 17686275}, {64422, 17686531},
1821
  {64426, 17686787}, {64430, 17687043}, {64432, 17687299}, {64434, 1},
1822
  {64467, 17687555}, {64471, 16911619}, {64473, 17687811}, {64475, 17688067},
1823
  {64477, 33688835}, {64478, 17688323}, {64480, 17688579}, {64482, 17688835},
1824
  {64484, 17689091}, {64488, 17689347}, {64490, 34466819}, {64492, 34467331},
1825
  {64494, 34467843}, {64496, 34468355}, {64498, 34468867}, {64500, 34469379},
1826
  {64502, 34469891}, {64505, 34470403}, {64508, 17693699}, {64512, 34471171},
1827
  {64513, 34471683}, {64514, 34472195}, {64515, 34470403}, {64516, 34472707},
1828
  {64517, 34473219}, {64518, 34473731}, {64519, 34474243}, {64520, 34474755},
1829
  {64521, 34475267}, {64522, 34475779}, {64523, 34476291}, {64524, 34476803},
1830
  {64525, 34477315}, {64526, 34477827}, {64527, 34478339}, {64528, 34478851},
1831
  {64529, 34479363}, {64530, 34479875}, {64531, 34480387}, {64532, 34480899},
1832
  {64533, 34481411}, {64534, 34481923}, {64535, 34481667}, {64536, 34482435},
1833
  {64537, 34482947}, {64538, 34483459}, {64539, 34483971}, {64540, 34484483},
1834
  {64541, 34484995}, {64542, 34485507}, {64543, 34486019}, {64544, 34486531},
1835
  {64545, 34487043}, {64546, 34487555}, {64547, 34488067}, {64548, 34488579},
1836
  {64549, 34489091}, {64550, 34489603}, {64551, 34490115}, {64552, 34490627},
1837
  {64553, 34491139}, {64554, 34491651}, {64555, 34492163}, {64556, 34492675},
1838
  {64557, 34493187}, {64558, 34493699}, {64559, 34494211}, {64560, 34494723},
1839
  {64561, 34495235}, {64562, 34495747}, {64563, 34496259}, {64564, 34496771},
1840
  {64565, 34497283}, {64566, 34497795}, {64567, 34498307}, {64568, 34498819},
1841
  {64569, 34499331}, {64570, 34499843}, {64571, 34500355}, {64572, 34500867},
1842
  {64573, 34501379}, {64574, 34501891}, {64575, 34502403}, {64576, 34502915},
1843
  {64577, 34503427}, {64578, 34503939}, {64579, 34504451}, {64580, 34504963},
1844
  {64581, 34505475}, {64582, 34482179}, {64583, 34482691}, {64584, 34505987},
1845
  {64585, 34506499}, {64586, 34507011}, {64587, 34507523}, {64588, 34508035},
1846
  {64589, 34508547}, {64590, 34509059}, {64591, 34509571}, {64592, 34510083},
1847
  {64593, 34510595}, {64594, 34511107}, {64595, 34511619}, {64596, 34512131},
1848
  {64597, 34481155}, {64598, 34512643}, {64599, 34513155}, {64600, 34505219},
1849
  {64601, 34513667}, {64602, 34512387}, {64603, 34514179}, {64604, 34514691},
1850
  {64605, 34515203}, {64606, 51292931}, {64607, 51293699}, {64608, 51294467},
1851
  {64609, 51295235}, {64610, 51296003}, {64611, 51296771}, {64612, 34520323},
1852
  {64613, 34520835}, {64614, 34472195}, {64615, 34521347}, {64616, 34470403},
1853
  {64617, 34472707}, {64618, 34521859}, {64619, 34522371}, {64620, 34474755},
1854
  {64621, 34522883}, {64622, 34475267}, {64623, 34475779}, {64624, 34523395},
1855
  {64625, 34523907}, {64626, 34477827}, {64627, 34524419}, {64628, 34478339},
1856
  {64629, 34478851}, {64630, 34524931}, {64631, 34525443}, {64632, 34479875},
1857
  {64633, 34525955}, {64634, 34480387}, {64635, 34480899}, {64636, 34495235},
1858
  {64637, 34495747}, {64638, 34497283}, {64639, 34497795}, {64640, 34498307},
1859
  {64641, 34500355}, {64642, 34500867}, {64643, 34501379}, {64644, 34501891},
1860
  {64645, 34503939}, {64646, 34504451}, {64647, 34504963}, {64648, 34526467},
1861
  {64649, 34505987}, {64650, 34526979}, {64651, 34527491}, {64652, 34509059},
1862
  {64653, 34528003}, {64654, 34509571}, {64655, 34510083}, {64656, 34515203},
1863
  {64657, 34528515}, {64658, 34529027}, {64659, 34505219}, {64660, 34507267},
1864
  {64661, 34513667}, {64662, 34512387}, {64663, 34471171}, {64664, 34471683},
1865
  {64665, 34529539}, {64666, 34472195}, {64667, 34530051}, {64668, 34473219},
1866
  {64669, 34473731}, {64670, 34474243}, {64671, 34474755}, {64672, 34530563},
1867
  {64673, 34476291}, {64674, 34476803}, {64675, 34477315}, {64676, 34477827},
1868
  {64677, 34531075}, {64678, 34479875}, {64679, 34481411}, {64680, 34481923},
1869
  {64681, 34481667}, {64682, 34482435}, {64683, 34482947}, {64684, 34483971},
1870
  {64685, 34484483}, {64686, 34484995}, {64687, 34485507}, {64688, 34486019},
1871
  {64689, 34486531}, {64690, 34531587}, {64691, 34487043}, {64692, 34487555},
1872
  {64693, 34488067}, {64694, 34488579}, {64695, 34489091}, {64696, 34489603},
1873
  {64697, 34490627}, {64698, 34491139}, {64699, 34491651}, {64700, 34492163},
1874
  {64701, 34492675}, {64702, 34493187}, {64703, 34493699}, {64704, 34494211},
1875
  {64705, 34494723}, {64706, 34496259}, {64707, 34496771}, {64708, 34498819},
1876
  {64709, 34499331}, {64710, 34499843}, {64711, 34500355}, {64712, 34500867},
1877
  {64713, 34502403}, {64714, 34502915}, {64715, 34503427}, {64716, 34503939},
1878
  {64717, 34532099}, {64718, 34505475}, {64719, 34482179}, {64720, 34482691},
1879
  {64721, 34505987}, {64722, 34507523}, {64723, 34508035}, {64724, 34508547},
1880
  {64725, 34509059}, {64726, 34532611}, {64727, 34510595}, {64728, 34511107},
1881
  {64729, 34533123}, {64730, 34481155}, {64731, 34512643}, {64732, 34513155},
1882
  {64733, 34505219}, {64734, 34510339}, {64735, 34472195}, {64736, 34530051},
1883
  {64737, 34474755}, {64738, 34530563}, {64739, 34477827}, {64740, 34531075},
1884
  {64741, 34479875}, {64742, 34533635}, {64743, 34486019}, {64744, 34534147},
1885
  {64745, 34534659}, {64746, 34535171}, {64747, 34500355}, {64748, 34500867},
1886
  {64749, 34503939}, {64750, 34509059}, {64751, 34532611}, {64752, 34505219},
1887
  {64753, 34510339}, {64754, 51312899}, {64755, 51313667}, {64756, 51314435},
1888
  {64757, 34537987}, {64758, 34538499}, {64759, 34539011}, {64760, 34539523},
1889
  {64761, 34540035}, {64762, 34540547}, {64763, 34541059}, {64764, 34541571},
1890
  {64765, 34542083}, {64766, 34542595}, {64767, 34543107}, {64768, 34512899},
1891
  {64769, 34543619}, {64770, 34544131}, {64771, 34544643}, {64772, 34513411},
1892
  {64773, 34545155}, {64774, 34545667}, {64775, 34546179}, {64776, 34546691},
1893
  {64777, 34547203}, {64778, 34547715}, {64779, 34548227}, {64780, 34534659},
1894
  {64781, 34548739}, {64782, 34549251}, {64783, 34549763}, {64784, 34550275},
1895
  {64785, 34537987}, {64786, 34538499}, {64787, 34539011}, {64788, 34539523},
1896
  {64789, 34540035}, {64790, 34540547}, {64791, 34541059}, {64792, 34541571},
1897
  {64793, 34542083}, {64794, 34542595}, {64795, 34543107}, {64796, 34512899},
1898
  {64797, 34543619}, {64798, 34544131}, {64799, 34544643}, {64800, 34513411},
1899
  {64801, 34545155}, {64802, 34545667}, {64803, 34546179}, {64804, 34546691},
1900
  {64805, 34547203}, {64806, 34547715}, {64807, 34548227}, {64808, 34534659},
1901
  {64809, 34548739}, {64810, 34549251}, {64811, 34549763}, {64812, 34550275},
1902
  {64813, 34547203}, {64814, 34547715}, {64815, 34548227}, {64816, 34534659},
1903
  {64817, 34534147}, {64818, 34535171}, {64819, 34490115}, {64820, 34484483},
1904
  {64821, 34484995}, {64822, 34485507}, {64823, 34547203}, {64824, 34547715},
1905
  {64825, 34548227}, {64826, 34490115}, {64827, 34490627}, {64828, 34550787},
1906
  {64830, 1}, {64848, 51328515}, {64849, 51329283}, {64851, 51330051},
1907
  {64852, 51330819}, {64853, 51331587}, {64854, 51332355}, {64855, 51333123},
1908
  {64856, 51259139}, {64858, 51333891}, {64859, 51334659}, {64860, 51335427},
1909
  {64861, 51336195}, {64862, 51336963}, {64863, 51337731}, {64865, 51338499},
1910
  {64866, 51339267}, {64868, 51340035}, {64870, 51340803}, {64871, 51341571},
1911
  {64873, 51342339}, {64874, 51343107}, {64876, 51343875}, {64878, 51344643},
1912
  {64879, 51345411}, {64881, 51346179}, {64883, 51346947}, {64884, 51347715},
1913
  {64885, 51348483}, {64886, 51349251}, {64888, 51350019}, {64889, 51350787},
1914
  {64890, 51351555}, {64891, 51352323}, {64892, 51353091}, {64894, 51353859},
1915
  {64895, 51354627}, {64896, 51355395}, {64897, 51356163}, {64898, 51356931},
1916
  {64899, 51357699}, {64901, 51358467}, {64903, 51359235}, {64905, 51360003},
1917
  {64906, 51259395}, {64907, 51360771}, {64908, 51361539}, {64909, 51282691},
1918
  {64910, 51259907}, {64911, 51362307}, {64912, 1}, {64914, 51363075},
1919
  {64915, 51363843}, {64916, 51364611}, {64917, 51365379}, {64918, 51366147},
1920
  {64919, 51366915}, {64921, 51367683}, {64922, 51368451}, {64923, 51369219},
1921
  {64924, 51369987}, {64926, 51370755}, {64927, 51371523}, {64928, 51372291},
1922
  {64929, 51373059}, {64930, 51373827}, {64931, 51374595}, {64932, 51375363},
1923
  {64933, 51376131}, {64934, 51376899}, {64935, 51377667}, {64936, 51378435},
1924
  {64937, 51379203}, {64938, 51379971}, {64939, 51380739}, {64940, 51381507},
1925
  {64941, 51382275}, {64942, 51289859}, {64943, 51383043}, {64944, 51383811},
1926
  {64945, 51384579}, {64946, 51385347}, {64947, 51386115}, {64948, 51353859},
1927
  {64949, 51355395}, {64950, 51386883}, {64951, 51387651}, {64952, 51388419},
1928
  {64953, 51389187}, {64954, 51389955}, {64955, 51390723}, {64956, 51389955},
1929
  {64957, 51388419}, {64958, 51391491}, {64959, 51392259}, {64960, 51393027},
1930
  {64961, 51393795}, {64962, 51394563}, {64963, 51390723}, {64964, 51348483},
1931
  {64965, 51340803}, {64966, 51395331}, {64967, 51396099}, {64968, 1},
1932
  {64976, 2}, {65008, 51396867}, {65009, 51397635}, {65010, 68175619},
1933
  {65011, 68176643}, {65012, 68177667}, {65013, 68178691}, {65014, 68179715},
1934
  {65015, 68180739}, {65016, 68181763}, {65017, 51405571}, {65018, 303064579},
1935
  {65019, 135297027}, {65020, 68190211}, {65021, 1}, {65024, 0},
1936
  {65040, 17859587}, {65041, 17859843}, {65042, 2}, {65043, 17121027},
1937
  {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17860099},
1938
  {65048, 17860355}, {65049, 2}, {65056, 1}, {65072, 2},
1939
  {65073, 17860611}, {65074, 17860867}, {65075, 17861123}, {65077, 17047811},
1940
  {65078, 17048067}, {65079, 17861379}, {65080, 17861635}, {65081, 17861891},
1941
  {65082, 17862147}, {65083, 17862403}, {65084, 17862659}, {65085, 17862915},
1942
  {65086, 17863171}, {65087, 17077763}, {65088, 17078019}, {65089, 17863427},
1943
  {65090, 17863683}, {65091, 17863939}, {65092, 17864195}, {65093, 1},
1944
  {65095, 17864451}, {65096, 17864707}, {65097, 33820675}, {65101, 17861123},
1945
  {65104, 17859587}, {65105, 17859843}, {65106, 2}, {65108, 16848643},
1946
  {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17860611},
1947
  {65113, 17047811}, {65114, 17048067}, {65115, 17861379}, {65116, 17861635},
1948
  {65117, 17861891}, {65118, 17862147}, {65119, 17864963}, {65120, 17865219},
1949
  {65121, 17865475}, {65122, 17047043}, {65123, 17865731}, {65124, 17865987},
1950
  {65125, 17866243}, {65126, 17047555}, {65127, 2}, {65128, 17866499},
1951
  {65129, 17866755}, {65130, 17867011}, {65131, 17867267}, {65132, 2},
1952
  {65136, 34644739}, {65137, 34645251}, {65138, 34515715}, {65139, 1},
1953
  {65140, 34516483}, {65141, 2}, {65142, 34517251}, {65143, 34535683},
1954
  {65144, 34518019}, {65145, 34536451}, {65146, 34518787}, {65147, 34537219},
1955
  {65148, 34519555}, {65149, 34645763}, {65150, 34646275}, {65151, 34646787},
1956
  {65152, 17870083}, {65153, 17870339}, {65155, 17870595}, {65157, 17870851},
1957
  {65159, 17871107}, {65161, 17689603}, {65165, 16910595}, {65167, 17696003},
1958
  {65171, 17871363}, {65173, 17699075}, {65177, 17702147}, {65181, 17694211},
1959
  {65185, 17694723}, {65189, 17697283}, {65193, 17846787}, {65195, 17736963},
1960
  {65197, 17737475}, {65199, 17743875}, {65201, 17707267}, {65205, 17757443},
1961
  {65209, 17709315}, {65213, 17710339}, {65217, 17712387}, {65221, 17713411},
1962
  {65225, 17713923}, {65229, 17714947}, {65233, 17715971}, {65237, 17719043},
1963
  {65241, 17721091}, {65245, 17723395}, {65249, 17695235}, {65253, 17730307},
1964
  {65257, 17733379}, {65261, 16911107}, {65263, 17689347}, {65265, 16912131},
1965
  {65269, 34648835}, {65271, 34649347}, {65273, 34649859}, {65275, 34634755},
1966
  {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947},
1967
  {65282, 17873155}, {65283, 17864963}, {65284, 17866755}, {65285, 17867011},
1968
  {65286, 17865219}, {65287, 17873411}, {65288, 17047811}, {65289, 17048067},
1969
  {65290, 17865475}, {65291, 17047043}, {65292, 17859587}, {65293, 17865731},
1970
  {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947},
1971
  {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763},
1972
  {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787},
1973
  {65306, 17121027}, {65307, 16848643}, {65308, 17865987}, {65309, 17047555},
1974
  {65310, 17866243}, {65311, 17043971}, {65312, 17867267}, {65313, 16777219},
1975
  {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243},
1976
  {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267},
1977
  {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291},
1978
  {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315},
1979
  {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339},
1980
  {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363},
1981
  {65338, 16783619}, {65339, 17864451}, {65340, 17866499}, {65341, 17864707},
1982
  {65342, 17873667}, {65343, 17861123}, {65344, 17037059}, {65345, 16777219},
1983
  {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243},
1984
  {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267},
1985
  {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291},
1986
  {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315},
1987
  {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339},
1988
  {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363},
1989
  {65370, 16783619}, {65371, 17861379}, {65372, 17873923}, {65373, 17861635},
1990
  {65374, 17874179}, {65375, 17874435}, {65376, 17874691}, {65377, 17207043},
1991
  {65378, 17863427}, {65379, 17863683}, {65380, 17859843}, {65381, 17874947},
1992
  {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17875203},
1993
  {65386, 17374467}, {65387, 17334019}, {65388, 17875459}, {65389, 17344259},
1994
  {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099},
1995
  {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123},
1996
  {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147},
1997
  {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915},
1998
  {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939},
1999
  {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707},
2000
  {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731},
2001
  {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755},
2002
  {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779},
2003
  {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803},
2004
  {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827},
2005
  {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435},
2006
  {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115},
2007
  {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139},
2008
  {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163},
2009
  {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187},
2010
  {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211},
2011
  {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235},
2012
  {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259},
2013
  {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283},
2014
  {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051},
2015
  {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075},
2016
  {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843},
2017
  {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2},
2018
  {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635},
2019
  {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403},
2020
  {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17875715},
2021
  {65505, 17875971}, {65506, 17876227}, {65507, 33561859}, {65508, 17876483},
2022
  {65509, 17876739}, {65510, 17876995}, {65511, 2}, {65512, 17877251},
2023
  {65513, 17877507}, {65514, 17877763}, {65515, 17878019}, {65516, 17878275},
2024
  {65517, 17878531}, {65518, 17878787}, {65519, 2}, {65536, 1},
2025
  {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1},
2026
  {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1},
2027
  {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1},
2028
  {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1},
2029
  {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1},
2030
  {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1},
2031
  {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1},
2032
  {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1},
2033
  {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1},
2034
  {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1},
2035
  {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17879043},
2036
  {66561, 17879299}, {66562, 17879555}, {66563, 17879811}, {66564, 17880067},
2037
  {66565, 17880323}, {66566, 17880579}, {66567, 17880835}, {66568, 17881091},
2038
  {66569, 17881347}, {66570, 17881603}, {66571, 17881859}, {66572, 17882115},
2039
  {66573, 17882371}, {66574, 17882627}, {66575, 17882883}, {66576, 17883139},
2040
  {66577, 17883395}, {66578, 17883651}, {66579, 17883907}, {66580, 17884163},
2041
  {66581, 17884419}, {66582, 17884675}, {66583, 17884931}, {66584, 17885187},
2042
  {66585, 17885443}, {66586, 17885699}, {66587, 17885955}, {66588, 17886211},
2043
  {66589, 17886467}, {66590, 17886723}, {66591, 17886979}, {66592, 17887235},
2044
  {66593, 17887491}, {66594, 17887747}, {66595, 17888003}, {66596, 17888259},
2045
  {66597, 17888515}, {66598, 17888771}, {66599, 17889027}, {66600, 1},
2046
  {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17889283},
2047
  {66737, 17889539}, {66738, 17889795}, {66739, 17890051}, {66740, 17890307},
2048
  {66741, 17890563}, {66742, 17890819}, {66743, 17891075}, {66744, 17891331},
2049
  {66745, 17891587}, {66746, 17891843}, {66747, 17892099}, {66748, 17892355},
2050
  {66749, 17892611}, {66750, 17892867}, {66751, 17893123}, {66752, 17893379},
2051
  {66753, 17893635}, {66754, 17893891}, {66755, 17894147}, {66756, 17894403},
2052
  {66757, 17894659}, {66758, 17894915}, {66759, 17895171}, {66760, 17895427},
2053
  {66761, 17895683}, {66762, 17895939}, {66763, 17896195}, {66764, 17896451},
2054
  {66765, 17896707}, {66766, 17896963}, {66767, 17897219}, {66768, 17897475},
2055
  {66769, 17897731}, {66770, 17897987}, {66771, 17898243}, {66772, 2},
2056
  {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2},
2057
  {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17898499},
2058
  {66929, 17898755}, {66930, 17899011}, {66931, 17899267}, {66932, 17899523},
2059
  {66933, 17899779}, {66934, 17900035}, {66935, 17900291}, {66936, 17900547},
2060
  {66937, 17900803}, {66938, 17901059}, {66939, 2}, {66940, 17901315},
2061
  {66941, 17901571}, {66942, 17901827}, {66943, 17902083}, {66944, 17902339},
2062
  {66945, 17902595}, {66946, 17902851}, {66947, 17903107}, {66948, 17903363},
2063
  {66949, 17903619}, {66950, 17903875}, {66951, 17904131}, {66952, 17904387},
2064
  {66953, 17904643}, {66954, 17904899}, {66955, 2}, {66956, 17905155},
2065
  {66957, 17905411}, {66958, 17905667}, {66959, 17905923}, {66960, 17906179},
2066
  {66961, 17906435}, {66962, 17906691}, {66963, 2}, {66964, 17906947},
2067
  {66965, 17907203}, {66966, 2}, {66967, 1}, {66978, 2},
2068
  {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2},
2069
  {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2},
2070
  {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2},
2071
  {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17907459},
2072
  {67458, 17907715}, {67459, 16791043}, {67460, 17907971}, {67461, 16814083},
2073
  {67462, 2}, {67463, 17908227}, {67464, 17908483}, {67465, 17908739},
2074
  {67466, 17908995}, {67467, 16815363}, {67468, 16815619}, {67469, 17909251},
2075
  {67470, 17909507}, {67471, 17909763}, {67472, 17910019}, {67473, 17527555},
2076
  {67474, 17910275}, {67475, 16817155}, {67476, 17910531}, {67477, 16802051},
2077
  {67478, 17910787}, {67479, 17911043}, {67480, 17911299}, {67481, 17911555},
2078
  {67482, 17911811}, {67483, 17523459}, {67484, 17912067}, {67485, 17912323},
2079
  {67486, 17912579}, {67487, 17912835}, {67488, 17913091}, {67489, 17913347},
2080
  {67490, 16795395}, {67491, 17913603}, {67492, 17913859}, {67493, 16781315},
2081
  {67494, 17914115}, {67495, 17914371}, {67496, 17135875}, {67497, 17914627},
2082
  {67498, 16819971}, {67499, 17914883}, {67500, 17915139}, {67501, 17915395},
2083
  {67502, 17915651}, {67503, 16820995}, {67504, 17915907}, {67505, 2},
2084
  {67506, 17916163}, {67507, 17916419}, {67508, 17916675}, {67509, 17916931},
2085
  {67510, 17917187}, {67511, 17917443}, {67512, 17917699}, {67513, 17917955},
2086
  {67514, 17918211}, {67515, 2}, {67584, 1}, {67590, 2},
2087
  {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2},
2088
  {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2},
2089
  {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2},
2090
  {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2},
2091
  {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2},
2092
  {67871, 1}, {67898, 2}, {67903, 1}, {67930, 2},
2093
  {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2},
2094
  {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2},
2095
  {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2},
2096
  {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2},
2097
  {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2},
2098
  {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2},
2099
  {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2},
2100
  {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2},
2101
  {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2},
2102
  {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2},
2103
  {68736, 17918467}, {68737, 17918723}, {68738, 17918979}, {68739, 17919235},
2104
  {68740, 17919491}, {68741, 17919747}, {68742, 17920003}, {68743, 17920259},
2105
  {68744, 17920515}, {68745, 17920771}, {68746, 17921027}, {68747, 17921283},
2106
  {68748, 17921539}, {68749, 17921795}, {68750, 17922051}, {68751, 17922307},
2107
  {68752, 17922563}, {68753, 17922819}, {68754, 17923075}, {68755, 17923331},
2108
  {68756, 17923587}, {68757, 17923843}, {68758, 17924099}, {68759, 17924355},
2109
  {68760, 17924611}, {68761, 17924867}, {68762, 17925123}, {68763, 17925379},
2110
  {68764, 17925635}, {68765, 17925891}, {68766, 17926147}, {68767, 17926403},
2111
  {68768, 17926659}, {68769, 17926915}, {68770, 17927171}, {68771, 17927427},
2112
  {68772, 17927683}, {68773, 17927939}, {68774, 17928195}, {68775, 17928451},
2113
  {68776, 17928707}, {68777, 17928963}, {68778, 17929219}, {68779, 17929475},
2114
  {68780, 17929731}, {68781, 17929987}, {68782, 17930243}, {68783, 17930499},
2115
  {68784, 17930755}, {68785, 17931011}, {68786, 17931267}, {68787, 2},
2116
  {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2},
2117
  {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17931523},
2118
  {68945, 17931779}, {68946, 17932035}, {68947, 17932291}, {68948, 17932547},
2119
  {68949, 17932803}, {68950, 17933059}, {68951, 17933315}, {68952, 17933571},
2120
  {68953, 17933827}, {68954, 17934083}, {68955, 17934339}, {68956, 17934595},
2121
  {68957, 17934851}, {68958, 17935107}, {68959, 17935363}, {68960, 17935619},
2122
  {68961, 17935875}, {68962, 17936131}, {68963, 17936387}, {68964, 17936643},
2123
  {68965, 17936899}, {68966, 2}, {68969, 1}, {68998, 2},
2124
  {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2},
2125
  {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2},
2126
  {69296, 1}, {69298, 2}, {69314, 1}, {69320, 2},
2127
  {69328, 1}, {69337, 2}, {69370, 1}, {69416, 2},
2128
  {69424, 1}, {69466, 2}, {69488, 1}, {69514, 2},
2129
  {69552, 1}, {69580, 2}, {69600, 1}, {69623, 2},
2130
  {69632, 1}, {69710, 2}, {69714, 1}, {69750, 2},
2131
  {69759, 1}, {69821, 2}, {69822, 1}, {69827, 2},
2132
  {69840, 1}, {69865, 2}, {69872, 1}, {69882, 2},
2133
  {69888, 1}, {69941, 2}, {69942, 1}, {69960, 2},
2134
  {69968, 1}, {70007, 2}, {70016, 1}, {70112, 2},
2135
  {70113, 1}, {70133, 2}, {70144, 1}, {70162, 2},
2136
  {70163, 1}, {70210, 2}, {70272, 1}, {70279, 2},
2137
  {70280, 1}, {70281, 2}, {70282, 1}, {70286, 2},
2138
  {70287, 1}, {70302, 2}, {70303, 1}, {70314, 2},
2139
  {70320, 1}, {70379, 2}, {70384, 1}, {70394, 2},
2140
  {70400, 1}, {70404, 2}, {70405, 1}, {70413, 2},
2141
  {70415, 1}, {70417, 2}, {70419, 1}, {70441, 2},
2142
  {70442, 1}, {70449, 2}, {70450, 1}, {70452, 2},
2143
  {70453, 1}, {70458, 2}, {70459, 1}, {70469, 2},
2144
  {70471, 1}, {70473, 2}, {70475, 1}, {70478, 2},
2145
  {70480, 1}, {70481, 2}, {70487, 1}, {70488, 2},
2146
  {70493, 1}, {70500, 2}, {70502, 1}, {70509, 2},
2147
  {70512, 1}, {70517, 2}, {70528, 1}, {70538, 2},
2148
  {70539, 1}, {70540, 2}, {70542, 1}, {70543, 2},
2149
  {70544, 1}, {70582, 2}, {70583, 1}, {70593, 2},
2150
  {70594, 1}, {70595, 2}, {70597, 1}, {70598, 2},
2151
  {70599, 1}, {70603, 2}, {70604, 1}, {70614, 2},
2152
  {70615, 1}, {70617, 2}, {70625, 1}, {70627, 2},
2153
  {70656, 1}, {70748, 2}, {70749, 1}, {70754, 2},
2154
  {70784, 1}, {70856, 2}, {70864, 1}, {70874, 2},
2155
  {71040, 1}, {71094, 2}, {71096, 1}, {71134, 2},
2156
  {71168, 1}, {71237, 2}, {71248, 1}, {71258, 2},
2157
  {71264, 1}, {71277, 2}, {71296, 1}, {71354, 2},
2158
  {71360, 1}, {71370, 2}, {71376, 1}, {71396, 2},
2159
  {71424, 1}, {71451, 2}, {71453, 1}, {71468, 2},
2160
  {71472, 1}, {71495, 2}, {71680, 1}, {71740, 2},
2161
  {71840, 17937155}, {71841, 17937411}, {71842, 17937667}, {71843, 17937923},
2162
  {71844, 17938179}, {71845, 17938435}, {71846, 17938691}, {71847, 17938947},
2163
  {71848, 17939203}, {71849, 17939459}, {71850, 17939715}, {71851, 17939971},
2164
  {71852, 17940227}, {71853, 17940483}, {71854, 17940739}, {71855, 17940995},
2165
  {71856, 17941251}, {71857, 17941507}, {71858, 17941763}, {71859, 17942019},
2166
  {71860, 17942275}, {71861, 17942531}, {71862, 17942787}, {71863, 17943043},
2167
  {71864, 17943299}, {71865, 17943555}, {71866, 17943811}, {71867, 17944067},
2168
  {71868, 17944323}, {71869, 17944579}, {71870, 17944835}, {71871, 17945091},
2169
  {71872, 1}, {71923, 2}, {71935, 1}, {71943, 2},
2170
  {71945, 1}, {71946, 2}, {71948, 1}, {71956, 2},
2171
  {71957, 1}, {71959, 2}, {71960, 1}, {71990, 2},
2172
  {71991, 1}, {71993, 2}, {71995, 1}, {72007, 2},
2173
  {72016, 1}, {72026, 2}, {72096, 1}, {72104, 2},
2174
  {72106, 1}, {72152, 2}, {72154, 1}, {72165, 2},
2175
  {72192, 1}, {72264, 2}, {72272, 1}, {72355, 2},
2176
  {72368, 1}, {72441, 2}, {72448, 1}, {72458, 2},
2177
  {72544, 1}, {72552, 2}, {72640, 1}, {72674, 2},
2178
  {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2},
2179
  {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2},
2180
  {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2},
2181
  {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2},
2182
  {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2},
2183
  {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2},
2184
  {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2},
2185
  {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2},
2186
  {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2},
2187
  {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2},
2188
  {73120, 1}, {73130, 2}, {73136, 1}, {73180, 2},
2189
  {73184, 1}, {73194, 2}, {73440, 1}, {73465, 2},
2190
  {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2},
2191
  {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2},
2192
  {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2},
2193
  {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2},
2194
  {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2},
2195
  {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2},
2196
  {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2},
2197
  {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2},
2198
  {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2},
2199
  {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2},
2200
  {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2},
2201
  {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2},
2202
  {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2},
2203
  {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2},
2204
  {93760, 17945347}, {93761, 17945603}, {93762, 17945859}, {93763, 17946115},
2205
  {93764, 17946371}, {93765, 17946627}, {93766, 17946883}, {93767, 17947139},
2206
  {93768, 17947395}, {93769, 17947651}, {93770, 17947907}, {93771, 17948163},
2207
  {93772, 17948419}, {93773, 17948675}, {93774, 17948931}, {93775, 17949187},
2208
  {93776, 17949443}, {93777, 17949699}, {93778, 17949955}, {93779, 17950211},
2209
  {93780, 17950467}, {93781, 17950723}, {93782, 17950979}, {93783, 17951235},
2210
  {93784, 17951491}, {93785, 17951747}, {93786, 17952003}, {93787, 17952259},
2211
  {93788, 17952515}, {93789, 17952771}, {93790, 17953027}, {93791, 17953283},
2212
  {93792, 1}, {93851, 2}, {93856, 17953539}, {93857, 17953795},
2213
  {93858, 17954051}, {93859, 17954307}, {93860, 17954563}, {93861, 17954819},
2214
  {93862, 17955075}, {93863, 17955331}, {93864, 17955587}, {93865, 17955843},
2215
  {93866, 17956099}, {93867, 17956355}, {93868, 17956611}, {93869, 17956867},
2216
  {93870, 17957123}, {93871, 17957379}, {93872, 17957635}, {93873, 17957891},
2217
  {93874, 17958147}, {93875, 17958403}, {93876, 17958659}, {93877, 17958915},
2218
  {93878, 17959171}, {93879, 17959427}, {93880, 17959683}, {93881, 2},
2219
  {93883, 1}, {93908, 2}, {93952, 1}, {94027, 2},
2220
  {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2},
2221
  {94176, 1}, {94181, 2}, {94192, 1}, {94199, 2},
2222
  {94208, 1}, {101590, 2}, {101631, 1}, {101663, 2},
2223
  {101760, 1}, {101875, 2}, {110576, 1}, {110580, 2},
2224
  {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2},
2225
  {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2},
2226
  {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2},
2227
  {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2},
2228
  {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2},
2229
  {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2},
2230
  {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1},
2231
  {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987},
2232
  {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011},
2233
  {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035},
2234
  {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059},
2235
  {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083},
2236
  {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107},
2237
  {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947},
2238
  {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763},
2239
  {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787},
2240
  {118010, 1}, {118013, 2}, {118016, 1}, {118452, 2},
2241
  {118458, 1}, {118481, 2}, {118496, 1}, {118513, 2},
2242
  {118528, 1}, {118574, 2}, {118576, 1}, {118599, 2},
2243
  {118608, 1}, {118724, 2}, {118784, 1}, {119030, 2},
2244
  {119040, 1}, {119079, 2}, {119081, 1}, {119134, 34737155},
2245
  {119135, 34737667}, {119136, 51515395}, {119137, 51516163}, {119138, 51516931},
2246
  {119139, 51517699}, {119140, 51518467}, {119141, 1}, {119155, 0},
2247
  {119163, 1}, {119227, 34742019}, {119228, 34742531}, {119229, 51520259},
2248
  {119230, 51521027}, {119231, 51521795}, {119232, 51522563}, {119233, 1},
2249
  {119275, 2}, {119296, 1}, {119366, 2}, {119488, 1},
2250
  {119508, 2}, {119520, 1}, {119540, 2}, {119552, 1},
2251
  {119639, 2}, {119648, 1}, {119673, 2}, {119808, 16777219},
2252
  {119809, 16777475}, {119810, 16777731}, {119811, 16777987}, {119812, 16778243},
2253
  {119813, 16778499}, {119814, 16778755}, {119815, 16779011}, {119816, 16779267},
2254
  {119817, 16779523}, {119818, 16779779}, {119819, 16780035}, {119820, 16780291},
2255
  {119821, 16780547}, {119822, 16780803}, {119823, 16781059}, {119824, 16781315},
2256
  {119825, 16781571}, {119826, 16781827}, {119827, 16782083}, {119828, 16782339},
2257
  {119829, 16782595}, {119830, 16782851}, {119831, 16783107}, {119832, 16783363},
2258
  {119833, 16783619}, {119834, 16777219}, {119835, 16777475}, {119836, 16777731},
2259
  {119837, 16777987}, {119838, 16778243}, {119839, 16778499}, {119840, 16778755},
2260
  {119841, 16779011}, {119842, 16779267}, {119843, 16779523}, {119844, 16779779},
2261
  {119845, 16780035}, {119846, 16780291}, {119847, 16780547}, {119848, 16780803},
2262
  {119849, 16781059}, {119850, 16781315}, {119851, 16781571}, {119852, 16781827},
2263
  {119853, 16782083}, {119854, 16782339}, {119855, 16782595}, {119856, 16782851},
2264
  {119857, 16783107}, {119858, 16783363}, {119859, 16783619}, {119860, 16777219},
2265
  {119861, 16777475}, {119862, 16777731}, {119863, 16777987}, {119864, 16778243},
2266
  {119865, 16778499}, {119866, 16778755}, {119867, 16779011}, {119868, 16779267},
2267
  {119869, 16779523}, {119870, 16779779}, {119871, 16780035}, {119872, 16780291},
2268
  {119873, 16780547}, {119874, 16780803}, {119875, 16781059}, {119876, 16781315},
2269
  {119877, 16781571}, {119878, 16781827}, {119879, 16782083}, {119880, 16782339},
2270
  {119881, 16782595}, {119882, 16782851}, {119883, 16783107}, {119884, 16783363},
2271
  {119885, 16783619}, {119886, 16777219}, {119887, 16777475}, {119888, 16777731},
2272
  {119889, 16777987}, {119890, 16778243}, {119891, 16778499}, {119892, 16778755},
2273
  {119893, 2}, {119894, 16779267}, {119895, 16779523}, {119896, 16779779},
2274
  {119897, 16780035}, {119898, 16780291}, {119899, 16780547}, {119900, 16780803},
2275
  {119901, 16781059}, {119902, 16781315}, {119903, 16781571}, {119904, 16781827},
2276
  {119905, 16782083}, {119906, 16782339}, {119907, 16782595}, {119908, 16782851},
2277
  {119909, 16783107}, {119910, 16783363}, {119911, 16783619}, {119912, 16777219},
2278
  {119913, 16777475}, {119914, 16777731}, {119915, 16777987}, {119916, 16778243},
2279
  {119917, 16778499}, {119918, 16778755}, {119919, 16779011}, {119920, 16779267},
2280
  {119921, 16779523}, {119922, 16779779}, {119923, 16780035}, {119924, 16780291},
2281
  {119925, 16780547}, {119926, 16780803}, {119927, 16781059}, {119928, 16781315},
2282
  {119929, 16781571}, {119930, 16781827}, {119931, 16782083}, {119932, 16782339},
2283
  {119933, 16782595}, {119934, 16782851}, {119935, 16783107}, {119936, 16783363},
2284
  {119937, 16783619}, {119938, 16777219}, {119939, 16777475}, {119940, 16777731},
2285
  {119941, 16777987}, {119942, 16778243}, {119943, 16778499}, {119944, 16778755},
2286
  {119945, 16779011}, {119946, 16779267}, {119947, 16779523}, {119948, 16779779},
2287
  {119949, 16780035}, {119950, 16780291}, {119951, 16780547}, {119952, 16780803},
2288
  {119953, 16781059}, {119954, 16781315}, {119955, 16781571}, {119956, 16781827},
2289
  {119957, 16782083}, {119958, 16782339}, {119959, 16782595}, {119960, 16782851},
2290
  {119961, 16783107}, {119962, 16783363}, {119963, 16783619}, {119964, 16777219},
2291
  {119965, 2}, {119966, 16777731}, {119967, 16777987}, {119968, 2},
2292
  {119970, 16778755}, {119971, 2}, {119973, 16779523}, {119974, 16779779},
2293
  {119975, 2}, {119977, 16780547}, {119978, 16780803}, {119979, 16781059},
2294
  {119980, 16781315}, {119981, 2}, {119982, 16781827}, {119983, 16782083},
2295
  {119984, 16782339}, {119985, 16782595}, {119986, 16782851}, {119987, 16783107},
2296
  {119988, 16783363}, {119989, 16783619}, {119990, 16777219}, {119991, 16777475},
2297
  {119992, 16777731}, {119993, 16777987}, {119994, 2}, {119995, 16778499},
2298
  {119996, 2}, {119997, 16779011}, {119998, 16779267}, {119999, 16779523},
2299
  {120000, 16779779}, {120001, 16780035}, {120002, 16780291}, {120003, 16780547},
2300
  {120004, 2}, {120005, 16781059}, {120006, 16781315}, {120007, 16781571},
2301
  {120008, 16781827}, {120009, 16782083}, {120010, 16782339}, {120011, 16782595},
2302
  {120012, 16782851}, {120013, 16783107}, {120014, 16783363}, {120015, 16783619},
2303
  {120016, 16777219}, {120017, 16777475}, {120018, 16777731}, {120019, 16777987},
2304
  {120020, 16778243}, {120021, 16778499}, {120022, 16778755}, {120023, 16779011},
2305
  {120024, 16779267}, {120025, 16779523}, {120026, 16779779}, {120027, 16780035},
2306
  {120028, 16780291}, {120029, 16780547}, {120030, 16780803}, {120031, 16781059},
2307
  {120032, 16781315}, {120033, 16781571}, {120034, 16781827}, {120035, 16782083},
2308
  {120036, 16782339}, {120037, 16782595}, {120038, 16782851}, {120039, 16783107},
2309
  {120040, 16783363}, {120041, 16783619}, {120042, 16777219}, {120043, 16777475},
2310
  {120044, 16777731}, {120045, 16777987}, {120046, 16778243}, {120047, 16778499},
2311
  {120048, 16778755}, {120049, 16779011}, {120050, 16779267}, {120051, 16779523},
2312
  {120052, 16779779}, {120053, 16780035}, {120054, 16780291}, {120055, 16780547},
2313
  {120056, 16780803}, {120057, 16781059}, {120058, 16781315}, {120059, 16781571},
2314
  {120060, 16781827}, {120061, 16782083}, {120062, 16782339}, {120063, 16782595},
2315
  {120064, 16782851}, {120065, 16783107}, {120066, 16783363}, {120067, 16783619},
2316
  {120068, 16777219}, {120069, 16777475}, {120070, 2}, {120071, 16777987},
2317
  {120072, 16778243}, {120073, 16778499}, {120074, 16778755}, {120075, 2},
2318
  {120077, 16779523}, {120078, 16779779}, {120079, 16780035}, {120080, 16780291},
2319
  {120081, 16780547}, {120082, 16780803}, {120083, 16781059}, {120084, 16781315},
2320
  {120085, 2}, {120086, 16781827}, {120087, 16782083}, {120088, 16782339},
2321
  {120089, 16782595}, {120090, 16782851}, {120091, 16783107}, {120092, 16783363},
2322
  {120093, 2}, {120094, 16777219}, {120095, 16777475}, {120096, 16777731},
2323
  {120097, 16777987}, {120098, 16778243}, {120099, 16778499}, {120100, 16778755},
2324
  {120101, 16779011}, {120102, 16779267}, {120103, 16779523}, {120104, 16779779},
2325
  {120105, 16780035}, {120106, 16780291}, {120107, 16780547}, {120108, 16780803},
2326
  {120109, 16781059}, {120110, 16781315}, {120111, 16781571}, {120112, 16781827},
2327
  {120113, 16782083}, {120114, 16782339}, {120115, 16782595}, {120116, 16782851},
2328
  {120117, 16783107}, {120118, 16783363}, {120119, 16783619}, {120120, 16777219},
2329
  {120121, 16777475}, {120122, 2}, {120123, 16777987}, {120124, 16778243},
2330
  {120125, 16778499}, {120126, 16778755}, {120127, 2}, {120128, 16779267},
2331
  {120129, 16779523}, {120130, 16779779}, {120131, 16780035}, {120132, 16780291},
2332
  {120133, 2}, {120134, 16780803}, {120135, 2}, {120138, 16781827},
2333
  {120139, 16782083}, {120140, 16782339}, {120141, 16782595}, {120142, 16782851},
2334
  {120143, 16783107}, {120144, 16783363}, {120145, 2}, {120146, 16777219},
2335
  {120147, 16777475}, {120148, 16777731}, {120149, 16777987}, {120150, 16778243},
2336
  {120151, 16778499}, {120152, 16778755}, {120153, 16779011}, {120154, 16779267},
2337
  {120155, 16779523}, {120156, 16779779}, {120157, 16780035}, {120158, 16780291},
2338
  {120159, 16780547}, {120160, 16780803}, {120161, 16781059}, {120162, 16781315},
2339
  {120163, 16781571}, {120164, 16781827}, {120165, 16782083}, {120166, 16782339},
2340
  {120167, 16782595}, {120168, 16782851}, {120169, 16783107}, {120170, 16783363},
2341
  {120171, 16783619}, {120172, 16777219}, {120173, 16777475}, {120174, 16777731},
2342
  {120175, 16777987}, {120176, 16778243}, {120177, 16778499}, {120178, 16778755},
2343
  {120179, 16779011}, {120180, 16779267}, {120181, 16779523}, {120182, 16779779},
2344
  {120183, 16780035}, {120184, 16780291}, {120185, 16780547}, {120186, 16780803},
2345
  {120187, 16781059}, {120188, 16781315}, {120189, 16781571}, {120190, 16781827},
2346
  {120191, 16782083}, {120192, 16782339}, {120193, 16782595}, {120194, 16782851},
2347
  {120195, 16783107}, {120196, 16783363}, {120197, 16783619}, {120198, 16777219},
2348
  {120199, 16777475}, {120200, 16777731}, {120201, 16777987}, {120202, 16778243},
2349
  {120203, 16778499}, {120204, 16778755}, {120205, 16779011}, {120206, 16779267},
2350
  {120207, 16779523}, {120208, 16779779}, {120209, 16780035}, {120210, 16780291},
2351
  {120211, 16780547}, {120212, 16780803}, {120213, 16781059}, {120214, 16781315},
2352
  {120215, 16781571}, {120216, 16781827}, {120217, 16782083}, {120218, 16782339},
2353
  {120219, 16782595}, {120220, 16782851}, {120221, 16783107}, {120222, 16783363},
2354
  {120223, 16783619}, {120224, 16777219}, {120225, 16777475}, {120226, 16777731},
2355
  {120227, 16777987}, {120228, 16778243}, {120229, 16778499}, {120230, 16778755},
2356
  {120231, 16779011}, {120232, 16779267}, {120233, 16779523}, {120234, 16779779},
2357
  {120235, 16780035}, {120236, 16780291}, {120237, 16780547}, {120238, 16780803},
2358
  {120239, 16781059}, {120240, 16781315}, {120241, 16781571}, {120242, 16781827},
2359
  {120243, 16782083}, {120244, 16782339}, {120245, 16782595}, {120246, 16782851},
2360
  {120247, 16783107}, {120248, 16783363}, {120249, 16783619}, {120250, 16777219},
2361
  {120251, 16777475}, {120252, 16777731}, {120253, 16777987}, {120254, 16778243},
2362
  {120255, 16778499}, {120256, 16778755}, {120257, 16779011}, {120258, 16779267},
2363
  {120259, 16779523}, {120260, 16779779}, {120261, 16780035}, {120262, 16780291},
2364
  {120263, 16780547}, {120264, 16780803}, {120265, 16781059}, {120266, 16781315},
2365
  {120267, 16781571}, {120268, 16781827}, {120269, 16782083}, {120270, 16782339},
2366
  {120271, 16782595}, {120272, 16782851}, {120273, 16783107}, {120274, 16783363},
2367
  {120275, 16783619}, {120276, 16777219}, {120277, 16777475}, {120278, 16777731},
2368
  {120279, 16777987}, {120280, 16778243}, {120281, 16778499}, {120282, 16778755},
2369
  {120283, 16779011}, {120284, 16779267}, {120285, 16779523}, {120286, 16779779},
2370
  {120287, 16780035}, {120288, 16780291}, {120289, 16780547}, {120290, 16780803},
2371
  {120291, 16781059}, {120292, 16781315}, {120293, 16781571}, {120294, 16781827},
2372
  {120295, 16782083}, {120296, 16782339}, {120297, 16782595}, {120298, 16782851},
2373
  {120299, 16783107}, {120300, 16783363}, {120301, 16783619}, {120302, 16777219},
2374
  {120303, 16777475}, {120304, 16777731}, {120305, 16777987}, {120306, 16778243},
2375
  {120307, 16778499}, {120308, 16778755}, {120309, 16779011}, {120310, 16779267},
2376
  {120311, 16779523}, {120312, 16779779}, {120313, 16780035}, {120314, 16780291},
2377
  {120315, 16780547}, {120316, 16780803}, {120317, 16781059}, {120318, 16781315},
2378
  {120319, 16781571}, {120320, 16781827}, {120321, 16782083}, {120322, 16782339},
2379
  {120323, 16782595}, {120324, 16782851}, {120325, 16783107}, {120326, 16783363},
2380
  {120327, 16783619}, {120328, 16777219}, {120329, 16777475}, {120330, 16777731},
2381
  {120331, 16777987}, {120332, 16778243}, {120333, 16778499}, {120334, 16778755},
2382
  {120335, 16779011}, {120336, 16779267}, {120337, 16779523}, {120338, 16779779},
2383
  {120339, 16780035}, {120340, 16780291}, {120341, 16780547}, {120342, 16780803},
2384
  {120343, 16781059}, {120344, 16781315}, {120345, 16781571}, {120346, 16781827},
2385
  {120347, 16782083}, {120348, 16782339}, {120349, 16782595}, {120350, 16782851},
2386
  {120351, 16783107}, {120352, 16783363}, {120353, 16783619}, {120354, 16777219},
2387
  {120355, 16777475}, {120356, 16777731}, {120357, 16777987}, {120358, 16778243},
2388
  {120359, 16778499}, {120360, 16778755}, {120361, 16779011}, {120362, 16779267},
2389
  {120363, 16779523}, {120364, 16779779}, {120365, 16780035}, {120366, 16780291},
2390
  {120367, 16780547}, {120368, 16780803}, {120369, 16781059}, {120370, 16781315},
2391
  {120371, 16781571}, {120372, 16781827}, {120373, 16782083}, {120374, 16782339},
2392
  {120375, 16782595}, {120376, 16782851}, {120377, 16783107}, {120378, 16783363},
2393
  {120379, 16783619}, {120380, 16777219}, {120381, 16777475}, {120382, 16777731},
2394
  {120383, 16777987}, {120384, 16778243}, {120385, 16778499}, {120386, 16778755},
2395
  {120387, 16779011}, {120388, 16779267}, {120389, 16779523}, {120390, 16779779},
2396
  {120391, 16780035}, {120392, 16780291}, {120393, 16780547}, {120394, 16780803},
2397
  {120395, 16781059}, {120396, 16781315}, {120397, 16781571}, {120398, 16781827},
2398
  {120399, 16782083}, {120400, 16782339}, {120401, 16782595}, {120402, 16782851},
2399
  {120403, 16783107}, {120404, 16783363}, {120405, 16783619}, {120406, 16777219},
2400
  {120407, 16777475}, {120408, 16777731}, {120409, 16777987}, {120410, 16778243},
2401
  {120411, 16778499}, {120412, 16778755}, {120413, 16779011}, {120414, 16779267},
2402
  {120415, 16779523}, {120416, 16779779}, {120417, 16780035}, {120418, 16780291},
2403
  {120419, 16780547}, {120420, 16780803}, {120421, 16781059}, {120422, 16781315},
2404
  {120423, 16781571}, {120424, 16781827}, {120425, 16782083}, {120426, 16782339},
2405
  {120427, 16782595}, {120428, 16782851}, {120429, 16783107}, {120430, 16783363},
2406
  {120431, 16783619}, {120432, 16777219}, {120433, 16777475}, {120434, 16777731},
2407
  {120435, 16777987}, {120436, 16778243}, {120437, 16778499}, {120438, 16778755},
2408
  {120439, 16779011}, {120440, 16779267}, {120441, 16779523}, {120442, 16779779},
2409
  {120443, 16780035}, {120444, 16780291}, {120445, 16780547}, {120446, 16780803},
2410
  {120447, 16781059}, {120448, 16781315}, {120449, 16781571}, {120450, 16781827},
2411
  {120451, 16782083}, {120452, 16782339}, {120453, 16782595}, {120454, 16782851},
2412
  {120455, 16783107}, {120456, 16783363}, {120457, 16783619}, {120458, 16777219},
2413
  {120459, 16777475}, {120460, 16777731}, {120461, 16777987}, {120462, 16778243},
2414
  {120463, 16778499}, {120464, 16778755}, {120465, 16779011}, {120466, 16779267},
2415
  {120467, 16779523}, {120468, 16779779}, {120469, 16780035}, {120470, 16780291},
2416
  {120471, 16780547}, {120472, 16780803}, {120473, 16781059}, {120474, 16781315},
2417
  {120475, 16781571}, {120476, 16781827}, {120477, 16782083}, {120478, 16782339},
2418
  {120479, 16782595}, {120480, 16782851}, {120481, 16783107}, {120482, 16783363},
2419
  {120483, 16783619}, {120484, 17968899}, {120485, 17969155}, {120486, 2},
2420
  {120488, 16851715}, {120489, 16851971}, {120490, 16852227}, {120491, 16852483},
2421
  {120492, 16852739}, {120493, 16852995}, {120494, 16853251}, {120495, 16853507},
2422
  {120496, 16846851}, {120497, 16853763}, {120498, 16854019}, {120499, 16786179},
2423
  {120500, 16854275}, {120501, 16854531}, {120502, 16854787}, {120503, 16855043},
2424
  {120504, 16855299}, {120505, 16853507}, {120506, 16855555}, {120507, 16855811},
2425
  {120508, 16856067}, {120509, 16856323}, {120510, 16856579}, {120511, 16856835},
2426
  {120512, 16857091}, {120513, 17969411}, {120514, 16851715}, {120515, 16851971},
2427
  {120516, 16852227}, {120517, 16852483}, {120518, 16852739}, {120519, 16852995},
2428
  {120520, 16853251}, {120521, 16853507}, {120522, 16846851}, {120523, 16853763},
2429
  {120524, 16854019}, {120525, 16786179}, {120526, 16854275}, {120527, 16854531},
2430
  {120528, 16854787}, {120529, 16855043}, {120530, 16855299}, {120531, 16855555},
2431
  {120533, 16855811}, {120534, 16856067}, {120535, 16856323}, {120536, 16856579},
2432
  {120537, 16856835}, {120538, 16857091}, {120539, 17969667}, {120540, 16852739},
2433
  {120541, 16853507}, {120542, 16853763}, {120543, 16856323}, {120544, 16855299},
2434
  {120545, 16855043}, {120546, 16851715}, {120547, 16851971}, {120548, 16852227},
2435
  {120549, 16852483}, {120550, 16852739}, {120551, 16852995}, {120552, 16853251},
2436
  {120553, 16853507}, {120554, 16846851}, {120555, 16853763}, {120556, 16854019},
2437
  {120557, 16786179}, {120558, 16854275}, {120559, 16854531}, {120560, 16854787},
2438
  {120561, 16855043}, {120562, 16855299}, {120563, 16853507}, {120564, 16855555},
2439
  {120565, 16855811}, {120566, 16856067}, {120567, 16856323}, {120568, 16856579},
2440
  {120569, 16856835}, {120570, 16857091}, {120571, 17969411}, {120572, 16851715},
2441
  {120573, 16851971}, {120574, 16852227}, {120575, 16852483}, {120576, 16852739},
2442
  {120577, 16852995}, {120578, 16853251}, {120579, 16853507}, {120580, 16846851},
2443
  {120581, 16853763}, {120582, 16854019}, {120583, 16786179}, {120584, 16854275},
2444
  {120585, 16854531}, {120586, 16854787}, {120587, 16855043}, {120588, 16855299},
2445
  {120589, 16855555}, {120591, 16855811}, {120592, 16856067}, {120593, 16856323},
2446
  {120594, 16856579}, {120595, 16856835}, {120596, 16857091}, {120597, 17969667},
2447
  {120598, 16852739}, {120599, 16853507}, {120600, 16853763}, {120601, 16856323},
2448
  {120602, 16855299}, {120603, 16855043}, {120604, 16851715}, {120605, 16851971},
2449
  {120606, 16852227}, {120607, 16852483}, {120608, 16852739}, {120609, 16852995},
2450
  {120610, 16853251}, {120611, 16853507}, {120612, 16846851}, {120613, 16853763},
2451
  {120614, 16854019}, {120615, 16786179}, {120616, 16854275}, {120617, 16854531},
2452
  {120618, 16854787}, {120619, 16855043}, {120620, 16855299}, {120621, 16853507},
2453
  {120622, 16855555}, {120623, 16855811}, {120624, 16856067}, {120625, 16856323},
2454
  {120626, 16856579}, {120627, 16856835}, {120628, 16857091}, {120629, 17969411},
2455
  {120630, 16851715}, {120631, 16851971}, {120632, 16852227}, {120633, 16852483},
2456
  {120634, 16852739}, {120635, 16852995}, {120636, 16853251}, {120637, 16853507},
2457
  {120638, 16846851}, {120639, 16853763}, {120640, 16854019}, {120641, 16786179},
2458
  {120642, 16854275}, {120643, 16854531}, {120644, 16854787}, {120645, 16855043},
2459
  {120646, 16855299}, {120647, 16855555}, {120649, 16855811}, {120650, 16856067},
2460
  {120651, 16856323}, {120652, 16856579}, {120653, 16856835}, {120654, 16857091},
2461
  {120655, 17969667}, {120656, 16852739}, {120657, 16853507}, {120658, 16853763},
2462
  {120659, 16856323}, {120660, 16855299}, {120661, 16855043}, {120662, 16851715},
2463
  {120663, 16851971}, {120664, 16852227}, {120665, 16852483}, {120666, 16852739},
2464
  {120667, 16852995}, {120668, 16853251}, {120669, 16853507}, {120670, 16846851},
2465
  {120671, 16853763}, {120672, 16854019}, {120673, 16786179}, {120674, 16854275},
2466
  {120675, 16854531}, {120676, 16854787}, {120677, 16855043}, {120678, 16855299},
2467
  {120679, 16853507}, {120680, 16855555}, {120681, 16855811}, {120682, 16856067},
2468
  {120683, 16856323}, {120684, 16856579}, {120685, 16856835}, {120686, 16857091},
2469
  {120687, 17969411}, {120688, 16851715}, {120689, 16851971}, {120690, 16852227},
2470
  {120691, 16852483}, {120692, 16852739}, {120693, 16852995}, {120694, 16853251},
2471
  {120695, 16853507}, {120696, 16846851}, {120697, 16853763}, {120698, 16854019},
2472
  {120699, 16786179}, {120700, 16854275}, {120701, 16854531}, {120702, 16854787},
2473
  {120703, 16855043}, {120704, 16855299}, {120705, 16855555}, {120707, 16855811},
2474
  {120708, 16856067}, {120709, 16856323}, {120710, 16856579}, {120711, 16856835},
2475
  {120712, 16857091}, {120713, 17969667}, {120714, 16852739}, {120715, 16853507},
2476
  {120716, 16853763}, {120717, 16856323}, {120718, 16855299}, {120719, 16855043},
2477
  {120720, 16851715}, {120721, 16851971}, {120722, 16852227}, {120723, 16852483},
2478
  {120724, 16852739}, {120725, 16852995}, {120726, 16853251}, {120727, 16853507},
2479
  {120728, 16846851}, {120729, 16853763}, {120730, 16854019}, {120731, 16786179},
2480
  {120732, 16854275}, {120733, 16854531}, {120734, 16854787}, {120735, 16855043},
2481
  {120736, 16855299}, {120737, 16853507}, {120738, 16855555}, {120739, 16855811},
2482
  {120740, 16856067}, {120741, 16856323}, {120742, 16856579}, {120743, 16856835},
2483
  {120744, 16857091}, {120745, 17969411}, {120746, 16851715}, {120747, 16851971},
2484
  {120748, 16852227}, {120749, 16852483}, {120750, 16852739}, {120751, 16852995},
2485
  {120752, 16853251}, {120753, 16853507}, {120754, 16846851}, {120755, 16853763},
2486
  {120756, 16854019}, {120757, 16786179}, {120758, 16854275}, {120759, 16854531},
2487
  {120760, 16854787}, {120761, 16855043}, {120762, 16855299}, {120763, 16855555},
2488
  {120765, 16855811}, {120766, 16856067}, {120767, 16856323}, {120768, 16856579},
2489
  {120769, 16856835}, {120770, 16857091}, {120771, 17969667}, {120772, 16852739},
2490
  {120773, 16853507}, {120774, 16853763}, {120775, 16856323}, {120776, 16855299},
2491
  {120777, 16855043}, {120778, 16858627}, {120780, 2}, {120782, 17045507},
2492
  {120783, 16786947}, {120784, 16785155}, {120785, 16785411}, {120786, 16787715},
2493
  {120787, 17045763}, {120788, 17046019}, {120789, 17046275}, {120790, 17046531},
2494
  {120791, 17046787}, {120792, 17045507}, {120793, 16786947}, {120794, 16785155},
2495
  {120795, 16785411}, {120796, 16787715}, {120797, 17045763}, {120798, 17046019},
2496
  {120799, 17046275}, {120800, 17046531}, {120801, 17046787}, {120802, 17045507},
2497
  {120803, 16786947}, {120804, 16785155}, {120805, 16785411}, {120806, 16787715},
2498
  {120807, 17045763}, {120808, 17046019}, {120809, 17046275}, {120810, 17046531},
2499
  {120811, 17046787}, {120812, 17045507}, {120813, 16786947}, {120814, 16785155},
2500
  {120815, 16785411}, {120816, 16787715}, {120817, 17045763}, {120818, 17046019},
2501
  {120819, 17046275}, {120820, 17046531}, {120821, 17046787}, {120822, 17045507},
2502
  {120823, 16786947}, {120824, 16785155}, {120825, 16785411}, {120826, 16787715},
2503
  {120827, 17045763}, {120828, 17046019}, {120829, 17046275}, {120830, 17046531},
2504
  {120831, 17046787}, {120832, 1}, {121484, 2}, {121499, 1},
2505
  {121504, 2}, {121505, 1}, {121520, 2}, {122624, 1},
2506
  {122655, 2}, {122661, 1}, {122667, 2}, {122880, 1},
2507
  {122887, 2}, {122888, 1}, {122905, 2}, {122907, 1},
2508
  {122914, 2}, {122915, 1}, {122917, 2}, {122918, 1},
2509
  {122923, 2}, {122928, 16866563}, {122929, 16866819}, {122930, 16867075},
2510
  {122931, 16867331}, {122932, 16867587}, {122933, 16867843}, {122934, 16868099},
2511
  {122935, 16868355}, {122936, 16868611}, {122937, 16869123}, {122938, 16869379},
2512
  {122939, 16869635}, {122940, 16870147}, {122941, 16870403}, {122942, 16870659},
2513
  {122943, 16870915}, {122944, 16871171}, {122945, 16871427}, {122946, 16871683},
2514
  {122947, 16871939}, {122948, 16872195}, {122949, 16872451}, {122950, 16872707},
2515
  {122951, 16873475}, {122952, 16873987}, {122953, 16874243}, {122954, 17505795},
2516
  {122955, 16889091}, {122956, 16864003}, {122957, 16864515}, {122958, 16891139},
2517
  {122959, 16883715}, {122960, 16886019}, {122961, 16866563}, {122962, 16866819},
2518
  {122963, 16867075}, {122964, 16867331}, {122965, 16867587}, {122966, 16867843},
2519
  {122967, 16868099}, {122968, 16868355}, {122969, 16868611}, {122970, 16869123},
2520
  {122971, 16869379}, {122972, 16870147}, {122973, 16870403}, {122974, 16870915},
2521
  {122975, 16871427}, {122976, 16871683}, {122977, 16871939}, {122978, 16872195},
2522
  {122979, 16872451}, {122980, 16872707}, {122981, 16873219}, {122982, 16873475},
2523
  {122983, 16879875}, {122984, 16864003}, {122985, 16863747}, {122986, 16866307},
2524
  {122987, 16883203}, {122988, 17500931}, {122989, 16883971}, {122990, 2},
2525
  {123023, 1}, {123024, 2}, {123136, 1}, {123181, 2},
2526
  {123184, 1}, {123198, 2}, {123200, 1}, {123210, 2},
2527
  {123214, 1}, {123216, 2}, {123536, 1}, {123567, 2},
2528
  {123584, 1}, {123642, 2}, {123647, 1}, {123648, 2},
2529
  {124112, 1}, {124154, 2}, {124368, 1}, {124411, 2},
2530
  {124415, 1}, {124416, 2}, {124608, 1}, {124639, 2},
2531
  {124640, 1}, {124662, 2}, {124670, 1}, {124672, 2},
2532
  {124896, 1}, {124903, 2}, {124904, 1}, {124908, 2},
2533
  {124909, 1}, {124911, 2}, {124912, 1}, {124927, 2},
2534
  {124928, 1}, {125125, 2}, {125127, 1}, {125143, 2},
2535
  {125184, 17969923}, {125185, 17970179}, {125186, 17970435}, {125187, 17970691},
2536
  {125188, 17970947}, {125189, 17971203}, {125190, 17971459}, {125191, 17971715},
2537
  {125192, 17971971}, {125193, 17972227}, {125194, 17972483}, {125195, 17972739},
2538
  {125196, 17972995}, {125197, 17973251}, {125198, 17973507}, {125199, 17973763},
2539
  {125200, 17974019}, {125201, 17974275}, {125202, 17974531}, {125203, 17974787},
2540
  {125204, 17975043}, {125205, 17975299}, {125206, 17975555}, {125207, 17975811},
2541
  {125208, 17976067}, {125209, 17976323}, {125210, 17976579}, {125211, 17976835},
2542
  {125212, 17977091}, {125213, 17977347}, {125214, 17977603}, {125215, 17977859},
2543
  {125216, 17978115}, {125217, 17978371}, {125218, 1}, {125260, 2},
2544
  {125264, 1}, {125274, 2}, {125278, 1}, {125280, 2},
2545
  {126065, 1}, {126133, 2}, {126209, 1}, {126270, 2},
2546
  {126464, 16910595}, {126465, 17696003}, {126466, 17694211}, {126467, 17846787},
2547
  {126468, 2}, {126469, 16911107}, {126470, 17743875}, {126471, 17694723},
2548
  {126472, 17712387}, {126473, 16912131}, {126474, 17721091}, {126475, 17723395},
2549
  {126476, 17695235}, {126477, 17730307}, {126478, 17707267}, {126479, 17713923},
2550
  {126480, 17715971}, {126481, 17709315}, {126482, 17719043}, {126483, 17737475},
2551
  {126484, 17757443}, {126485, 17699075}, {126486, 17702147}, {126487, 17697283},
2552
  {126488, 17736963}, {126489, 17710339}, {126490, 17713411}, {126491, 17714947},
2553
  {126492, 17978627}, {126493, 17685763}, {126494, 17978883}, {126495, 17979139},
2554
  {126496, 2}, {126497, 17696003}, {126498, 17694211}, {126499, 2},
2555
  {126500, 17733379}, {126501, 2}, {126503, 17694723}, {126504, 2},
2556
  {126505, 16912131}, {126506, 17721091}, {126507, 17723395}, {126508, 17695235},
2557
  {126509, 17730307}, {126510, 17707267}, {126511, 17713923}, {126512, 17715971},
2558
  {126513, 17709315}, {126514, 17719043}, {126515, 2}, {126516, 17757443},
2559
  {126517, 17699075}, {126518, 17702147}, {126519, 17697283}, {126520, 2},
2560
  {126521, 17710339}, {126522, 2}, {126523, 17714947}, {126524, 2},
2561
  {126530, 17694211}, {126531, 2}, {126535, 17694723}, {126536, 2},
2562
  {126537, 16912131}, {126538, 2}, {126539, 17723395}, {126540, 2},
2563
  {126541, 17730307}, {126542, 17707267}, {126543, 17713923}, {126544, 2},
2564
  {126545, 17709315}, {126546, 17719043}, {126547, 2}, {126548, 17757443},
2565
  {126549, 2}, {126551, 17697283}, {126552, 2}, {126553, 17710339},
2566
  {126554, 2}, {126555, 17714947}, {126556, 2}, {126557, 17685763},
2567
  {126558, 2}, {126559, 17979139}, {126560, 2}, {126561, 17696003},
2568
  {126562, 17694211}, {126563, 2}, {126564, 17733379}, {126565, 2},
2569
  {126567, 17694723}, {126568, 17712387}, {126569, 16912131}, {126570, 17721091},
2570
  {126571, 2}, {126572, 17695235}, {126573, 17730307}, {126574, 17707267},
2571
  {126575, 17713923}, {126576, 17715971}, {126577, 17709315}, {126578, 17719043},
2572
  {126579, 2}, {126580, 17757443}, {126581, 17699075}, {126582, 17702147},
2573
  {126583, 17697283}, {126584, 2}, {126585, 17710339}, {126586, 17713411},
2574
  {126587, 17714947}, {126588, 17978627}, {126589, 2}, {126590, 17978883},
2575
  {126591, 2}, {126592, 16910595}, {126593, 17696003}, {126594, 17694211},
2576
  {126595, 17846787}, {126596, 17733379}, {126597, 16911107}, {126598, 17743875},
2577
  {126599, 17694723}, {126600, 17712387}, {126601, 16912131}, {126602, 2},
2578
  {126603, 17723395}, {126604, 17695235}, {126605, 17730307}, {126606, 17707267},
2579
  {126607, 17713923}, {126608, 17715971}, {126609, 17709315}, {126610, 17719043},
2580
  {126611, 17737475}, {126612, 17757443}, {126613, 17699075}, {126614, 17702147},
2581
  {126615, 17697283}, {126616, 17736963}, {126617, 17710339}, {126618, 17713411},
2582
  {126619, 17714947}, {126620, 2}, {126625, 17696003}, {126626, 17694211},
2583
  {126627, 17846787}, {126628, 2}, {126629, 16911107}, {126630, 17743875},
2584
  {126631, 17694723}, {126632, 17712387}, {126633, 16912131}, {126634, 2},
2585
  {126635, 17723395}, {126636, 17695235}, {126637, 17730307}, {126638, 17707267},
2586
  {126639, 17713923}, {126640, 17715971}, {126641, 17709315}, {126642, 17719043},
2587
  {126643, 17737475}, {126644, 17757443}, {126645, 17699075}, {126646, 17702147},
2588
  {126647, 17697283}, {126648, 17736963}, {126649, 17710339}, {126650, 17713411},
2589
  {126651, 17714947}, {126652, 2}, {126704, 1}, {126706, 2},
2590
  {126976, 1}, {127020, 2}, {127024, 1}, {127124, 2},
2591
  {127136, 1}, {127151, 2}, {127153, 1}, {127168, 2},
2592
  {127169, 1}, {127184, 2}, {127185, 1}, {127222, 2},
2593
  {127233, 34756611}, {127234, 34757123}, {127235, 34757635}, {127236, 34758147},
2594
  {127237, 34758659}, {127238, 34759171}, {127239, 34759683}, {127240, 34760195},
2595
  {127241, 34760707}, {127242, 34761219}, {127243, 1}, {127248, 50655491},
2596
  {127249, 50656259}, {127250, 50657027}, {127251, 50657795}, {127252, 50658563},
2597
  {127253, 50659331}, {127254, 50660099}, {127255, 50660867}, {127256, 50661635},
2598
  {127257, 50662403}, {127258, 50663171}, {127259, 50663939}, {127260, 50664707},
2599
  {127261, 50665475}, {127262, 50666243}, {127263, 50667011}, {127264, 50667779},
2600
  {127265, 50668547}, {127266, 50669315}, {127267, 50670083}, {127268, 50670851},
2601
  {127269, 50671619}, {127270, 50672387}, {127271, 50673155}, {127272, 50673923},
2602
  {127273, 50674691}, {127274, 51538947}, {127275, 16777731}, {127276, 16781571},
2603
  {127277, 33554947}, {127278, 34762499}, {127279, 1}, {127280, 16777219},
2604
  {127281, 16777475}, {127282, 16777731}, {127283, 16777987}, {127284, 16778243},
2605
  {127285, 16778499}, {127286, 16778755}, {127287, 16779011}, {127288, 16779267},
2606
  {127289, 16779523}, {127290, 16779779}, {127291, 16780035}, {127292, 16780291},
2607
  {127293, 16780547}, {127294, 16780803}, {127295, 16781059}, {127296, 16781315},
2608
  {127297, 16781571}, {127298, 16781827}, {127299, 16782083}, {127300, 16782339},
2609
  {127301, 16782595}, {127302, 16782851}, {127303, 16783107}, {127304, 16783363},
2610
  {127305, 16783619}, {127306, 34763011}, {127307, 34237187}, {127308, 34763523},
2611
  {127309, 34764035}, {127310, 51541763}, {127311, 34765315}, {127312, 1},
2612
  {127338, 34220035}, {127339, 34200067}, {127340, 34765827}, {127341, 1},
2613
  {127376, 34766339}, {127377, 1}, {127406, 2}, {127462, 1},
2614
  {127488, 34766851}, {127489, 34767363}, {127490, 17318403}, {127491, 2},
2615
  {127504, 17168387}, {127505, 17990659}, {127506, 17990915}, {127507, 17362179},
2616
  {127508, 17153795}, {127509, 17991171}, {127510, 17991427}, {127511, 17235971},
2617
  {127512, 17991683}, {127513, 17991939}, {127514, 17992195}, {127515, 17596931},
2618
  {127516, 17992451}, {127517, 17992707}, {127518, 17992963}, {127519, 17993219},
2619
  {127520, 17993475}, {127521, 17993731}, {127522, 17177603}, {127523, 17993987},
2620
  {127524, 17994243}, {127525, 17994499}, {127526, 17994755}, {127527, 17995011},
2621
  {127528, 17995267}, {127529, 17152259}, {127530, 17233923}, {127531, 17995523},
2622
  {127532, 17299203}, {127533, 17234691}, {127534, 17299459}, {127535, 17995779},
2623
  {127536, 17191939}, {127537, 17996035}, {127538, 17996291}, {127539, 17996547},
2624
  {127540, 17996803}, {127541, 17997059}, {127542, 17274883}, {127543, 17170947},
2625
  {127544, 17997315}, {127545, 17997571}, {127546, 17997827}, {127547, 17998083},
2626
  {127548, 2}, {127552, 51552771}, {127553, 51553539}, {127554, 51554307},
2627
  {127555, 51555075}, {127556, 51555843}, {127557, 51556611}, {127558, 51557379},
2628
  {127559, 51558147}, {127560, 51558915}, {127561, 2}, {127568, 18005251},
2629
  {127569, 18005507}, {127570, 2}, {127584, 1}, {127590, 2},
2630
  {127744, 1}, {128729, 2}, {128732, 1}, {128749, 2},
2631
  {128752, 1}, {128765, 2}, {128768, 1}, {128986, 2},
2632
  {128992, 1}, {129004, 2}, {129008, 1}, {129009, 2},
2633
  {129024, 1}, {129036, 2}, {129040, 1}, {129096, 2},
2634
  {129104, 1}, {129114, 2}, {129120, 1}, {129160, 2},
2635
  {129168, 1}, {129198, 2}, {129200, 1}, {129212, 2},
2636
  {129216, 1}, {129218, 2}, {129232, 1}, {129241, 2},
2637
  {129280, 1}, {129624, 2}, {129632, 1}, {129646, 2},
2638
  {129648, 1}, {129661, 2}, {129664, 1}, {129675, 2},
2639
  {129678, 1}, {129735, 2}, {129736, 1}, {129737, 2},
2640
  {129741, 1}, {129757, 2}, {129759, 1}, {129771, 2},
2641
  {129775, 1}, {129785, 2}, {129792, 1}, {129939, 2},
2642
  {129940, 1}, {130032, 17045507}, {130033, 16786947}, {130034, 16785155},
2643
  {130035, 16785411}, {130036, 16787715}, {130037, 17045763}, {130038, 17046019},
2644
  {130039, 17046275}, {130040, 17046531}, {130041, 17046787}, {130042, 1},
2645
  {130043, 2}, {131072, 1}, {173792, 2}, {173824, 1},
2646
  {178206, 2}, {178208, 1}, {183982, 2}, {183984, 1},
2647
  {191457, 2}, {191472, 1}, {192094, 2}, {194560, 18005763},
2648
  {194561, 18006019}, {194562, 18006275}, {194563, 18006531}, {194564, 18006787},
2649
  {194565, 17620739}, {194566, 18007043}, {194567, 18007299}, {194568, 18007555},
2650
  {194569, 18007811}, {194570, 17620995}, {194571, 18008067}, {194572, 18008323},
2651
  {194573, 18008579}, {194574, 17621251}, {194575, 18008835}, {194576, 18009091},
2652
  {194577, 18009347}, {194578, 18009603}, {194579, 18009859}, {194580, 18010115},
2653
  {194581, 17992963}, {194582, 18010371}, {194583, 18010627}, {194584, 18010883},
2654
  {194585, 18011139}, {194586, 18011395}, {194587, 17635331}, {194588, 18011651},
2655
  {194589, 17156355}, {194590, 18011907}, {194591, 18012163}, {194592, 18012419},
2656
  {194593, 18012675}, {194594, 17997571}, {194595, 18012931}, {194596, 18013187},
2657
  {194597, 17636611}, {194598, 17621507}, {194599, 17621763}, {194600, 17636867},
2658
  {194601, 18013443}, {194602, 18013699}, {194603, 17575171}, {194604, 18013955},
2659
  {194605, 17622019}, {194606, 18014211}, {194607, 18014467}, {194608, 18014723},
2660
  {194609, 18014979}, {194612, 18015235}, {194613, 18015491}, {194614, 18015747},
2661
  {194615, 18016003}, {194616, 18016259}, {194617, 18016515}, {194618, 18016771},
2662
  {194619, 18017027}, {194620, 18017283}, {194621, 18017539}, {194622, 18017795},
2663
  {194623, 18018051}, {194624, 18018307}, {194625, 18018563}, {194626, 18018819},
2664
  {194627, 18019075}, {194628, 18019331}, {194629, 18019587}, {194631, 17637379},
2665
  {194632, 18019843}, {194633, 18020099}, {194634, 18020355}, {194635, 18020611},
2666
  {194636, 17622531}, {194637, 18020867}, {194638, 18021123}, {194639, 18021379},
2667
  {194640, 17612291}, {194641, 18021635}, {194642, 18021891}, {194643, 18022147},
2668
  {194644, 18022403}, {194645, 18022659}, {194646, 18022915}, {194647, 18023171},
2669
  {194648, 18023427}, {194649, 18023683}, {194650, 18023939}, {194651, 18024195},
2670
  {194652, 18024451}, {194653, 17991171}, {194654, 18024707}, {194655, 18024963},
2671
  {194656, 18025219}, {194657, 18025475}, {194658, 18025731}, {194659, 18025987},
2672
  {194660, 18026243}, {194661, 18026499}, {194662, 18026755}, {194663, 18027011},
2673
  {194664, 18027267}, {194665, 18027523}, {194666, 18027779}, {194668, 18028035},
2674
  {194669, 18028291}, {194670, 18028547}, {194671, 17574147}, {194672, 18028803},
2675
  {194673, 18029059}, {194674, 18029315}, {194675, 18029571}, {194676, 18029827},
2676
  {194677, 17163011}, {194678, 18030083}, {194679, 18030339}, {194680, 17163523},
2677
  {194681, 18030595}, {194682, 18030851}, {194683, 18031107}, {194684, 18031363},
2678
  {194685, 18031619}, {194686, 18031875}, {194687, 18032131}, {194688, 18032387},
2679
  {194689, 18032643}, {194690, 18032899}, {194691, 18033155}, {194692, 18033411},
2680
  {194693, 18033667}, {194694, 18033923}, {194695, 18034179}, {194696, 18034435},
2681
  {194697, 18034691}, {194698, 18034947}, {194699, 18035203}, {194700, 18035459},
2682
  {194701, 18035715}, {194702, 17560835}, {194703, 18035971}, {194704, 17166083},
2683
  {194705, 18036227}, {194707, 18036483}, {194708, 18036739}, {194710, 18036995},
2684
  {194711, 18037251}, {194712, 18037507}, {194713, 18037763}, {194714, 18038019},
2685
  {194715, 18038275}, {194716, 18038531}, {194717, 18038787}, {194718, 18039043},
2686
  {194719, 18039299}, {194720, 18039555}, {194721, 18039811}, {194722, 18040067},
2687
  {194723, 17623811}, {194724, 18040323}, {194725, 18040579}, {194726, 18040835},
2688
  {194727, 18041091}, {194728, 17640451}, {194729, 18041091}, {194730, 18041347},
2689
  {194731, 17624323}, {194732, 18041603}, {194733, 18041859}, {194734, 18042115},
2690
  {194735, 18042371}, {194736, 17624579}, {194737, 17553923}, {194738, 17425411},
2691
  {194739, 18042627}, {194740, 18042883}, {194741, 18043139}, {194742, 18043395},
2692
  {194743, 18043651}, {194744, 18043907}, {194745, 18044163}, {194746, 18044419},
2693
  {194747, 18044675}, {194748, 18044931}, {194749, 18045187}, {194750, 18045443},
2694
  {194751, 18045699}, {194752, 18045955}, {194753, 18046211}, {194754, 18046467},
2695
  {194755, 18046723}, {194756, 18046979}, {194757, 18047235}, {194758, 18047491},
2696
  {194759, 18047747}, {194760, 17624835}, {194761, 18048003}, {194762, 18048259},
2697
  {194763, 18048515}, {194764, 18048771}, {194765, 18049027}, {194766, 18049283},
2698
  {194767, 17625347}, {194768, 18049539}, {194769, 18049795}, {194770, 18050051},
2699
  {194771, 18050307}, {194772, 18050563}, {194773, 18050819}, {194774, 18051075},
2700
  {194775, 18051331}, {194776, 17561091}, {194777, 17642499}, {194778, 18051587},
2701
  {194779, 18051843}, {194780, 18052099}, {194781, 18052355}, {194782, 18052611},
2702
  {194783, 18052867}, {194784, 18053123}, {194785, 18053379}, {194786, 17625603},
2703
  {194787, 18053635}, {194788, 18053891}, {194789, 18054147}, {194790, 18054403},
2704
  {194791, 17653251}, {194792, 18054659}, {194793, 18054915}, {194794, 18055171},
2705
  {194795, 18055427}, {194796, 18055683}, {194797, 18055939}, {194798, 18056195},
2706
  {194799, 18056451}, {194800, 18056707}, {194801, 18056963}, {194802, 18057219},
2707
  {194803, 18057475}, {194804, 18057731}, {194805, 17578499}, {194806, 18057987},
2708
  {194807, 18058243}, {194808, 18058499}, {194809, 18058755}, {194810, 18059011},
2709
  {194811, 18059267}, {194812, 18059523}, {194813, 18059779}, {194814, 18060035},
2710
  {194815, 18060291}, {194816, 18060547}, {194817, 17625859}, {194818, 17599491},
2711
  {194819, 18060803}, {194820, 18061059}, {194821, 18061315}, {194822, 18061571},
2712
  {194823, 18061827}, {194824, 18062083}, {194825, 18062339}, {194826, 18062595},
2713
  {194827, 17643267}, {194828, 18062851}, {194829, 18063107}, {194830, 18063363},
2714
  {194831, 18063619}, {194832, 18063875}, {194833, 18064131}, {194834, 18064387},
2715
  {194835, 18064643}, {194836, 17643523}, {194837, 18064899}, {194838, 18065155},
2716
  {194839, 18065411}, {194840, 18065667}, {194841, 18065923}, {194842, 18066179},
2717
  {194843, 18066435}, {194844, 18066691}, {194845, 18066947}, {194846, 18067203},
2718
  {194847, 18067459}, {194848, 18067715}, {194849, 17644035}, {194850, 18067971},
2719
  {194851, 18068227}, {194852, 18068483}, {194853, 18068739}, {194854, 18068995},
2720
  {194855, 18069251}, {194856, 18069507}, {194857, 18069763}, {194858, 18070019},
2721
  {194859, 18070275}, {194860, 18070531}, {194862, 18070787}, {194863, 18071043},
2722
  {194864, 17644547}, {194865, 18071299}, {194866, 18071555}, {194867, 18071811},
2723
  {194868, 18072067}, {194869, 18072323}, {194870, 18072579}, {194871, 18072835},
2724
  {194872, 17574915}, {194873, 18073091}, {194874, 18073347}, {194875, 18073603},
2725
  {194876, 18073859}, {194877, 18074115}, {194878, 18074371}, {194879, 18074627},
2726
  {194880, 17646083}, {194881, 18074883}, {194882, 18075139}, {194883, 18075395},
2727
  {194884, 18075651}, {194885, 18075907}, {194886, 18076163}, {194888, 17646339},
2728
  {194889, 17653763}, {194890, 18076419}, {194891, 18076675}, {194892, 18076931},
2729
  {194893, 18077187}, {194894, 18077443}, {194895, 17565443}, {194896, 17646851},
2730
  {194897, 18077699}, {194898, 18077955}, {194899, 17628419}, {194900, 18078211},
2731
  {194901, 18078467}, {194902, 17617411}, {194903, 18078723}, {194904, 18078979},
2732
  {194905, 17629187}, {194906, 18079235}, {194907, 18079491}, {194908, 18079747},
2733
  {194909, 18080003}, {194911, 18080259}, {194912, 18080515}, {194913, 18080771},
2734
  {194914, 18081027}, {194915, 18081283}, {194916, 18081539}, {194917, 18081795},
2735
  {194918, 18082051}, {194919, 18082307}, {194920, 18082563}, {194921, 18082819},
2736
  {194922, 18083075}, {194923, 18083331}, {194924, 18083587}, {194925, 18083843},
2737
  {194926, 18084099}, {194927, 18084355}, {194928, 18084611}, {194929, 18084867},
2738
  {194930, 18085123}, {194931, 18085379}, {194932, 18085635}, {194933, 18085891},
2739
  {194934, 18086147}, {194935, 18086403}, {194936, 18086659}, {194937, 18086915},
2740
  {194938, 17630723}, {194939, 18087171}, {194940, 18087427}, {194941, 18087683},
2741
  {194942, 18087939}, {194943, 18088195}, {194944, 18088451}, {194945, 18088707},
2742
  {194946, 18088963}, {194947, 18089219}, {194948, 18089475}, {194949, 18089731},
2743
  {194950, 18089987}, {194951, 18090243}, {194952, 18090499}, {194953, 18090755},
2744
  {194954, 18091011}, {194955, 18036483}, {194956, 18091267}, {194957, 18091523},
2745
  {194958, 18091779}, {194959, 18092035}, {194960, 18092291}, {194961, 18092547},
2746
  {194962, 18092803}, {194963, 18093059}, {194964, 18093315}, {194965, 18093571},
2747
  {194966, 18093827}, {194967, 18094083}, {194968, 17579267}, {194969, 18094339},
2748
  {194970, 18094595}, {194971, 18094851}, {194972, 18095107}, {194973, 18095363},
2749
  {194974, 18095619}, {194975, 17631491}, {194976, 18095875}, {194977, 18096131},
2750
  {194978, 18096387}, {194979, 18096643}, {194980, 18096899}, {194981, 18097155},
2751
  {194982, 18097411}, {194983, 18097667}, {194984, 18097923}, {194985, 18098179},
2752
  {194986, 18098435}, {194987, 18098691}, {194988, 18098947}, {194989, 18099203},
2753
  {194990, 18099459}, {194991, 18099715}, {194992, 18099971}, {194993, 18100227},
2754
  {194994, 18100483}, {194995, 18100739}, {194996, 17564163}, {194997, 18100995},
2755
  {194998, 18101251}, {194999, 18101507}, {195000, 18101763}, {195001, 18102019},
2756
  {195002, 18102275}, {195003, 17648643}, {195004, 18102531}, {195005, 18102787},
2757
  {195006, 18103043}, {195007, 18103299}, {195008, 18103555}, {195009, 18103811},
2758
  {195010, 18104067}, {195011, 18104323}, {195012, 17189123}, {195013, 18104579},
2759
  {195014, 18104835}, {195015, 18105091}, {195016, 18105347}, {195017, 18105603},
2760
  {195018, 18105859}, {195019, 18106115}, {195020, 18106371}, {195021, 18106627},
2761
  {195022, 18106883}, {195023, 18107139}, {195024, 17649923}, {195025, 17650179},
2762
  {195026, 17190915}, {195027, 18107395}, {195028, 18107651}, {195029, 18107907},
2763
  {195030, 18108163}, {195031, 18108419}, {195032, 18108675}, {195033, 18108931},
2764
  {195034, 18109187}, {195035, 18109443}, {195036, 18109699}, {195037, 18109955},
2765
  {195038, 18110211}, {195039, 17650435}, {195040, 18110467}, {195041, 18110723},
2766
  {195042, 18110979}, {195043, 18111235}, {195044, 18111491}, {195045, 18111747},
2767
  {195046, 18112003}, {195047, 18112259}, {195048, 18112515}, {195049, 18112771},
2768
  {195050, 18113027}, {195051, 18113283}, {195052, 18113539}, {195053, 18113795},
2769
  {195054, 18114051}, {195055, 18114307}, {195056, 18114563}, {195057, 18114819},
2770
  {195058, 18115075}, {195059, 18115331}, {195060, 18115587}, {195061, 18115843},
2771
  {195062, 18116099}, {195063, 18116355}, {195064, 18116611}, {195065, 18116867},
2772
  {195066, 18117123}, {195067, 18117379}, {195068, 18117635}, {195069, 18117891},
2773
  {195070, 17651971}, {195072, 18118147}, {195073, 18118403}, {195074, 18118659},
2774
  {195075, 18118915}, {195076, 18119171}, {195077, 18119427}, {195078, 18119683},
2775
  {195079, 18119939}, {195080, 18120195}, {195081, 18120451}, {195082, 17652227},
2776
  {195083, 18120707}, {195084, 18120963}, {195085, 18121219}, {195086, 18121475},
2777
  {195087, 18121731}, {195088, 18121987}, {195089, 18122243}, {195090, 18122499},
2778
  {195091, 18122755}, {195092, 18123011}, {195093, 17203203}, {195094, 18123267},
2779
  {195095, 17204227}, {195096, 18123523}, {195097, 18123779}, {195098, 18124035},
2780
  {195099, 18124291}, {195100, 17205507}, {195101, 18124547}, {195102, 2},
2781
  {196608, 1}, {201547, 2}, {201552, 1}, {210042, 2},
2782
  {917760, 0}, {918000, 2}
2783
};
2784
2785
2786
} // namespace ada::idna
2787
#endif // ADA_IDNA_TABLES_H
2788
/* end file src/mapping_tables.cpp */
2789
2790
namespace ada::idna {
2791
2792
// This can be greatly accelerated. For now we just use a simply
2793
// binary search. In practice, you should *not* do that.
2794
64.2k
uint32_t find_range_index(uint32_t key) {
2795
  ////////////////
2796
  // This could be implemented with std::lower_bound, but we roll our own
2797
  // because we want to allow further optimizations in the future.
2798
  ////////////////
2799
64.2k
  uint32_t len = std::size(table);
2800
64.2k
  uint32_t low = 0;
2801
64.2k
  uint32_t high = len - 1;
2802
866k
  while (low <= high) {
2803
824k
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2804
824k
    uint32_t middle_value = table[middle_index][0];
2805
824k
    if (middle_value < key) {
2806
260k
      low = middle_index + 1;
2807
564k
    } else if (middle_value > key) {
2808
541k
      high = middle_index - 1;
2809
541k
    } else {
2810
22.2k
      return middle_index;  // perfect match
2811
22.2k
    }
2812
824k
  }
2813
41.9k
  return low == 0 ? 0 : low - 1;
2814
64.2k
}
2815
2816
1.20k
void ascii_map(char* input, size_t length) {
2817
3.60k
  auto broadcast = [](uint8_t v) -> uint64_t {
2818
3.60k
    return 0x101010101010101ull * v;
2819
3.60k
  };
2820
1.20k
  uint64_t broadcast_80 = broadcast(0x80);
2821
1.20k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2822
1.20k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2823
1.20k
  size_t i = 0;
2824
2825
6.52k
  for (; i + 7 < length; i += 8) {
2826
5.32k
    uint64_t word{};
2827
5.32k
    memcpy(&word, input + i, sizeof(word));
2828
5.32k
    word ^=
2829
5.32k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2830
5.32k
    memcpy(input + i, &word, sizeof(word));
2831
5.32k
  }
2832
1.20k
  if (i < length) {
2833
958
    uint64_t word{};
2834
958
    memcpy(&word, input + i, length - i);
2835
958
    word ^=
2836
958
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2837
958
    memcpy(input + i, &word, length - i);
2838
958
  }
2839
1.20k
}
2840
2841
// Map the characters according to IDNA, returning the empty string on error.
2842
5.13k
std::u32string map(std::u32string_view input) {
2843
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2844
  //  For each code point in the domain_name string, look up the status
2845
  //  value in Section 5, [IDNA Mapping
2846
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2847
  //  and take the following actions:
2848
  //    * disallowed: Leave the code point unchanged in the string, and
2849
  //    record that there was an error.
2850
  //    * ignored: Remove the code point from the string. This is
2851
  //    equivalent to mapping the code point to an empty string.
2852
  //    * mapped: Replace the code point in the string by the value for
2853
  //    the mapping in Section 5, [IDNA Mapping
2854
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2855
  //    * valid: Leave the code point unchanged in the string.
2856
5.13k
  static std::u32string error = U"";
2857
5.13k
  std::u32string answer;
2858
5.13k
  answer.reserve(input.size());
2859
64.2k
  for (char32_t x : input) {
2860
64.2k
    size_t index = find_range_index(x);
2861
64.2k
    uint32_t descriptor = table[index][1];
2862
64.2k
    uint8_t code = uint8_t(descriptor);
2863
64.2k
    switch (code) {
2864
532
      case 0:
2865
532
        break;  // nothing to do, ignored
2866
46.2k
      case 1:
2867
46.2k
        answer.push_back(x);  // valid, we just copy it to output
2868
46.2k
        break;
2869
414
      case 2:
2870
414
        return error;  // disallowed
2871
      // case 3 :
2872
17.0k
      default:
2873
        // We have a mapping
2874
17.0k
        {
2875
17.0k
          size_t char_count = (descriptor >> 24);
2876
17.0k
          uint16_t char_index = uint16_t(descriptor >> 8);
2877
172k
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2878
155k
            answer.push_back(mappings[idx]);
2879
155k
          }
2880
17.0k
        }
2881
64.2k
    }
2882
64.2k
  }
2883
4.72k
  return answer;
2884
5.13k
}
2885
}  // namespace ada::idna
2886
/* end file src/mapping.cpp */
2887
/* begin file src/normalization.cpp */
2888
/* begin file src/normalization_tables.cpp */
2889
// IDNA  17.0.0
2890
2891
// clang-format off
2892
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2893
#define ADA_IDNA_NORMALIZATION_TABLES_H
2894
#include <cstdint>
2895
2896
/**
2897
 * Unicode Standard Annex #15
2898
 *
2899
 * UNICODE NORMALIZATION FORMS
2900
 * https://www.unicode.org/reports/tr15/
2901
 *
2902
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2903
 */
2904
2905
namespace ada::idna {
2906
2907
const uint8_t decomposition_index[4352] = {
2908
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2910
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 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,  34, 35, 7,  7,  7,
2917
    36, 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,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2922
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 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,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2933
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2934
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 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
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3101
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3102
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3103
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3104
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3105
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3106
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3107
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3108
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3109
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3110
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3111
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3112
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3113
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3114
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3115
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3116
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3117
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3118
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3119
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3120
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3121
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3122
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3123
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3124
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3125
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3126
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3127
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3128
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3129
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3130
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3131
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3132
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3133
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3134
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3135
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3136
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3137
    7};
3138
3139
const uint16_t decomposition_block[67][257] = {
3140
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3141
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3142
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3143
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3144
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3145
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3146
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3147
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3148
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3149
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3150
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3151
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3152
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3153
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3154
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3155
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3156
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3157
     516, 524},
3158
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3159
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3160
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3161
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3162
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3163
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3164
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3165
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3166
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3167
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3168
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3169
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3170
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3171
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3172
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3173
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3174
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3175
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3176
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3177
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3178
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3179
     1948, 1956, 1964, 1972, 1980},
3180
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3181
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3182
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3183
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3184
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3185
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3186
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3187
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3188
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3189
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3190
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3191
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3192
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3193
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3194
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3195
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3196
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3197
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3198
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3199
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3200
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3201
     2460, 2460, 2460, 2460, 2460},
3202
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3203
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3204
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3205
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3206
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3207
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3208
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3209
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3210
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3211
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3212
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3213
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3214
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3215
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3216
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3217
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3218
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3219
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3220
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3221
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3222
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3223
     2744, 2744, 2744, 2744, 2744},
3224
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3225
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3226
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3227
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3228
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3229
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3230
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3231
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3232
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3233
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3234
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3235
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3236
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3237
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3238
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3239
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3240
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3241
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3242
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3243
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3244
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3245
     3160, 3160, 3160, 3160, 3160},
3246
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3247
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3248
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3249
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3250
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3251
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3252
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3253
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3254
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3255
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3256
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3257
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3258
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3259
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3260
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3261
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3262
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3263
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3264
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3265
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3266
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3267
     3168, 3168, 3168, 3168, 3168},
3268
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3269
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3270
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3271
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3272
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3273
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3274
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3275
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3276
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3277
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3278
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3279
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3280
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3281
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3282
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3283
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3284
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3285
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3286
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3287
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3288
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3289
     3264, 3264, 3264, 3264, 3264},
3290
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3291
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3292
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3293
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3294
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3295
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3296
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3297
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3298
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3299
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3300
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3301
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3302
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3303
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3304
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3305
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3306
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3307
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3308
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3309
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3310
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3311
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3312
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3313
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3314
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3315
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3316
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3317
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3318
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3319
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3320
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3321
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3322
     3392, 3392, 3392, 3392, 3392},
3323
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3324
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3325
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3326
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3327
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3328
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3329
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3330
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3331
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3332
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3333
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3334
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3335
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3336
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3337
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3338
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3339
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3340
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3341
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3342
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3343
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3344
     3440, 3440, 3440, 3440, 3440},
3345
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3346
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3347
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3348
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3349
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3350
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3351
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3352
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3353
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3354
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3355
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3356
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3357
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3358
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3359
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3360
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3361
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3362
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3363
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3364
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3365
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3366
     3512, 3512, 3512, 3512, 3512},
3367
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3368
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3369
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3370
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3371
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3372
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3373
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3374
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3375
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3376
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3377
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3378
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3379
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3380
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3381
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3382
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3383
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3384
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3385
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3386
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3387
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3388
     3564, 3564, 3564, 3564, 3564},
3389
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3390
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3391
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3392
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3393
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3394
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3395
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3396
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3397
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3398
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3399
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3400
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3401
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3402
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3403
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3404
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3405
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3406
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3407
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3408
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3409
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3410
     3624, 3624, 3624, 3624, 3624},
3411
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3412
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3413
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3414
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3415
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3416
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3417
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3418
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3419
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3420
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3421
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3422
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3423
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3424
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3425
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3426
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3427
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3428
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3429
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3430
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3431
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3432
     3656, 3656, 3656, 3656, 3656},
3433
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3434
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3435
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3436
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3437
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3438
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3439
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3440
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3441
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3442
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3443
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3444
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3445
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3446
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3447
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3448
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3449
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3450
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3451
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3452
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3453
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3454
     3820, 3820, 3820, 3820, 3820},
3455
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3456
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3457
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3458
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3459
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3460
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3461
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3462
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3463
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3464
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3465
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3466
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3467
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3468
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3469
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3470
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3471
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3472
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3473
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3474
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3475
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3476
     3829, 3832, 3832, 3832, 3832},
3477
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3478
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3479
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3480
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3481
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3482
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3483
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3484
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3485
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3486
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3487
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3488
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3489
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3490
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3491
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3492
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3493
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3494
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3495
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3496
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3497
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3498
     3920, 3920, 3920, 3920, 3920},
3499
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3500
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3501
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3502
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3503
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3504
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3505
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3506
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3507
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3508
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3509
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3510
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3511
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3512
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3513
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3514
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3515
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3516
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3517
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3518
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3519
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3520
     4312, 4312, 4312, 4312, 4312},
3521
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3522
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3523
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3524
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3525
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3526
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3527
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3528
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3529
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3530
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3531
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3532
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3533
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3534
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3535
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3536
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3537
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3538
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3539
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3540
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3541
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3542
     6648, 6648, 6648, 6648, 6648},
3543
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3544
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3545
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3546
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3547
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3548
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3549
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3550
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3551
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3552
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3553
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3554
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3555
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3556
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3557
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3558
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3559
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3560
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3561
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3562
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3563
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3564
     9168, 9178, 9181, 9188, 9190},
3565
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3566
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3567
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3568
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3569
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3570
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3571
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3572
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3573
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3574
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3575
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3576
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3577
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3578
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3579
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3580
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3581
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3582
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3583
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3584
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3585
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3586
     9548, 9548, 9548, 9548, 9549},
3587
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3588
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3589
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3590
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3591
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3592
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3593
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3594
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3595
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3596
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3597
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3598
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3599
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3600
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3601
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3602
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3603
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3604
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3605
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3606
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3607
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3608
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3609
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3610
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3611
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3612
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3613
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3614
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3615
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3616
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3617
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3618
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3619
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3620
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3621
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3622
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3623
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3624
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3625
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3626
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3627
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3628
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3629
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3630
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3631
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3632
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3633
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3634
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3635
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3636
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3637
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3638
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3639
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3640
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3641
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3642
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3643
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3644
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3645
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3646
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3647
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3648
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3649
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3650
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3651
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3652
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3653
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3654
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3655
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3656
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3657
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3658
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3659
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3660
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3661
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3662
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3663
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3664
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3665
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3666
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3667
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3668
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3669
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3670
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3671
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3672
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3673
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3674
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3675
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3676
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3677
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3678
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3679
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3680
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3681
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3682
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3683
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3684
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3685
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3686
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3687
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3688
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3689
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3690
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3691
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3692
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3693
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3694
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3695
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3696
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3697
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3698
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3699
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3700
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3701
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3702
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3703
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3704
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3705
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3706
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3707
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3708
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3709
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3710
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3711
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3712
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3713
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3714
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3715
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3716
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3717
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3718
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3719
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3720
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3721
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3722
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3723
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3724
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3725
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3726
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3727
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3728
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3729
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3730
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3731
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3732
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3733
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3734
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3735
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3736
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3737
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3738
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3739
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3740
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3741
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3742
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3743
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3744
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3745
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3746
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3747
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3748
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3749
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3750
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3751
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3752
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3753
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3754
     11888, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3755
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3756
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3757
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3758
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3759
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3760
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3761
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3762
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3763
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3764
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3765
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3766
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3767
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3768
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3769
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3770
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3771
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3772
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3773
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3774
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3775
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3776
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3777
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3778
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3779
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3780
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3781
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3782
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3783
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3784
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3785
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3786
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3787
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3788
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3789
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3790
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3791
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3792
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3793
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3794
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3795
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3796
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3797
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3798
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3799
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3800
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3801
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3802
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3803
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3804
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3805
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3806
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3807
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3808
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3809
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3810
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3811
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3812
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3813
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3814
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3815
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3816
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3817
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3818
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3819
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3820
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3821
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3822
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3823
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3824
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3825
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3826
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3827
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3828
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3829
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3830
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3831
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3832
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3833
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3834
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3835
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3836
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3837
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3838
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3839
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3840
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3841
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3842
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3843
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3844
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3845
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3846
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3847
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3848
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3849
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3850
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3851
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3852
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3853
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3854
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3855
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3856
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3857
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3858
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3859
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3860
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3861
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3862
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3863
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3864
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3865
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3866
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3867
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3868
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3869
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3870
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3871
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3872
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3873
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3874
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3875
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3876
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3877
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3878
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3879
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3880
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3881
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3882
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3883
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3884
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3885
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3886
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3887
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3888
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3889
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3890
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3891
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3892
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3893
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3894
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3895
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3896
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3897
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3898
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3899
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3900
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3901
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3902
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3903
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3904
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3905
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3906
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3907
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3908
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3909
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3910
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3911
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3912
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3913
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3914
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3915
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3916
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3917
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3918
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3919
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3920
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3921
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3922
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3923
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3924
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3925
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3926
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3927
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3928
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3929
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3930
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3931
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3932
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3933
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3934
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3935
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3936
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3937
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3938
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3939
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3940
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3941
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3942
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3943
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3944
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3945
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3946
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3947
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3948
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3949
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3950
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3951
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3952
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3953
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3954
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3955
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3956
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3957
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3958
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3959
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3960
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3961
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3962
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3963
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3964
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3965
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3966
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3967
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3968
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3969
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3970
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3971
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3972
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3973
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3974
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3975
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3976
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3977
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3978
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3979
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3980
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3981
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3982
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3983
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3984
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3985
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3986
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3987
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3988
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3989
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3990
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3991
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3992
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3993
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3994
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3995
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3996
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3997
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3998
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3999
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4000
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4001
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4002
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
4003
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
4004
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
4005
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
4006
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
4007
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
4008
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
4009
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
4010
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
4011
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
4012
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
4013
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
4014
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4015
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4016
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4017
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4018
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4019
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4020
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4021
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4022
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4023
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4024
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4025
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4026
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4027
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4028
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4029
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4030
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4031
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4032
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4033
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4034
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4035
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4036
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4037
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4038
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4039
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4040
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4041
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4042
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4043
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4044
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4045
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4046
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4047
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4048
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4049
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4050
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4051
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4052
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4053
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4054
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4055
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4056
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4057
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4058
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4059
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4060
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4061
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4062
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4063
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4064
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4065
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4066
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4067
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4068
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4069
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4070
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4071
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4072
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4073
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4074
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4075
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4076
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4077
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4078
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4079
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4080
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4081
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4082
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4083
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4084
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4085
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4086
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4087
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4088
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4089
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4090
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4091
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4092
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4093
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4094
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4095
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4096
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4097
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4098
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4099
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4100
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4101
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4102
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4103
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4104
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4105
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4106
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4107
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4108
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4109
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4110
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4111
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4112
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4113
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4114
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4115
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4116
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4117
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4118
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4119
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4120
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4121
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4122
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4123
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4124
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4125
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4126
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4127
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4128
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4129
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4130
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4131
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4132
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4133
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4134
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4135
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4136
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4137
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4138
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4139
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4140
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4141
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4142
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4143
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4144
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4145
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4146
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4147
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4148
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4149
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4150
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4151
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4152
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4153
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4154
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4155
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4156
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4157
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4158
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4159
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4160
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4161
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4162
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4163
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4164
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4165
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4166
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4167
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4168
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4169
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4170
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4171
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4172
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4173
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4174
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4175
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4176
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4177
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4178
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4179
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4180
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4181
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4182
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4183
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4184
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4185
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4186
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4187
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4188
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4189
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4190
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4191
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4192
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4193
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4194
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4195
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4196
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4197
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4198
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4199
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4200
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4201
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4202
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4203
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4204
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4205
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4206
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4207
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4208
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4209
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4210
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4211
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4212
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4213
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4214
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4215
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4216
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4217
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4218
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4219
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4220
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4221
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4222
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4223
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4224
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4225
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4226
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4227
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4228
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4229
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4230
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4231
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4232
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4233
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4234
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4235
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4236
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4237
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4238
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4239
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4240
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4241
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4242
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4243
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4244
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4245
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4246
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4247
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4248
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4249
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4250
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4251
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4252
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4253
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4254
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4255
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4256
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4257
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4258
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4259
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4260
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4261
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4262
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4263
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4264
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4265
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4266
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4267
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4268
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4269
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4270
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4271
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4272
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4273
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4274
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4275
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4276
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4277
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4278
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4279
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4280
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4281
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4282
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4283
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4284
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4285
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4286
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4287
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4288
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4289
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4290
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4291
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4292
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4293
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4294
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4295
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4296
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4297
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4298
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4299
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4300
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4301
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4302
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4303
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4304
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4305
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4306
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4307
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4308
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4309
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4310
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4311
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4312
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4313
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4314
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4315
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4316
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4317
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4318
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4319
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4320
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4321
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4322
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4323
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4324
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4325
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4326
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4327
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4328
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4329
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4330
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4331
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4332
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4333
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4334
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4335
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4336
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4337
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4338
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4339
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4340
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4341
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4342
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4343
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4344
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4345
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4346
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4347
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4348
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4349
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4350
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4351
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4352
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4353
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4354
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4355
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4356
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4357
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4358
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4359
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4360
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4361
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4362
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4363
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4364
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4365
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4366
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4367
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4368
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4369
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4370
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4371
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4372
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4373
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4374
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4375
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4376
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4377
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4378
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4379
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4380
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4381
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4382
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4383
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4384
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4385
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4386
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4387
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4388
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4389
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4390
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4391
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4392
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4393
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4394
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4395
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4396
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4397
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4398
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4399
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4400
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4401
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4402
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4403
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4404
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4405
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4406
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4407
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4408
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4409
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4410
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4411
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4412
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4413
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4414
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4415
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4416
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4417
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4418
     28464, 28464, 28464, 28464, 28464, 28464, 28465},
4419
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4420
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4421
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4422
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4423
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4424
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4425
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4426
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4427
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4428
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4429
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4430
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4431
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4432
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4433
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4434
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4435
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4436
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4437
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4438
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4439
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4440
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4441
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4442
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4443
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4444
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4445
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4446
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4447
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4448
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4449
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4450
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4451
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4452
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4453
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4454
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4455
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4456
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4457
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4458
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4459
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4460
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4461
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4462
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4463
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4464
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4465
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4466
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4467
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4468
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4469
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4470
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4471
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4472
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4473
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4474
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4475
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4476
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4477
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4478
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4479
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4480
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4481
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4482
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4483
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4484
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4485
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4486
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4487
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4488
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4489
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4490
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4491
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4492
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4493
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4494
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4495
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4496
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4497
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4498
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4499
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4500
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4501
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4502
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4503
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4504
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4505
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4506
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4507
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4508
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4509
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4510
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4511
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4512
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4513
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4514
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4515
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4516
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4517
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4518
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4519
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4520
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4521
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4522
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4523
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4524
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4525
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4526
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4527
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4528
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4529
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4530
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4531
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4532
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4533
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4534
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4535
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4536
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4537
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4538
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4539
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4540
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4541
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4542
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4543
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4544
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4545
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4546
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4547
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4548
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4549
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4550
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4551
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4552
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4553
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4554
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4555
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4556
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4557
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4558
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4559
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4560
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4561
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4562
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4563
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4564
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4565
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4566
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4567
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4568
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4569
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4570
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4571
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4572
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4573
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4574
     32696, 32696, 32696, 32696, 32696, 32696, 32697},
4575
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4576
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4577
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4578
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4579
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4580
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4581
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4582
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4583
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4584
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4585
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4586
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4587
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4588
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4589
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4590
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4591
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4592
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4593
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4594
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4595
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4596
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4597
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4598
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4599
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4600
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4601
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4602
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4603
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4604
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4605
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4606
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4607
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4608
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4609
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4610
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4611
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4612
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4613
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4614
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4615
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4616
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4617
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4618
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4619
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4620
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4621
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4622
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4623
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4624
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4625
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4626
     33260, 33260, 33260, 33260, 33260, 33260, 33261},
4627
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4628
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4629
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4630
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4631
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4632
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4633
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4634
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4635
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4636
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4637
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4638
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4639
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4640
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4641
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4642
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4643
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4644
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4645
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4646
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4647
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4648
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4649
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4650
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4651
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4652
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4653
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4654
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4655
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4656
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4657
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4658
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4659
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4660
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4661
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4663
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4664
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4665
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4666
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4667
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4668
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4669
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4670
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4671
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4672
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4673
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4674
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4675
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4676
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4677
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4678
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4679
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4680
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4681
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4682
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4683
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4684
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4685
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4686
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4687
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4688
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4689
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4690
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4691
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4692
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4693
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4694
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4695
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4696
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4697
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4698
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4699
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4700
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4701
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4702
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4703
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4704
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4705
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4706
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4707
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4708
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4709
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4710
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4711
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4712
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4713
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4714
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4715
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4716
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4717
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4718
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4719
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4720
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4721
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4722
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4723
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4724
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4725
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4726
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4727
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4728
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4729
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4730
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4731
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4732
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4733
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4734
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4735
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4736
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4737
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4738
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4739
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4740
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4741
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4742
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4743
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4744
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4745
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4746
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4747
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4748
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4749
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4750
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4751
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4752
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4753
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4754
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4755
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4756
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4757
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4758
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4759
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4760
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4761
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4762
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4763
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4764
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4765
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4766
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4767
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4768
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4769
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4770
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4771
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4772
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4773
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4774
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4775
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4776
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4777
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4778
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4779
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4780
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4781
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4782
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4783
const char32_t decomposition_data[9102] = {
4784
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4785
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4786
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4787
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4788
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4789
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4790
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4791
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4792
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4793
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4794
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4795
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4796
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4797
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4798
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4799
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4800
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4801
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4802
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4803
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4804
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4805
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4806
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4807
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4808
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4809
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4810
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4811
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4812
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4813
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4814
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4815
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4816
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4817
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4818
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4819
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4820
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4821
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4822
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4823
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4824
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4825
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4826
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4827
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4828
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4829
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4830
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4831
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4832
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4833
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4834
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4835
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4836
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4837
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4838
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4839
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4840
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4841
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4842
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4843
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4844
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4845
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4846
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4847
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4848
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4849
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4850
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4851
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4852
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4853
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4854
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4855
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4856
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4857
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4858
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4859
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4860
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4861
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4862
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4863
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4864
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4865
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4866
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4867
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4868
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4869
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4870
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4871
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4872
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4873
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4874
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4875
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4876
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4877
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4878
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4879
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4880
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4881
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4882
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4883
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4884
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4885
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4886
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4887
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4888
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4889
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4890
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4891
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4892
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4893
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4894
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4895
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4896
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4897
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4898
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4899
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4900
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4901
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4902
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4903
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4904
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4905
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4906
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4907
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4908
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4909
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4910
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4911
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4912
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4913
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4914
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4915
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4916
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4917
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4918
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4919
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4920
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4921
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4922
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4923
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4924
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4925
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4926
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4927
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4928
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4929
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4930
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4931
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4932
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4933
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4934
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4935
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4936
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4937
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4938
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4939
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4940
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4941
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4942
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4943
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4944
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4945
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4946
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4947
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4948
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4949
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4950
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4951
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4952
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4953
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4954
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4955
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4956
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4957
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4958
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4959
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4960
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4961
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4962
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4963
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4964
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4965
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4966
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4967
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4968
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4969
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4970
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4971
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4972
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4973
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4974
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4975
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4976
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4977
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4978
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4979
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4980
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4981
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4982
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4983
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4984
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4985
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4986
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4987
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4988
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4989
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4990
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4991
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4992
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4993
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4994
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4995
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4996
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4997
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4998
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4999
    945,    768,    945,    769,    949,    768,    949,    769,    951,
5000
    768,    951,    769,    953,    768,    953,    769,    959,    768,
5001
    959,    769,    965,    768,    965,    769,    969,    768,    969,
5002
    769,    945,    787,    837,    945,    788,    837,    945,    787,
5003
    768,    837,    945,    788,    768,    837,    945,    787,    769,
5004
    837,    945,    788,    769,    837,    945,    787,    834,    837,
5005
    945,    788,    834,    837,    913,    787,    837,    913,    788,
5006
    837,    913,    787,    768,    837,    913,    788,    768,    837,
5007
    913,    787,    769,    837,    913,    788,    769,    837,    913,
5008
    787,    834,    837,    913,    788,    834,    837,    951,    787,
5009
    837,    951,    788,    837,    951,    787,    768,    837,    951,
5010
    788,    768,    837,    951,    787,    769,    837,    951,    788,
5011
    769,    837,    951,    787,    834,    837,    951,    788,    834,
5012
    837,    919,    787,    837,    919,    788,    837,    919,    787,
5013
    768,    837,    919,    788,    768,    837,    919,    787,    769,
5014
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5015
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5016
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5017
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5018
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5019
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5020
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5021
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5022
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5023
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5024
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5025
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5026
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5027
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5028
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5029
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5030
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5031
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5032
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5033
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5034
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5035
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5036
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5037
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5038
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5039
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5040
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5041
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5042
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5043
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5044
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5045
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5046
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5047
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5048
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5049
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5050
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5051
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5052
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5053
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5054
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5055
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5056
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5057
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5058
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5059
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5060
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5061
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5062
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5063
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5064
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5065
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5066
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5067
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5068
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5069
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5070
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5071
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5072
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5073
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5074
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5075
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5076
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5077
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5078
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5079
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5080
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5081
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5082
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5083
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5084
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5085
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5086
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5087
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5088
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5089
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5090
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5091
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5092
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5093
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5094
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5095
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5096
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5097
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5098
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5099
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5100
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5101
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5102
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5103
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5104
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5105
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5106
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5107
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5108
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5109
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5110
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5111
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5112
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5113
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5114
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5115
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5116
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5117
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5118
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5119
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5120
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5121
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5122
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5123
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5124
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5125
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5126
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5127
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5128
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5129
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5130
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5131
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5132
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5133
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5134
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5135
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5136
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5137
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5138
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5139
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5140
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5141
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5142
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5143
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5144
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5145
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5146
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5147
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5148
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5149
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5150
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5151
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5152
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5153
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5154
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5155
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5156
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5157
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5158
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5159
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5160
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5161
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5162
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5163
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5164
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5165
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5166
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5167
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5168
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5169
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5170
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5171
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5172
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5173
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5174
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5175
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5176
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5177
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5178
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5179
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5180
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5181
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5182
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5183
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5184
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5185
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5186
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5187
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5188
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5189
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5190
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5191
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5192
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5193
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5194
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5195
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5196
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5197
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5198
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5199
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5200
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5201
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5202
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5203
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5204
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5205
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5206
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5207
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5208
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5209
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5210
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5211
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5212
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5213
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5214
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5215
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5216
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5217
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5218
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5219
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5220
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5221
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5222
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5223
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5224
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5225
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5226
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5227
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5228
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5229
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5230
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5231
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5232
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5233
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5234
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5235
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5236
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5237
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5238
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5239
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5240
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5241
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5242
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5243
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5244
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5245
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5246
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5247
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5248
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5249
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5250
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5251
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5252
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5253
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5254
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5255
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5256
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5257
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5258
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5259
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5260
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5261
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5262
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5263
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5264
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5265
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5266
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5267
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5268
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5269
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5270
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5271
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5272
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5273
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5274
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5275
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5276
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5277
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5278
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5279
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5280
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5281
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5282
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5283
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5284
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5285
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5286
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5287
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5288
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5289
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5290
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5291
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5292
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5293
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5294
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5295
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5296
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5297
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5298
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5299
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5300
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5301
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5302
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5303
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5304
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5305
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5306
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5307
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5308
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5309
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5310
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5311
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5312
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5313
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5314
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5315
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5316
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5317
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5318
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5319
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5320
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5321
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5322
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5323
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5324
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5325
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5326
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5327
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5328
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5329
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5330
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5331
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5332
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5333
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5334
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5335
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5336
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5337
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5338
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5339
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5340
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5341
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5342
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5343
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5344
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5345
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5346
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5347
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5348
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5349
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5350
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5351
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5352
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5353
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5354
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5355
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5356
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5357
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5358
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5359
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5360
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5361
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5362
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5363
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5364
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5365
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5366
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5367
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5368
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5369
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5370
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5371
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5372
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5373
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5374
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5375
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5376
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5377
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5378
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5379
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5380
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5381
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5382
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5383
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5384
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5385
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5386
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5387
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5388
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5389
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5390
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5391
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5392
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5393
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5394
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5395
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5396
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5397
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5398
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5399
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5400
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5401
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5402
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5403
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5404
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5405
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5406
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5407
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5408
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5409
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5410
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5411
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5412
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5413
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5414
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5415
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5416
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5417
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5418
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5419
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5420
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5421
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5422
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5423
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5424
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5425
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5426
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5427
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5428
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5429
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5430
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5431
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5432
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5433
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5434
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5435
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5436
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5437
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5438
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5439
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5440
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5441
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5442
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5443
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5444
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5445
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5446
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5447
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5448
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5449
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5450
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5451
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5452
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5453
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5454
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5455
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5456
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5457
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5458
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5459
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5460
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5461
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5462
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5463
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5464
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5465
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5466
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5467
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5468
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5469
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5470
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5471
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5472
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5473
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5474
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5475
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5476
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5477
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5478
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5479
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5480
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5481
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5482
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5483
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5484
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5485
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5486
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5487
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5488
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5489
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5490
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5491
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5492
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5493
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5494
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5495
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5496
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5497
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5498
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5499
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5500
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5501
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5502
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5503
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5504
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5505
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5506
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5507
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5508
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5509
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5510
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5511
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5512
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5513
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5514
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5515
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5516
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5517
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5518
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5519
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5520
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5521
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5522
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5523
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5524
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5525
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5526
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5527
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5528
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5529
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5530
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5531
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5532
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5533
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5534
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5535
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5536
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5537
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5538
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5539
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5540
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5541
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5542
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5543
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5544
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5545
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5546
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5547
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5548
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5549
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5550
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5551
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5552
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5553
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5554
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5555
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5556
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5557
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5558
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5559
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5560
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5561
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5562
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5563
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5564
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5565
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5566
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5567
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5568
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5569
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5570
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5571
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5572
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5573
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5574
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5575
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5576
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5577
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5578
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5579
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5580
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5581
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5582
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5583
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5584
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5585
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5586
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5587
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5588
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5589
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5590
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5591
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5592
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5593
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5594
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5595
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5596
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5597
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5598
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5599
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5600
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5601
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5602
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5603
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5604
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5605
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5606
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5607
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5608
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5609
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5610
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5611
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5612
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5613
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5614
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5615
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5616
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5617
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5618
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5619
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5620
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5621
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5622
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5623
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5624
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5625
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5626
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5627
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5628
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5629
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5630
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5631
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5632
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5633
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5634
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5635
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5636
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5637
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5638
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5639
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5640
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5641
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5642
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5643
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5644
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5645
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5646
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5647
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5648
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5649
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5650
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5651
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5652
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5653
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5654
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5655
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5656
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5657
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5658
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5659
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5660
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5661
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5662
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5663
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5664
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5665
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5666
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5667
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5668
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5669
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5670
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5671
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5672
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5673
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5674
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5675
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5676
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5677
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5678
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5679
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5680
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5681
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5682
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5683
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5684
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5685
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5686
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5687
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5688
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5689
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5690
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5691
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5692
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5693
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5694
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5695
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5696
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5697
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5698
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5699
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5700
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5701
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5702
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5703
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5704
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5705
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5706
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5707
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5708
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5709
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5710
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5711
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5712
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5713
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5714
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5715
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5716
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5717
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5718
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5719
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5720
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5721
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5722
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5723
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5724
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5725
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5726
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5727
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5728
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5729
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5730
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5731
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5732
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5733
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5734
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5735
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5736
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5737
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5738
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5739
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5740
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5741
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5742
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5743
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5744
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5745
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5746
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5747
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5748
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5749
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5750
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5751
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5752
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5753
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5754
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5755
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5756
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5757
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5758
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5759
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5760
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5761
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5762
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5763
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5764
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5765
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5766
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5767
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5768
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5769
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5770
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5771
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5772
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5773
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5774
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5775
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5776
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5777
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5778
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5779
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5780
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5781
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5782
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5783
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5784
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5785
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5786
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5787
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5788
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5789
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5790
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5791
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5792
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5793
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5794
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5795
    40726,  40763,  173568};
5796
5797
const uint8_t canonical_combining_class_index[4352] = {
5798
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5799
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 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,  27, 0,  28, 29, 30,
5807
    31, 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,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5812
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5813
    53, 0,  54, 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,  55, 56, 0,  0,  0,  57, 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,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5824
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  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,
5992
    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,
5994
    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,
5996
    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,
5998
    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,
6000
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6001
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6002
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6003
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6004
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6005
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6006
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6007
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6008
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6009
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6011
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6013
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6015
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6017
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6018
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6019
    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,
6021
    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,
6023
    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,
6025
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6026
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6027
    0};
6028
const uint8_t canonical_combining_class_block[67][256] = {
6029
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6030
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6031
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6032
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 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, 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, 0},
6040
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6041
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6042
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6043
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6044
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6045
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6046
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6047
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6048
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6049
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6050
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6055
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6057
     0},
6058
    {0,   0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6060
     0,   0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6062
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6063
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6064
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6065
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6066
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6067
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6068
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 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},
6070
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6071
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6072
     0,   0,   0,   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,   220, 230, 230, 230, 230,
6080
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6081
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6082
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6083
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   0,   0,   0,   0,   0,   0,   0,   0,
6087
     0},
6088
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6089
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6090
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6091
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6094
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6095
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6096
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6098
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6099
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6100
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6101
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6102
     0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6103
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6105
     0},
6106
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6107
     0,   0,   36,  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,
6109
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6110
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6111
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6112
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6113
     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,   0,   0,   0,
6115
     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,
6117
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6118
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6119
     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,
6121
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6122
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6123
     0},
6124
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6125
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6126
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6127
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6128
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6129
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6130
     220, 220, 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,
6132
     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,
6134
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6135
     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,
6137
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6138
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6139
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6140
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6141
     230},
6142
    {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,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6145
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 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,
6147
     0, 0, 0, 0, 0, 0, 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,
6149
     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, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6151
     0, 0, 0, 0, 0, 0, 0, 9, 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,
6153
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6154
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157
     0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 7, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     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, 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, 0, 0, 0, 0, 0, 0,
6167
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, 0,
6173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6176
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6177
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6178
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6179
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 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,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6181
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6182
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6183
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6184
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  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,  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,  0},
6187
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6188
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6190
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6191
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6192
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
6198
    {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,
6200
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6201
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6202
     107, 107, 107, 107, 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,
6204
     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,
6206
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6207
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6208
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6209
     0,   0,   122, 122, 122, 122, 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,
6211
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6212
     0,   0,   0,   0},
6213
    {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,   220, 220, 0,   0,   0, 0,
6215
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6216
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6217
     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,
6219
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6220
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6221
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6222
     230, 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,
6224
     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,
6226
     0,   0, 0,   220, 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,
6228
     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,
6230
     0},
6231
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6232
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6233
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 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, 0, 0, 0, 0, 0, 220, 0, 0,
6237
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6238
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6239
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   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,   0, 0,
6241
     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, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6247
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6249
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6250
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6251
     0, 0, 0, 0, 0, 0,   0,   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, 0, 0, 0, 0, 0, 0, 0,
6253
     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, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6255
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6256
     0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6258
     0, 0, 0, 0, 0, 0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6260
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6261
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6262
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 230, 0, 0, 0, 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, 0},
6265
    {0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6266
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6267
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
6269
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6270
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
6272
     0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6273
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0,
6275
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6276
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6277
     0, 0, 0, 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, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6279
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6280
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6282
     0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6284
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6285
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6286
     0, 0, 0, 0, 0, 0, 0, 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},
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,   230, 220, 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,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6296
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6297
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6298
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6299
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6300
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6301
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 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},
6306
    {0,   0,   0, 0, 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,   0,   0,   0,   0,
6308
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6309
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6310
     0,   0,   0, 0, 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, 220, 230, 230, 230, 230, 230,
6312
     230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6313
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6314
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6315
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6316
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6317
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6318
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6319
     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,
6321
     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,
6323
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6324
     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,
6326
     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,
6328
     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,
6330
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6331
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6332
     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,   230, 230,
6334
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6335
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6336
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6337
     0},
6338
    {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,
6340
     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,
6342
     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,
6344
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6345
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   230, 230, 220,
6351
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6352
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6353
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6354
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6355
     220},
6356
    {0,   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,   0,
6358
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6359
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6360
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6361
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6362
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6363
     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,
6365
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6366
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6367
     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,
6369
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6370
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6371
     230, 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,   0,   0,
6373
     0, 0, 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,   0,   0,
6375
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6376
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6377
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,   0,   0,
6379
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,   0,   0,
6381
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6382
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6383
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6384
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6385
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6386
     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,
6388
     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,
6390
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6391
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6392
     0,   0,   0,   0,   0,   0,   0,   9,   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,   0,
6395
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6396
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230,
6399
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6400
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6401
     230},
6402
    {0, 0, 0,   0,   0,   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, 0, 0, 0, 0, 0,
6404
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6405
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6406
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6407
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6408
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6409
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
6410
     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,
6412
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6413
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6414
     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,
6416
     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,
6418
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6419
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6420
     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,   0,   230,
6422
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6423
     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,   230, 230,
6425
     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,
6427
     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,
6429
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6430
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6431
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6432
     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,   9,
6434
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6435
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6436
     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,
6438
     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,
6440
     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,
6442
     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,
6444
     0,   9,   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,   230,
6446
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6447
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6448
     0},
6449
    {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, 220,
6451
     220, 220, 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, 9, 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,
6454
     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,
6456
     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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6458
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6459
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6460
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6461
    {0,   0,   0, 0,   0, 0,   0, 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, 0, 0, 0, 0,
6463
     0,   0,   0, 0,   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, 0, 0, 0, 0,
6465
     0,   0,   0, 0,   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, 0, 0, 0, 0,
6467
     0,   0,   0, 0,   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, 0, 0, 0, 0,
6469
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6470
     0,   0,   0, 0,   0, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6471
     230, 230, 0, 230, 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, 0, 0, 0, 0,
6473
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6474
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6475
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6476
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0,
6485
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6486
    {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6487
     0, 0, 0, 0, 0, 0, 26, 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, 0, 0, 0, 0, 0, 0, 0, 0},
6497
    {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,
6499
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6500
     220, 230, 230, 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,
6502
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6503
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6504
     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,
6506
     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,
6508
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6509
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6510
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6511
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6512
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6513
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6514
     0},
6515
    {0, 0, 0, 0, 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, 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, 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, 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, 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, 0, 0, 0, 0,
6521
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6522
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 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, 0, 0,
6524
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6525
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0,
6534
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 220, 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},
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, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6543
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6544
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 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,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6547
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6549
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6550
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6551
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6552
     0, 0, 0, 9, 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, 0,   0,
6554
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6555
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6556
     0, 0, 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, 0,   0,
6558
     0, 0, 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, 0,   0,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6561
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6562
    {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, 230, 230, 230, 230, 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,
6565
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6567
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6568
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6570
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6571
     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,   0,   0,   0, 0, 0, 0,
6573
     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, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6576
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6577
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6578
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6579
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6580
     0, 0, 0, 0, 0, 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, 0, 230, 230, 0, 0, 0,
6582
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6583
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6584
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6585
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6586
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6587
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6588
     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, 220, 220,
6590
     230, 230, 230, 220, 230, 220, 220, 220, 220, 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,
6592
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6593
     0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6594
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6595
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6596
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6597
     0,   0,   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, 0,   0,
6599
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6600
     0,   0,   0,   0},
6601
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6602
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6603
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6604
     0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0, 0, 0, 0, 0, 0,
6606
     0, 0, 0, 0, 0, 0, 0, 9, 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, 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, 0, 9, 7, 0, 0, 0, 0, 0,
6609
     0, 0, 0, 0, 0, 0, 0, 0, 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, 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
    {230, 230, 230, 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,
6614
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6615
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6616
     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, 7, 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,
6619
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6620
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6621
     0,   0,   0,   0, 7, 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, 0, 0, 0, 0, 0, 0,
6623
     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, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6627
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6628
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6629
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6630
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6631
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6632
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6633
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0,
6634
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6635
    {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6636
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6637
     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,   7,   7,   0, 0, 0,
6639
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6640
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6641
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6642
     230, 230, 230, 230, 230, 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,
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,
6646
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6647
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6648
     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,
6650
     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, 9, 0, 0, 0, 7,   0,
6654
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6655
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6657
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6658
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6659
     0, 0, 9, 7, 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},
6662
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6669
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6670
     7, 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},
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, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6676
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6677
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6678
     0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682
     0, 0, 0, 0, 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},
6684
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6685
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6692
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6693
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
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, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6702
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6706
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6709
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6711
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6712
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6713
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6715
     0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6720
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6722
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6723
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
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, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6731
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6734
     0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6736
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
6738
     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, 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, 0, 0, 0, 0,
6741
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6742
     0, 0, 0, 0, 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, 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, 0, 0, 0, 0,
6745
     0, 0, 0, 0, 0, 0, 0, 9, 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},
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, 9, 9, 0, 0, 0, 0, 0,
6753
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6754
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6755
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6756
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6757
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6758
     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},
6761
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6762
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6763
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6764
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6765
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6768
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     1, 1, 1, 1, 1, 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, 0, 0, 0, 0,
6773
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6774
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6775
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6776
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6777
     0, 0, 0, 0, 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,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6779
     0, 0, 0, 0, 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, 0, 0, 0, 0,
6781
     0, 0, 0, 0, 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, 0, 0, 0, 0,
6783
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6784
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6785
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,
6787
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 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, 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, 0, 0,
6795
     6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6796
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6797
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6798
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6799
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6802
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6805
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6806
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6807
    {0,   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,   0,
6809
     0,   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,   0,
6811
     0,   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,   0,
6813
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6814
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6815
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6816
     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,   230, 230, 230, 230, 0,   0,
6818
     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,
6820
     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,
6822
     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, 0, 0, 0, 0, 0, 0,
6825
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6826
     230, 230, 230, 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},
6835
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6836
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6837
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6838
     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,
6840
     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,
6842
     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,
6844
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6845
     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,
6847
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6848
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6849
     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,
6851
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6852
     0},
6853
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6854
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6855
     0, 0, 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,   0,   0,
6857
     0, 0, 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,   0,   0,
6859
     0, 0, 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,   230, 0,
6861
     0, 0, 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,   0,   0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6864
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6865
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6866
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6867
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6868
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6869
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6870
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6871
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6872
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6873
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6874
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6875
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6876
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6877
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6878
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6879
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6880
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6881
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6882
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6883
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6884
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6885
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6886
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6887
     0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6888
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6889
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6890
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6891
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6892
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6893
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6894
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6895
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6896
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6897
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6898
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6899
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6900
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6901
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6902
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6903
6904
const uint8_t composition_index[4352] = {
6905
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 17, 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, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6918
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7066
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7067
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7068
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7069
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7070
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7071
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7072
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7073
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7074
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7075
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7076
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7077
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7078
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7079
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7080
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7081
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7082
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7083
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7084
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7085
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7086
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7087
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7088
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7089
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7090
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7091
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7092
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7093
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7094
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7095
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7096
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7097
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7098
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7099
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7100
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7101
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7102
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7103
const uint16_t composition_block[67][257] = {
7104
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7105
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7106
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7107
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7108
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7109
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7110
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7111
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7112
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7113
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7114
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7115
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7116
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7117
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7118
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7119
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7120
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7121
     869, 869},
7122
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7123
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7124
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7125
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7126
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7127
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7128
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7129
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7130
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7131
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7132
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7133
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7134
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7135
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7136
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7137
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7138
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7139
     965, 965},
7140
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7141
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7142
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7143
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7144
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7145
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7146
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7147
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7148
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7149
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7150
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7151
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7152
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7153
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7154
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7155
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7156
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7157
     979, 979},
7158
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7159
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7160
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7161
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7162
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7163
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7164
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7165
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7166
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7167
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7168
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7169
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7170
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7171
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7172
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7173
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7174
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7175
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7176
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7177
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7178
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7179
     1171, 1171, 1171, 1171, 1171},
7180
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7181
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7182
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7183
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7184
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7185
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7186
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7187
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7188
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7189
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7190
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7191
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7192
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7193
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7194
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7195
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7196
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7197
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7198
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7199
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7200
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7201
     1275, 1275, 1275, 1275, 1275},
7202
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7203
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7204
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7205
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7206
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7207
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7208
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7209
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7210
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7211
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7212
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7213
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7214
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7215
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7216
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7217
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7218
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7219
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7220
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7221
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7222
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7223
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7224
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7225
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7226
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7227
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7228
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7229
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7230
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7231
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7232
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7233
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7234
     1291, 1291, 1291, 1291, 1291},
7235
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7236
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7237
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7238
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7239
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7240
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7241
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7242
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7243
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7244
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7245
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7246
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7247
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7248
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7249
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7250
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7251
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7252
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7253
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7254
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7255
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7256
     1301, 1301, 1301, 1301, 1301},
7257
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7258
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7259
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7260
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7261
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7262
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7263
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7264
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7265
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7266
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7267
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7268
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7269
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7270
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7271
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7272
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7273
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7274
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7275
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7276
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7277
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7278
     1315, 1315, 1315, 1315, 1315},
7279
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7280
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7281
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7282
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7283
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7284
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7285
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7286
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7287
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7288
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7289
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7290
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7291
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7292
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7293
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7294
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7295
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7296
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7297
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7298
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7299
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7300
     1327, 1327, 1327, 1327, 1327},
7301
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7302
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7303
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7304
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7305
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7306
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7307
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7308
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7309
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7310
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7311
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7312
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7313
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7314
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7315
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7316
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7317
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7318
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7319
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7320
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7321
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7322
     1341, 1341, 1341, 1341, 1341},
7323
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7324
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7325
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7326
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7327
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7328
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7329
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7330
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7331
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7332
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7333
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7334
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7335
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7336
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7337
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7338
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7339
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7340
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7341
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7342
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7343
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7344
     1343, 1343, 1343, 1343, 1343},
7345
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7346
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7347
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7348
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7349
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7350
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7351
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7352
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7353
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7354
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7355
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7356
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7357
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7358
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7359
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7360
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7361
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7362
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7363
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7364
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7365
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7366
     1365, 1365, 1365, 1365, 1365},
7367
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7368
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7369
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7370
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7371
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7372
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7373
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7374
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7375
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7376
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7377
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7378
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7379
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7380
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7381
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7382
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7383
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7384
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7385
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7386
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7387
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7388
     1393, 1393, 1393, 1393, 1393},
7389
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7390
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7391
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7392
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7393
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7394
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7395
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7396
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7397
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7398
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7399
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7400
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7401
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7402
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7403
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7404
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7405
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7406
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7407
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7408
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7409
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7410
     1653, 1653, 1653, 1659, 1659},
7411
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7412
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7413
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7414
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7415
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7416
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7417
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7418
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7419
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7420
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7421
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7422
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7423
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7424
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7425
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7426
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7427
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7428
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7429
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7430
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7431
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7432
     1671, 1671, 1671, 1671, 1671},
7433
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7434
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7435
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7436
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7437
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7438
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7439
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7440
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7441
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7442
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7443
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7444
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7445
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7446
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7447
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7448
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7449
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7450
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7451
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7452
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7453
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7454
     1741, 1741, 1741, 1741, 1741},
7455
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7456
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7457
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7458
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7459
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7460
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7461
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7462
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7463
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7464
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7465
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7466
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7467
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7468
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7469
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7470
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7471
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7472
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7473
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7474
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7475
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7476
     1855, 1855, 1857, 1857, 1857},
7477
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7478
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7479
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7480
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7481
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7482
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7483
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7484
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7485
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7486
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7487
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7488
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7489
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7490
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7491
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7492
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7493
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7494
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7495
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7496
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7497
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7498
     1863, 1863, 1863, 1863, 1863},
7499
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7500
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7501
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7502
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7503
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7504
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7505
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7506
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7507
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7508
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7509
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7510
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7511
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7512
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7513
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7514
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7515
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7516
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7517
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7518
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7519
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7520
     1867, 1867, 1867, 1867, 1867},
7521
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7522
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7523
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7524
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7525
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7526
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7527
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7528
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7529
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7530
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7531
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7532
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7533
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7534
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7535
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7536
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7537
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7538
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7539
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7540
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7541
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7542
     1871, 1871, 1871, 1871, 1871},
7543
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7544
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7545
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7546
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7547
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7548
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7549
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7550
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7551
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7552
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7553
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7554
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7555
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7556
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7557
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7558
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7559
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7560
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7561
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7562
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7563
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7564
     1877, 1877, 1877, 1877, 1877},
7565
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7566
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7567
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7568
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7569
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7570
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7571
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7572
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7573
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7574
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7575
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7576
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7577
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7578
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7579
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7580
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7581
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7582
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7583
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7584
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7585
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7586
     1881, 1881, 1881, 1881, 1881},
7587
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7588
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7589
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7590
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7591
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7592
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7593
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7594
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7595
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7596
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7597
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7598
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7599
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7600
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7601
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7602
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7603
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7604
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7605
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7606
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7607
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7608
     1883, 1883, 1883, 1883, 1883}};
7609
const char32_t composition_data[1883] = {
7610
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7611
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7612
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7613
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7614
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7615
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7616
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7617
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7618
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7619
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7620
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7621
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7622
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7623
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7624
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7625
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7626
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7627
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7628
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7629
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7630
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7631
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7632
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7633
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7634
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7635
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7636
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7637
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7638
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7639
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7640
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7641
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7642
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7643
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7644
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7645
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7646
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7647
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7648
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7649
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7650
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7651
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7652
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7653
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7654
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7655
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7656
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7657
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7658
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7659
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7660
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7661
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7662
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7663
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7664
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7665
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7666
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7667
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7668
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7669
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7670
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7671
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7672
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7673
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7674
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7675
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7676
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7677
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7678
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7679
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7680
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7681
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7682
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7683
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7684
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7685
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7686
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7687
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7688
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7689
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7690
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7691
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7692
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7693
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7694
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7695
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7696
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7697
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7698
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7699
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7700
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7701
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7702
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7703
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7704
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7705
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7706
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7707
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7708
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7709
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7710
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7711
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7712
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7713
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7714
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7715
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7716
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7717
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7718
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7719
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7720
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7721
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7722
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7723
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7724
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7725
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7726
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7727
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7728
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7729
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7730
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7731
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7732
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7733
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7734
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7735
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7736
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7737
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7738
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7739
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7740
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7741
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7742
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7743
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7744
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7745
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7746
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7747
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7748
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7749
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7750
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7751
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7752
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7753
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7754
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7755
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7756
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7757
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7758
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7759
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7760
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7761
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7762
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7763
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7764
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7765
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7766
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7767
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7768
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7769
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7770
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7771
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7772
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7773
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7774
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7775
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7776
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7777
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7778
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7779
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7780
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7781
    71984, 71992};
7782
7783
}  // namespace ada::idna
7784
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7785
/* end file src/normalization_tables.cpp */
7786
7787
namespace ada::idna {
7788
7789
// See
7790
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7791
constexpr char32_t hangul_sbase = 0xAC00;
7792
constexpr char32_t hangul_tbase = 0x11A7;
7793
constexpr char32_t hangul_vbase = 0x1161;
7794
constexpr char32_t hangul_lbase = 0x1100;
7795
constexpr char32_t hangul_lcount = 19;
7796
constexpr char32_t hangul_vcount = 21;
7797
constexpr char32_t hangul_tcount = 28;
7798
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7799
constexpr char32_t hangul_scount =
7800
    hangul_lcount * hangul_vcount * hangul_tcount;
7801
7802
std::pair<bool, size_t> compute_decomposition_length(
7803
4.56k
    const std::u32string_view input) noexcept {
7804
4.56k
  bool decomposition_needed{false};
7805
4.56k
  size_t additional_elements{0};
7806
158k
  for (char32_t current_character : input) {
7807
158k
    size_t decomposition_length{0};
7808
7809
158k
    if (current_character >= hangul_sbase &&
7810
5.36k
        current_character < hangul_sbase + hangul_scount) {
7811
2.06k
      decomposition_length = 2;
7812
2.06k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7813
1.30k
        decomposition_length = 3;
7814
1.30k
      }
7815
156k
    } else if (current_character < 0x110000) {
7816
156k
      const uint8_t di = decomposition_index[current_character >> 8];
7817
156k
      const uint16_t* const decomposition =
7818
156k
          decomposition_block[di] + (current_character % 256);
7819
156k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7820
156k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7821
0
        decomposition_length = 0;
7822
0
      }
7823
156k
    }
7824
158k
    if (decomposition_length != 0) {
7825
4.79k
      decomposition_needed = true;
7826
4.79k
      additional_elements += decomposition_length - 1;
7827
4.79k
    }
7828
158k
  }
7829
4.56k
  return {decomposition_needed, additional_elements};
7830
4.56k
}
7831
7832
1.30k
void decompose(std::u32string& input, size_t additional_elements) {
7833
1.30k
  input.resize(input.size() + additional_elements);
7834
1.30k
  for (size_t descending_idx = input.size(),
7835
1.30k
              input_count = descending_idx - additional_elements;
7836
52.9k
       input_count--;) {
7837
51.6k
    if (input[input_count] >= hangul_sbase &&
7838
2.73k
        input[input_count] < hangul_sbase + hangul_scount) {
7839
      // Hangul decomposition.
7840
2.06k
      char32_t s_index = input[input_count] - hangul_sbase;
7841
2.06k
      if (s_index % hangul_tcount != 0) {
7842
1.30k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7843
1.30k
      }
7844
2.06k
      input[--descending_idx] =
7845
2.06k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7846
2.06k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7847
49.5k
    } else if (input[input_count] < 0x110000) {
7848
      // Check decomposition_data.
7849
49.5k
      const uint16_t* decomposition =
7850
49.5k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7851
49.5k
          (input[input_count] % 256);
7852
49.5k
      uint16_t decomposition_length =
7853
49.5k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7854
49.5k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7855
0
        decomposition_length = 0;
7856
0
      }
7857
49.5k
      if (decomposition_length > 0) {
7858
        // Non-recursive decomposition.
7859
9.58k
        while (decomposition_length-- > 0) {
7860
6.85k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7861
6.85k
                                                       decomposition_length];
7862
6.85k
        }
7863
46.8k
      } else {
7864
        // No decomposition.
7865
46.8k
        input[--descending_idx] = input[input_count];
7866
46.8k
      }
7867
49.5k
    } else {
7868
      // Non-Unicode character.
7869
0
      input[--descending_idx] = input[input_count];
7870
0
    }
7871
51.6k
  }
7872
1.30k
}
7873
7874
327k
uint8_t get_ccc(char32_t c) noexcept {
7875
327k
  return c < 0x110000 ? canonical_combining_class_block
7876
327k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7877
327k
                      : 0;
7878
327k
}
7879
7880
4.56k
void sort_marks(std::u32string& input) {
7881
166k
  for (size_t idx = 1; idx < input.size(); idx++) {
7882
161k
    uint8_t ccc = get_ccc(input[idx]);
7883
161k
    if (ccc == 0) {
7884
154k
      continue;
7885
154k
    }  // Skip non-combining characters.
7886
7.93k
    auto current_character = input[idx];
7887
7.93k
    size_t back_idx = idx;
7888
9.93k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7889
1.99k
      input[back_idx] = input[back_idx - 1];
7890
1.99k
      back_idx--;
7891
1.99k
    }
7892
7.93k
    input[back_idx] = current_character;
7893
7.93k
  }
7894
4.56k
}
7895
7896
4.56k
void decompose_nfc(std::u32string& input) {
7897
  /**
7898
   * Decompose the domain_name string to Unicode Normalization Form C.
7899
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7900
   */
7901
4.56k
  auto [decomposition_needed, additional_elements] =
7902
4.56k
      compute_decomposition_length(input);
7903
4.56k
  if (decomposition_needed) {
7904
1.30k
    decompose(input, additional_elements);
7905
1.30k
  }
7906
4.56k
  sort_marks(input);
7907
4.56k
}
7908
7909
4.56k
void compose(std::u32string& input) {
7910
  /**
7911
   * Compose the domain_name string to Unicode Normalization Form C.
7912
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7913
   */
7914
4.56k
  size_t input_count{0};
7915
4.56k
  size_t composition_count{0};
7916
159k
  for (; input_count < input.size(); input_count++, composition_count++) {
7917
155k
    input[composition_count] = input[input_count];
7918
155k
    if (input[input_count] >= hangul_lbase &&
7919
17.7k
        input[input_count] < hangul_lbase + hangul_lcount) {
7920
2.85k
      if (input_count + 1 < input.size() &&
7921
2.73k
          input[input_count + 1] >= hangul_vbase &&
7922
2.23k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7923
2.06k
        input[composition_count] =
7924
2.06k
            hangul_sbase +
7925
2.06k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7926
2.06k
             input[input_count + 1] - hangul_vbase) *
7927
2.06k
                hangul_tcount;
7928
2.06k
        input_count++;
7929
2.06k
        if (input_count + 1 < input.size() &&
7930
1.97k
            input[input_count + 1] > hangul_tbase &&
7931
1.43k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7932
1.30k
          input[composition_count] += input[++input_count] - hangul_tbase;
7933
1.30k
        }
7934
2.06k
      }
7935
152k
    } else if (input[input_count] >= hangul_sbase &&
7936
2.93k
               input[input_count] < hangul_sbase + hangul_scount) {
7937
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7938
0
          input_count + 1 < input.size() &&
7939
0
          input[input_count + 1] > hangul_tbase &&
7940
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7941
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7942
0
      }
7943
152k
    } else if (input[input_count] < 0x110000) {
7944
152k
      const uint16_t* composition =
7945
152k
          &composition_block[composition_index[input[input_count] >> 8]]
7946
152k
                            [input[input_count] % 256];
7947
152k
      size_t initial_composition_count = composition_count;
7948
160k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7949
156k
           input_count++) {
7950
156k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7951
7952
156k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7953
          // Try finding a composition.
7954
45.5k
          int left = composition[0];
7955
45.5k
          int right = composition[1];
7956
121k
          while (left + 2 < right) {
7957
            // mean without overflow
7958
76.2k
            int middle = left + (((right - left) >> 1) & ~1);
7959
76.2k
            if (composition_data[middle] <= input[input_count + 1]) {
7960
8.06k
              left = middle;
7961
8.06k
            }
7962
76.2k
            if (composition_data[middle] >= input[input_count + 1]) {
7963
70.6k
              right = middle;
7964
70.6k
            }
7965
76.2k
          }
7966
45.5k
          if (composition_data[left] == input[input_count + 1]) {
7967
3.79k
            input[initial_composition_count] = composition_data[left + 1];
7968
3.79k
            composition =
7969
3.79k
                &composition_block
7970
3.79k
                    [composition_index[composition_data[left + 1] >> 8]]
7971
3.79k
                    [composition_data[left + 1] % 256];
7972
3.79k
            continue;
7973
3.79k
          }
7974
45.5k
        }
7975
7976
152k
        if (ccc == 0) {
7977
148k
          break;
7978
148k
        }  // Not a combining character.
7979
4.21k
        previous_ccc = ccc;
7980
4.21k
        input[++composition_count] = input[input_count + 1];
7981
4.21k
      }
7982
152k
    }
7983
155k
  }
7984
7985
4.56k
  if (composition_count < input_count) {
7986
1.31k
    input.resize(composition_count);
7987
1.31k
  }
7988
4.56k
}
7989
7990
4.56k
void normalize(std::u32string& input) {
7991
  /**
7992
   * Normalize the domain_name string to Unicode Normalization Form C.
7993
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7994
   */
7995
4.56k
  decompose_nfc(input);
7996
4.56k
  compose(input);
7997
4.56k
}
7998
7999
}  // namespace ada::idna
8000
/* end file src/normalization.cpp */
8001
/* begin file src/punycode.cpp */
8002
8003
#include <cstdint>
8004
8005
namespace ada::idna {
8006
8007
constexpr int32_t base = 36;
8008
constexpr int32_t tmin = 1;
8009
constexpr int32_t tmax = 26;
8010
constexpr int32_t skew = 38;
8011
constexpr int32_t damp = 700;
8012
constexpr int32_t initial_bias = 72;
8013
constexpr uint32_t initial_n = 128;
8014
8015
65.4k
static constexpr int32_t char_to_digit_value(char value) {
8016
65.4k
  if (value >= 'a' && value <= 'z') return value - 'a';
8017
12.9k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8018
698
  return -1;
8019
12.9k
}
8020
8021
83.7k
static constexpr char digit_to_char(int32_t digit) {
8022
83.7k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8023
83.7k
}
8024
8025
103k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8026
103k
  if (firsttime) {
8027
10.8k
    d = d / damp;
8028
92.7k
  } else {
8029
92.7k
    d = d / 2;
8030
92.7k
  }
8031
103k
  d += d / n;
8032
103k
  int32_t k = 0;
8033
114k
  while (d > ((base - tmin) * tmax) / 2) {
8034
10.5k
    d /= base - tmin;
8035
10.5k
    k += base;
8036
10.5k
  }
8037
103k
  return k + (((base - tmin + 1) * d) / (d + skew));
8038
103k
}
8039
8040
5.62k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8041
  // See https://github.com/whatwg/url/issues/803
8042
5.62k
  if (input.starts_with("xn--")) {
8043
8
    return false;
8044
8
  }
8045
5.61k
  int32_t written_out{0};
8046
5.61k
  out.reserve(out.size() + input.size());
8047
5.61k
  uint32_t n = initial_n;
8048
5.61k
  int32_t i = 0;
8049
5.61k
  int32_t bias = initial_bias;
8050
  // grab ascii content
8051
5.61k
  size_t end_of_ascii = input.find_last_of('-');
8052
5.61k
  if (end_of_ascii != std::string_view::npos) {
8053
7.58k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8054
7.58k
      if (c >= 0x80) {
8055
0
        return false;
8056
0
      }
8057
7.58k
      out.push_back(c);
8058
7.58k
      written_out++;
8059
7.58k
    }
8060
622
    input.remove_prefix(end_of_ascii + 1);
8061
622
  }
8062
40.0k
  while (!input.empty()) {
8063
34.6k
    int32_t oldi = i;
8064
34.6k
    int32_t w = 1;
8065
48.1k
    for (int32_t k = base;; k += base) {
8066
48.1k
      if (input.empty()) {
8067
87
        return false;
8068
87
      }
8069
48.1k
      uint8_t code_point = input.front();
8070
48.1k
      input.remove_prefix(1);
8071
48.1k
      int32_t digit = char_to_digit_value(code_point);
8072
48.1k
      if (digit < 0) {
8073
68
        return false;
8074
68
      }
8075
48.0k
      if (digit > (0x7fffffff - i) / w) {
8076
15
        return false;
8077
15
      }
8078
48.0k
      i = i + digit * w;
8079
48.0k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8080
48.0k
      if (digit < t) {
8081
34.4k
        break;
8082
34.4k
      }
8083
13.5k
      if (w > 0x7fffffff / (base - t)) {
8084
0
        return false;
8085
0
      }
8086
13.5k
      w = w * (base - t);
8087
13.5k
    }
8088
34.4k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8089
34.4k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8090
40
      return false;
8091
40
    }
8092
34.4k
    n = n + i / (written_out + 1);
8093
34.4k
    i = i % (written_out + 1);
8094
34.4k
    if (n < 0x80) {
8095
0
      return false;
8096
0
    }
8097
34.4k
    out.insert(out.begin() + i, n);
8098
34.4k
    written_out++;
8099
34.4k
    ++i;
8100
34.4k
  }
8101
5.40k
  return true;
8102
5.61k
}
8103
8104
3.26k
bool verify_punycode(std::string_view input) {
8105
3.26k
  if (input.starts_with("xn--")) {
8106
38
    return false;
8107
38
  }
8108
3.23k
  size_t written_out{0};
8109
3.23k
  uint32_t n = initial_n;
8110
3.23k
  int32_t i = 0;
8111
3.23k
  int32_t bias = initial_bias;
8112
  // grab ascii content
8113
3.23k
  size_t end_of_ascii = input.find_last_of('-');
8114
3.23k
  if (end_of_ascii != std::string_view::npos) {
8115
3.06k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8116
3.06k
      if (c >= 0x80) {
8117
0
        return false;
8118
0
      }
8119
3.06k
      written_out++;
8120
3.06k
    }
8121
376
    input.remove_prefix(end_of_ascii + 1);
8122
376
  }
8123
12.1k
  while (!input.empty()) {
8124
9.85k
    int32_t oldi = i;
8125
9.85k
    int32_t w = 1;
8126
17.5k
    for (int32_t k = base;; k += base) {
8127
17.5k
      if (input.empty()) {
8128
143
        return false;
8129
143
      }
8130
17.3k
      uint8_t code_point = input.front();
8131
17.3k
      input.remove_prefix(1);
8132
17.3k
      int32_t digit = char_to_digit_value(code_point);
8133
17.3k
      if (digit < 0) {
8134
630
        return false;
8135
630
      }
8136
16.7k
      if (digit > (0x7fffffff - i) / w) {
8137
45
        return false;
8138
45
      }
8139
16.6k
      i = i + digit * w;
8140
16.6k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8141
16.6k
      if (digit < t) {
8142
9.03k
        break;
8143
9.03k
      }
8144
7.66k
      if (w > 0x7fffffff / (base - t)) {
8145
0
        return false;
8146
0
      }
8147
7.66k
      w = w * (base - t);
8148
7.66k
    }
8149
9.03k
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8150
9.03k
    if (i / (written_out + 1) > 0x7fffffff - n) {
8151
68
      return false;
8152
68
    }
8153
8.96k
    n = n + i / int32_t(written_out + 1);
8154
8.96k
    i = i % int32_t(written_out + 1);
8155
8.96k
    if (n < 0x80) {
8156
0
      return false;
8157
0
    }
8158
8.96k
    written_out++;
8159
8.96k
    ++i;
8160
8.96k
  }
8161
8162
2.34k
  return true;
8163
3.23k
}
8164
8165
3.81k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8166
3.81k
  out.reserve(input.size() + out.size());
8167
3.81k
  uint32_t n = initial_n;
8168
3.81k
  int32_t d = 0;
8169
3.81k
  int32_t bias = initial_bias;
8170
3.81k
  size_t h = 0;
8171
  // first push the ascii content
8172
75.2k
  for (uint32_t c : input) {
8173
75.2k
    if (c < 0x80) {
8174
15.0k
      ++h;
8175
15.0k
      out.push_back(char(c));
8176
15.0k
    }
8177
75.2k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8178
0
      return false;
8179
0
    }
8180
75.2k
  }
8181
3.81k
  size_t b = h;
8182
3.81k
  if (b > 0) {
8183
1.59k
    out.push_back('-');
8184
1.59k
  }
8185
15.9k
  while (h < input.size()) {
8186
12.1k
    uint32_t m = 0x10FFFF;
8187
859k
    for (auto code_point : input) {
8188
859k
      if (code_point >= n && code_point < m) m = code_point;
8189
859k
    }
8190
8191
12.1k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8192
0
      return false;
8193
0
    }
8194
12.1k
    d = d + int32_t((m - n) * (h + 1));
8195
12.1k
    n = m;
8196
859k
    for (auto c : input) {
8197
859k
      if (c < n) {
8198
535k
        if (d == 0x7fffffff) {
8199
0
          return false;
8200
0
        }
8201
535k
        ++d;
8202
535k
      }
8203
859k
      if (c == n) {
8204
60.1k
        int32_t q = d;
8205
83.7k
        for (int32_t k = base;; k += base) {
8206
83.7k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8207
8208
83.7k
          if (q < t) {
8209
60.1k
            break;
8210
60.1k
          }
8211
23.5k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8212
23.5k
          q = (q - t) / (base - t);
8213
23.5k
        }
8214
60.1k
        out.push_back(digit_to_char(q));
8215
60.1k
        bias = adapt(d, int32_t(h + 1), h == b);
8216
60.1k
        d = 0;
8217
60.1k
        ++h;
8218
60.1k
      }
8219
859k
    }
8220
12.1k
    ++d;
8221
12.1k
    ++n;
8222
12.1k
  }
8223
3.81k
  return true;
8224
3.81k
}
8225
8226
}  // namespace ada::idna
8227
/* end file src/punycode.cpp */
8228
/* begin file src/validity.cpp */
8229
#include <algorithm>
8230
#include <string_view>
8231
8232
namespace ada::idna {
8233
8234
enum direction : uint8_t {
8235
  NONE,
8236
  BN,
8237
  CS,
8238
  ES,
8239
  ON,
8240
  EN,
8241
  L,
8242
  R,
8243
  NSM,
8244
  AL,
8245
  AN,
8246
  ET,
8247
  WS,
8248
  RLO,
8249
  LRO,
8250
  PDF,
8251
  RLE,
8252
  RLI,
8253
  FSI,
8254
  PDI,
8255
  LRI,
8256
  B,
8257
  S,
8258
  LRE
8259
};
8260
8261
struct directions {
8262
  uint32_t start_code;
8263
  uint32_t final_code;
8264
  direction direct;
8265
};
8266
8267
static directions dir_table[] = {
8268
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8269
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8270
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8271
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8272
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8273
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8274
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8275
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8276
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8277
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8278
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8279
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8280
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8281
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8282
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8283
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8284
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8285
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8286
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8287
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8288
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8289
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8290
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8291
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8292
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8293
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8294
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8295
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8296
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8297
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8298
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8299
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8300
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8301
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8302
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8303
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8304
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8305
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8306
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8307
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8308
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8309
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8310
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8311
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8312
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8313
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8314
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8315
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8316
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8317
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8318
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8319
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8320
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8321
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8322
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8323
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8324
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8325
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8326
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8327
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8328
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8329
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8330
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8331
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8332
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8333
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8334
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8335
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8336
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8337
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8338
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8339
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8340
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8341
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8342
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8343
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8344
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8345
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8346
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8347
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8348
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8349
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8350
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8351
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8352
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8353
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8354
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8355
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8356
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8357
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8358
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8359
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8360
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8361
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8362
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8363
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8364
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8365
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8366
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8367
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8368
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8369
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8370
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8371
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8372
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8373
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8374
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8375
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8376
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8377
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8378
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8379
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8380
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8381
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8382
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8383
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8384
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8385
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8386
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8387
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8388
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8389
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8390
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8391
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8392
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8393
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8394
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8395
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8396
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8397
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8398
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8399
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8400
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8401
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8402
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8403
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8404
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8405
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8406
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8407
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8408
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8409
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8410
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8411
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8412
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8413
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8414
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8415
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8416
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8417
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8418
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8419
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8420
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8421
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8422
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8423
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8424
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8425
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8426
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8427
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8428
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8429
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8430
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8431
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8432
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8433
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8434
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8435
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8436
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8437
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8438
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8439
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8440
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8441
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8442
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8443
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8444
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8445
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8446
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8447
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8448
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8449
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8450
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8451
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8452
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8453
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8454
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8455
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8456
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8457
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8458
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8459
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8460
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8461
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8462
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8463
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8464
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8465
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8466
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8467
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8468
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8469
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8470
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8471
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8472
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8473
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8474
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8475
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8476
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8477
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8478
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8479
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8480
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8481
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8482
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8483
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8484
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8485
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8486
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8487
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8488
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8489
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8490
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8491
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8492
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8493
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8494
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8495
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8496
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8497
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8498
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8499
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8500
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8501
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8502
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8503
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8504
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8505
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8506
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8507
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8508
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8509
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8510
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8511
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8512
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8513
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8514
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8515
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8516
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8517
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8518
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8519
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8520
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8521
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8522
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8523
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8524
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8525
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8526
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8527
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8528
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8529
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8530
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8531
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8532
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8533
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8534
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8535
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8536
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8537
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8538
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8539
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8540
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8541
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8542
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8543
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8544
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8545
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8546
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8547
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8548
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8549
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8550
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8551
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8552
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8553
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8554
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8555
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8556
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8557
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8558
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8559
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8560
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8561
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8562
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8563
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8564
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8565
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8566
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8567
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8568
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8569
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8570
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8571
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8572
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8573
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8574
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8575
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8576
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8577
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8578
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8579
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8580
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8581
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8582
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8583
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8584
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8585
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8586
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8587
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8588
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8589
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8590
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8591
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8592
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8593
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8594
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8595
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8596
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8597
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8598
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8599
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8600
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8601
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8602
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8603
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8604
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8605
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8606
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8607
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8608
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8609
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8610
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8611
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8612
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8613
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8614
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8615
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8616
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8617
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8618
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8619
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8620
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8621
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8622
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8623
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8624
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8625
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8626
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8627
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8628
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8629
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8630
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8631
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8632
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8633
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8634
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8635
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8636
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8637
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8638
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8639
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8640
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8641
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8642
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8643
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8644
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8645
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8646
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8647
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8648
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8649
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8650
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8651
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8652
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8653
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8654
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8655
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8656
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8657
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8658
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8659
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8660
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8661
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8662
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8663
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8664
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8665
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8666
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8667
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8668
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8669
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8670
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8671
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8672
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8673
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8674
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8675
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8676
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8677
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8678
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8679
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8680
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8681
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8682
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8683
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8684
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8685
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8686
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8687
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8688
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8689
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8690
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8691
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8692
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8693
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8694
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8695
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8696
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8697
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8698
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8699
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8700
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8701
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8702
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8703
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8704
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8705
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8706
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8707
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8708
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8709
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8710
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8711
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8712
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8713
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8714
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8715
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8716
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8717
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8718
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8719
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8720
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8721
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8722
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8723
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8724
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8725
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8726
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8727
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8728
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8729
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8730
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8731
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8732
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8733
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8734
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8735
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8736
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8737
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8738
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8739
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8740
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8741
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8742
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8743
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8744
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8745
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8746
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8747
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8748
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8749
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8750
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8751
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8752
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8753
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8754
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8755
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8756
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8757
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8758
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8759
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8760
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8761
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8762
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8763
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8764
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8765
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8766
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8767
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8768
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8769
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8770
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8771
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8772
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8773
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8774
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8775
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8776
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8777
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8778
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8779
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8780
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8781
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8782
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8783
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8784
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8785
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8786
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8787
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8788
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8789
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8790
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8791
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8792
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8793
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8794
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8795
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8796
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8797
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8798
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8799
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8800
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8801
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8802
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8803
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8804
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8805
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8806
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8807
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8808
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8809
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8810
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8811
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8812
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8813
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8814
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8815
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8816
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8817
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8818
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8819
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8820
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8821
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8822
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8823
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8824
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8825
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8826
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8827
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8828
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8829
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8830
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8831
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8832
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8833
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8834
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8835
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8836
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8837
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8838
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8839
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8840
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8841
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8842
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8843
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8844
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8845
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8846
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8847
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8848
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8849
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8850
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8851
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8852
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8853
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8854
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8855
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8856
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8857
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8858
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8859
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8860
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8861
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8862
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8863
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8864
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8865
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8866
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8867
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8868
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8869
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8870
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8871
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8872
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8873
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8874
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8875
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8876
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8877
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8878
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8879
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8880
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8881
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8882
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8883
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8884
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8885
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8886
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8887
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8888
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8889
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8890
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8891
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8892
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8893
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8894
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8895
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8896
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8897
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8898
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8899
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8900
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8901
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8902
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8903
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8904
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8905
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8906
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8907
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8908
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8909
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8910
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8911
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8912
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8913
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8914
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8915
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8916
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8917
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8918
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8919
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8920
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8921
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8922
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8923
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8924
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8925
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8926
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8927
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8928
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8929
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8930
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8931
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8932
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8933
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8934
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8935
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8936
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8937
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8938
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8939
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8940
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8941
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8942
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8943
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8944
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8945
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8946
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8947
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8948
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8949
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8950
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8951
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8952
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8953
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8954
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8955
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8956
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8957
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8958
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8959
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8960
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8961
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8962
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8963
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8964
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8965
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8966
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8967
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8968
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8969
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8970
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8971
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8972
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8973
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8974
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8975
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8976
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8977
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8978
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8979
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8980
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8981
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8982
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8983
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8984
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8985
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8986
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8987
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8988
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8989
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8990
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8991
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8992
    {0x100000, 0x10fffd, direction::L}};
8993
8994
// CheckJoiners and CheckBidi are true for URL specification.
8995
8996
65.9k
inline static direction find_direction(uint32_t code_point) noexcept {
8997
65.9k
  auto it = std::lower_bound(
8998
65.9k
      std::begin(dir_table), std::end(dir_table), code_point,
8999
700k
      [](const directions& d, uint32_t c) { return d.final_code < c; });
9000
9001
  // next check is almost surely in vain, but we use it for safety.
9002
65.9k
  if (it == std::end(dir_table)) {
9003
0
    return direction::NONE;
9004
0
  }
9005
  // We have that d.final_code >= c.
9006
65.9k
  if (code_point >= it->start_code) {
9007
64.3k
    return it->direct;
9008
64.3k
  }
9009
1.64k
  return direction::NONE;
9010
65.9k
}
9011
9012
inline static size_t find_last_not_of_nsm(
9013
5.33k
    const std::u32string_view label) noexcept {
9014
6.70k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9015
6.70k
    if (find_direction(label[i]) != direction::NSM) return i;
9016
9017
0
  return std::u32string_view::npos;
9018
5.33k
}
9019
9020
// An RTL label is a label that contains at least one character of type R, AL,
9021
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9022
5.33k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9023
5.33k
  const size_t mask =
9024
5.33k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9025
9026
5.33k
  size_t directions = 0;
9027
56.7k
  for (size_t i = 0; i < label.size(); i++) {
9028
51.3k
    directions |= 1u << find_direction(label[i]);
9029
51.3k
  }
9030
5.33k
  return (directions & mask) != 0;
9031
5.33k
}
9032
9033
6.53k
bool is_label_valid(const std::u32string_view label) {
9034
6.53k
  if (label.empty()) {
9035
0
    return true;
9036
0
  }
9037
9038
  ///////////////
9039
  // We have a normalization step which ensures that we are in NFC.
9040
  // If we receive punycode, we normalize and check that the normalized
9041
  // version matches the original.
9042
  // --------------------------------------
9043
  // The label must be in Unicode Normalization Form NFC.
9044
9045
  // Current URL standard indicatest that CheckHyphens is set to false.
9046
  // ---------------------------------------
9047
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9048
  // in both the third and fourth positions. If CheckHyphens, the label must
9049
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9050
9051
  // This is not necessary because we segment the
9052
  // labels by '.'.
9053
  // ---------------------------------------
9054
  // The label must not contain a U+002E ( . ) FULL STOP.
9055
  // if (label.find('.') != std::string_view::npos) return false;
9056
9057
  // The label must not begin with a combining mark, that is:
9058
  // General_Category=Mark.
9059
6.53k
  constexpr static uint32_t combining[] = {
9060
6.53k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9061
6.53k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9062
6.53k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9063
6.53k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9064
6.53k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9065
6.53k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9066
6.53k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9067
6.53k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9068
6.53k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9069
6.53k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9070
6.53k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9071
6.53k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9072
6.53k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9073
6.53k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9074
6.53k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9075
6.53k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9076
6.53k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9077
6.53k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9078
6.53k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9079
6.53k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9080
6.53k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9081
6.53k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9082
6.53k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9083
6.53k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9084
6.53k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9085
6.53k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9086
6.53k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9087
6.53k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9088
6.53k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9089
6.53k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9090
6.53k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9091
6.53k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9092
6.53k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9093
6.53k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9094
6.53k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9095
6.53k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9096
6.53k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9097
6.53k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9098
6.53k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9099
6.53k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9100
6.53k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9101
6.53k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9102
6.53k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9103
6.53k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9104
6.53k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9105
6.53k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9106
6.53k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9107
6.53k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9108
6.53k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9109
6.53k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9110
6.53k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9111
6.53k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9112
6.53k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9113
6.53k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9114
6.53k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9115
6.53k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9116
6.53k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9117
6.53k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9118
6.53k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9119
6.53k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9120
6.53k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9121
6.53k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9122
6.53k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9123
6.53k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9124
6.53k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9125
6.53k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9126
6.53k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9127
6.53k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9128
6.53k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9129
6.53k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9130
6.53k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9131
6.53k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9132
6.53k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9133
6.53k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9134
6.53k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9135
6.53k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9136
6.53k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9137
6.53k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9138
6.53k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9139
6.53k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9140
6.53k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9141
6.53k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9142
6.53k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9143
6.53k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9144
6.53k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9145
6.53k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9146
6.53k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9147
6.53k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9148
6.53k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9149
6.53k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9150
6.53k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9151
6.53k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9152
6.53k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9153
6.53k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9154
6.53k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9155
6.53k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9156
6.53k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9157
6.53k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9158
6.53k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9159
6.53k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9160
6.53k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9161
6.53k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9162
6.53k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9163
6.53k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9164
6.53k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9165
6.53k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9166
6.53k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9167
6.53k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9168
6.53k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9169
6.53k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9170
6.53k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9171
6.53k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9172
6.53k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9173
6.53k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9174
6.53k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9175
6.53k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9176
6.53k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9177
6.53k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9178
6.53k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9179
6.53k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9180
6.53k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9181
6.53k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9182
6.53k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9183
6.53k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9184
6.53k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9185
6.53k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9186
6.53k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9187
6.53k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9188
6.53k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9189
6.53k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9190
6.53k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9191
6.53k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9192
6.53k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9193
6.53k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9194
6.53k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9195
6.53k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9196
6.53k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9197
6.53k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9198
6.53k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9199
6.53k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9200
6.53k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9201
6.53k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9202
6.53k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9203
6.53k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9204
6.53k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9205
6.53k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9206
6.53k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9207
6.53k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9208
6.53k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9209
6.53k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9210
6.53k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9211
6.53k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9212
6.53k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9213
6.53k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9214
6.53k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9215
6.53k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9216
6.53k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9217
6.53k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9218
6.53k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9219
6.53k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9220
6.53k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9221
6.53k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9222
6.53k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9223
6.53k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9224
6.53k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9225
6.53k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9226
6.53k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9227
6.53k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9228
6.53k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9229
6.53k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9230
6.53k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9231
6.53k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9232
6.53k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9233
6.53k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9234
6.53k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9235
6.53k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9236
6.53k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9237
6.53k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9238
6.53k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9239
6.53k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9240
6.53k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9241
6.53k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9242
6.53k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9243
6.53k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9244
6.53k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9245
6.53k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9246
6.53k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9247
6.53k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9248
6.53k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9249
6.53k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9250
6.53k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9251
6.53k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9252
6.53k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9253
6.53k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9254
6.53k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9255
6.53k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9256
6.53k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9257
6.53k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9258
6.53k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9259
6.53k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9260
6.53k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9261
6.53k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9262
6.53k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9263
6.53k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9264
6.53k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9265
6.53k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9266
6.53k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9267
6.53k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9268
6.53k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9269
6.53k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9270
6.53k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9271
6.53k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9272
6.53k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9273
6.53k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9274
6.53k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9275
6.53k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9276
6.53k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9277
6.53k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9278
6.53k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9279
6.53k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9280
6.53k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9281
6.53k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9282
6.53k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9283
6.53k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9284
6.53k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9285
6.53k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9286
6.53k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9287
6.53k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9288
6.53k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9289
6.53k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9290
6.53k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9291
6.53k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9292
6.53k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9293
6.53k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9294
6.53k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9295
6.53k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9296
6.53k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9297
6.53k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9298
6.53k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9299
6.53k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9300
6.53k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9301
6.53k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9302
6.53k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9303
6.53k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9304
6.53k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9305
6.53k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9306
6.53k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9307
6.53k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9308
6.53k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9309
6.53k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9310
6.53k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9311
6.53k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9312
6.53k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9313
6.53k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9314
6.53k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9315
6.53k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9316
6.53k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9317
6.53k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9318
6.53k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9319
6.53k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9320
6.53k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9321
6.53k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9322
6.53k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9323
6.53k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9324
6.53k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9325
6.53k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9326
6.53k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9327
6.53k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9328
6.53k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9329
6.53k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9330
6.53k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9331
6.53k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9332
6.53k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9333
6.53k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9334
6.53k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9335
6.53k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9336
6.53k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9337
6.53k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9338
6.53k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9339
6.53k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9340
6.53k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9341
6.53k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9342
6.53k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9343
6.53k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9344
6.53k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9345
6.53k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9346
6.53k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9347
6.53k
  if (std::binary_search(std::begin(combining), std::end(combining),
9348
6.53k
                         label.front())) {
9349
42
    return false;
9350
42
  }
9351
  // We verify this next step as part of the mapping:
9352
  // ---------------------------------------------
9353
  // Each code point in the label must only have certain status values
9354
  // according to Section 5, IDNA Mapping Table:
9355
  // - For Transitional Processing, each value must be valid.
9356
  // - For Nontransitional Processing, each value must be either valid or
9357
  // deviation.
9358
9359
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9360
  // A, in The Unicode Code Points and Internationalized Domain Names for
9361
  // Applications (IDNA) [IDNA2008].
9362
6.49k
  constexpr static uint32_t virama[] = {
9363
6.49k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9364
6.49k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9365
6.49k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9366
6.49k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9367
6.49k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9368
6.49k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9369
6.49k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9370
6.49k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9371
6.49k
  constexpr static uint32_t R[] = {
9372
6.49k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9373
6.49k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9374
6.49k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9375
6.49k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9376
6.49k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9377
6.49k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9378
6.49k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9379
6.49k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9380
6.49k
  constexpr static uint32_t L[] = {0xa872};
9381
6.49k
  constexpr static uint32_t D[] = {
9382
6.49k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9383
6.49k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9384
6.49k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9385
6.49k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9386
6.49k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9387
6.49k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9388
6.49k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9389
6.49k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9390
6.49k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9391
6.49k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9392
6.49k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9393
6.49k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9394
6.49k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9395
6.49k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9396
6.49k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9397
6.49k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9398
6.49k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9399
6.49k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9400
6.49k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9401
6.49k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9402
6.49k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9403
6.49k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9404
6.49k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9405
6.49k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9406
6.49k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9407
6.49k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9408
6.49k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9409
6.49k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9410
6.49k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9411
6.49k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9412
6.49k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9413
6.49k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9414
6.49k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9415
6.49k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9416
6.49k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9417
6.49k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9418
6.49k
      0xa870, 0xa871};
9419
9420
78.4k
  for (size_t i = 0; i < label.size(); i++) {
9421
73.1k
    uint32_t c = label[i];
9422
73.1k
    if (c == 0x200c) {
9423
861
      if (i > 0) {
9424
856
        if (std::binary_search(std::begin(virama), std::end(virama),
9425
856
                               label[i - 1])) {
9426
104
          return true;
9427
104
        }
9428
856
      }
9429
757
      if ((i == 0) || (i + 1 >= label.size())) {
9430
69
        return false;
9431
69
      }
9432
      // we go backward looking for L or D
9433
1.65k
      auto is_l_or_d = [](uint32_t code) {
9434
1.65k
        return std::binary_search(std::begin(L), std::end(L), code) ||
9435
1.61k
               std::binary_search(std::begin(D), std::end(D), code);
9436
1.65k
      };
9437
1.78k
      auto is_r_or_d = [](uint32_t code) {
9438
1.78k
        return std::binary_search(std::begin(R), std::end(R), code) ||
9439
1.55k
               std::binary_search(std::begin(D), std::end(D), code);
9440
1.78k
      };
9441
688
      std::u32string_view before = label.substr(0, i);
9442
688
      std::u32string_view after = label.substr(i + 1);
9443
688
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9444
688
              before.end()) &&
9445
623
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9446
623
              after.end());
9447
72.2k
    } else if (c == 0x200d) {
9448
297
      if (i > 0) {
9449
293
        if (std::binary_search(std::begin(virama), std::end(virama),
9450
293
                               label[i - 1])) {
9451
231
          return true;
9452
231
        }
9453
293
      }
9454
66
      return false;
9455
297
    }
9456
73.1k
  }
9457
9458
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9459
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9460
  // Section 2.
9461
9462
  // The following rule, consisting of six conditions, applies to labels
9463
  // in Bidi domain names.  The requirements that this rule satisfies are
9464
  // described in Section 3.  All of the conditions must be satisfied for
9465
  // the rule to be satisfied.
9466
  //
9467
  //  1.  The first character must be a character with Bidi property L, R,
9468
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9469
  //     has the L property, it is an LTR label.
9470
  //
9471
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9472
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9473
  //
9474
  //   3.  In an RTL label, the end of the label must be a character with
9475
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9476
  //       characters with Bidi property NSM.
9477
  //
9478
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9479
  //       vice versa.
9480
  //
9481
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9482
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9483
  //
9484
  //   6.  In an LTR label, the end of the label must be a character with
9485
  //       Bidi property L or EN, followed by zero or more characters with
9486
  //       Bidi property NSM.
9487
9488
5.33k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9489
5.33k
  if (last_non_nsm_char == std::u32string_view::npos) {
9490
0
    return false;
9491
0
  }
9492
9493
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9494
  // The following rule, consisting of six conditions, applies to labels in Bidi
9495
  // domain names.
9496
5.33k
  if (is_rtl_label(label)) {
9497
    // The first character must be a character with Bidi property L, R,
9498
    // or AL. If it has the R or AL property, it is an RTL label; if it
9499
    // has the L property, it is an LTR label.
9500
9501
1.22k
    if (find_direction(label[0]) == direction::L) {
9502
      // Eval as LTR
9503
9504
      // In an LTR label, only characters with the Bidi properties L, EN,
9505
      // ES, CS, ET, ON, BN, or NSM are allowed.
9506
2.58k
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9507
2.40k
        const direction d = find_direction(label[i]);
9508
2.40k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9509
1.19k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9510
500
              d == direction::BN || d == direction::NSM)) {
9511
55
          return false;
9512
55
        }
9513
9514
2.35k
        if ((i == last_non_nsm_char) &&
9515
0
            !(d == direction::L || d == direction::EN)) {
9516
0
          return false;
9517
0
        }
9518
2.35k
      }
9519
9520
176
      return true;
9521
9522
993
    } else {
9523
      // Eval as RTL
9524
9525
993
      bool has_an = false;
9526
993
      bool has_en = false;
9527
5.10k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9528
4.24k
        const direction d = find_direction(label[i]);
9529
9530
        // In an RTL label, if an EN is present, no AN may be present, and vice
9531
        // versa.
9532
4.24k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9533
4.24k
            (d == direction::AN && ((has_an = true) && has_en))) {
9534
3
          return false;
9535
3
        }
9536
9537
4.24k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9538
1.75k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9539
1.02k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9540
310
              d == direction::NSM)) {
9541
115
          return false;
9542
115
        }
9543
9544
4.13k
        if (i == last_non_nsm_char &&
9545
875
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9546
96
              d == direction::EN)) {
9547
19
          return false;
9548
19
        }
9549
4.13k
      }
9550
9551
856
      return true;
9552
993
    }
9553
1.22k
  }
9554
9555
4.10k
  return true;
9556
5.33k
}
9557
9558
}  // namespace ada::idna
9559
/* end file src/validity.cpp */
9560
/* begin file src/to_ascii.cpp */
9561
9562
#include <algorithm>
9563
#include <cstdint>
9564
#include <ranges>
9565
9566
9567
#ifdef ADA_USE_SIMDUTF
9568
#include "simdutf.h"
9569
#endif
9570
9571
namespace ada::idna {
9572
9573
7.82k
bool constexpr is_ascii(std::u32string_view view) {
9574
15.6k
  for (uint32_t c : view) {
9575
15.6k
    if (c >= 0x80) {
9576
7.21k
      return false;
9577
7.21k
    }
9578
15.6k
  }
9579
610
  return true;
9580
7.82k
}
9581
9582
7.52k
bool constexpr is_ascii(std::string_view view) {
9583
105k
  for (uint8_t c : view) {
9584
105k
    if (c >= 0x80) {
9585
3.05k
      return false;
9586
3.05k
    }
9587
105k
  }
9588
4.46k
  return true;
9589
7.52k
}
9590
9591
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9592
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9593
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9594
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9595
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9596
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9597
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9598
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9599
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9600
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9601
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9602
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9603
9604
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9605
9606
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9607
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9608
0
}
9609
9610
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9611
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9612
0
}
9613
9614
// We return "" on error.
9615
1.20k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9616
1.20k
  static const std::string error = "";
9617
  // copy and map
9618
  // we could be more efficient by avoiding the copy when unnecessary.
9619
1.20k
  std::string mapped_string = std::string(ut8_string);
9620
1.20k
  ascii_map(mapped_string.data(), mapped_string.size());
9621
1.20k
  std::string out;
9622
1.20k
  size_t label_start = 0;
9623
9624
5.28k
  while (label_start != mapped_string.size()) {
9625
4.86k
    size_t loc_dot = mapped_string.find('.', label_start);
9626
4.86k
    bool is_last_label = (loc_dot == std::string_view::npos);
9627
4.86k
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9628
4.86k
                                      : loc_dot - label_start;
9629
4.86k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9630
4.86k
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9631
4.86k
    label_start += label_size_with_dot;
9632
4.86k
    if (label_size == 0) {
9633
      // empty label? Nothing to do.
9634
2.86k
    } else if (label_view.starts_with("xn--")) {
9635
      // The xn-- part is the expensive game.
9636
1.95k
      out.append(label_view);
9637
1.95k
      std::string_view puny_segment_ascii(
9638
1.95k
          out.data() + out.size() - label_view.size() + 4,
9639
1.95k
          label_view.size() - 4);
9640
1.95k
      std::u32string tmp_buffer;
9641
1.95k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9642
1.95k
      if (!is_ok) {
9643
193
        return error;
9644
193
      }
9645
      // If the input is just ASCII, it should not have been encoded
9646
      // as punycode.
9647
      // https://github.com/whatwg/url/issues/760
9648
1.76k
      if (is_ascii(tmp_buffer)) {
9649
106
        return error;
9650
106
      }
9651
1.65k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9652
1.65k
      if (tmp_buffer != post_map) {
9653
404
        return error;
9654
404
      }
9655
1.25k
      std::u32string pre_normal = post_map;
9656
1.25k
      normalize(post_map);
9657
1.25k
      if (post_map != pre_normal) {
9658
59
        return error;
9659
59
      }
9660
1.19k
      if (post_map.empty()) {
9661
0
        return error;
9662
0
      }
9663
1.19k
      if (!is_label_valid(post_map)) {
9664
11
        return error;
9665
11
      }
9666
1.19k
    } else {
9667
912
      out.append(label_view);
9668
912
    }
9669
4.08k
    if (!is_last_label) {
9670
3.73k
      out.push_back('.');
9671
3.73k
    }
9672
4.08k
  }
9673
427
  return out;
9674
1.20k
}
9675
9676
// We return "" on error.
9677
3.62k
std::string to_ascii(std::string_view ut8_string) {
9678
3.62k
  if (is_ascii(ut8_string)) {
9679
1.20k
    return from_ascii_to_ascii(ut8_string);
9680
1.20k
  }
9681
2.42k
  static const std::string error = "";
9682
  // We convert to UTF-32
9683
9684
#ifdef ADA_USE_SIMDUTF
9685
  size_t utf32_length =
9686
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9687
  std::u32string utf32(utf32_length, '\0');
9688
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9689
      ut8_string.data(), ut8_string.size(), utf32.data());
9690
#else
9691
2.42k
  size_t utf32_length =
9692
2.42k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9693
2.42k
  std::u32string utf32(utf32_length, '\0');
9694
2.42k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9695
2.42k
      ut8_string.data(), ut8_string.size(), utf32.data());
9696
2.42k
#endif
9697
2.42k
  if (actual_utf32_length == 0) {
9698
173
    return error;
9699
173
  }
9700
  // mapping
9701
2.25k
  utf32 = ada::idna::map(utf32);
9702
2.25k
  normalize(utf32);
9703
2.25k
  std::string out;
9704
2.25k
  size_t label_start = 0;
9705
9706
8.45k
  while (label_start != utf32.size()) {
9707
7.05k
    size_t loc_dot = utf32.find('.', label_start);
9708
7.05k
    bool is_last_label = (loc_dot == std::string_view::npos);
9709
7.05k
    size_t label_size =
9710
7.05k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9711
7.05k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9712
7.05k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9713
7.05k
    label_start += label_size_with_dot;
9714
7.05k
    if (label_size == 0) {
9715
      // empty label? Nothing to do.
9716
6.10k
    } else if (label_view.starts_with(U"xn--")) {
9717
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9718
26.7k
      for (char32_t c : label_view) {
9719
26.7k
        if (c >= 0x80) {
9720
18
          return error;
9721
18
        }
9722
26.7k
        out += (unsigned char)(c);
9723
26.7k
      }
9724
1.32k
      std::string_view puny_segment_ascii(
9725
1.32k
          out.data() + out.size() - label_view.size() + 4,
9726
1.32k
          label_view.size() - 4);
9727
1.32k
      std::u32string tmp_buffer;
9728
1.32k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9729
1.32k
      if (!is_ok) {
9730
25
        return error;
9731
25
      }
9732
      // If the input is just ASCII, it should not have been encoded
9733
      // as punycode.
9734
      // https://github.com/whatwg/url/issues/760
9735
1.29k
      if (is_ascii(tmp_buffer)) {
9736
70
        return error;
9737
70
      }
9738
1.22k
      std::u32string post_map = ada::idna::map(tmp_buffer);
9739
1.22k
      if (tmp_buffer != post_map) {
9740
170
        return error;
9741
170
      }
9742
1.05k
      std::u32string pre_normal = post_map;
9743
1.05k
      normalize(post_map);
9744
1.05k
      if (post_map != pre_normal) {
9745
46
        return error;
9746
46
      }
9747
1.01k
      if (post_map.empty()) {
9748
0
        return error;
9749
0
      }
9750
1.01k
      if (!is_label_valid(post_map)) {
9751
8
        return error;
9752
8
      }
9753
4.75k
    } else {
9754
      // The fast path here is an ascii label.
9755
4.75k
      if (is_ascii(label_view)) {
9756
        // no validation needed.
9757
1.63k
        for (char32_t c : label_view) {
9758
1.63k
          out += (unsigned char)(c);
9759
1.63k
        }
9760
4.32k
      } else {
9761
        // slow path.
9762
        // first check validity.
9763
4.32k
        if (!is_label_valid(label_view)) {
9764
509
          return error;
9765
509
        }
9766
        // It is valid! So now we must encode it as punycode...
9767
3.81k
        out.append("xn--");
9768
3.81k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9769
3.81k
        if (!is_ok) {
9770
0
          return error;
9771
0
        }
9772
3.81k
      }
9773
4.75k
    }
9774
6.20k
    if (!is_last_label) {
9775
4.88k
      out.push_back('.');
9776
4.88k
    }
9777
6.20k
  }
9778
1.40k
  return out;
9779
2.25k
}
9780
}  // namespace ada::idna
9781
/* end file src/to_ascii.cpp */
9782
/* begin file src/to_unicode.cpp */
9783
9784
#include <algorithm>
9785
#include <string>
9786
9787
9788
#ifdef ADA_USE_SIMDUTF
9789
#include "simdutf.h"
9790
#endif
9791
9792
namespace ada::idna {
9793
3.62k
std::string to_unicode(std::string_view input) {
9794
3.62k
  std::string output;
9795
3.62k
  output.reserve(input.size());
9796
9797
3.62k
  size_t label_start = 0;
9798
16.7k
  while (label_start < input.size()) {
9799
13.1k
    size_t loc_dot = input.find('.', label_start);
9800
13.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9801
13.1k
    size_t label_size =
9802
13.1k
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9803
13.1k
    auto label_view = std::string_view(input.data() + label_start, label_size);
9804
9805
13.1k
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9806
3.26k
      label_view.remove_prefix(4);
9807
3.26k
      if (ada::idna::verify_punycode(label_view)) {
9808
2.34k
        std::u32string tmp_buffer;
9809
2.34k
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9810
#ifdef ADA_USE_SIMDUTF
9811
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9812
                                                           tmp_buffer.size());
9813
          std::string final_utf8(utf8_size, '\0');
9814
          simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9815
                                         final_utf8.data());
9816
#else
9817
2.34k
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9818
2.34k
                                                             tmp_buffer.size());
9819
2.34k
          std::string final_utf8(utf8_size, '\0');
9820
2.34k
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9821
2.34k
                                   final_utf8.data());
9822
2.34k
#endif
9823
2.34k
          output.append(final_utf8);
9824
2.34k
        } else {
9825
          // ToUnicode never fails.  If any step fails, then the original input
9826
          // sequence is returned immediately in that step.
9827
0
          output.append(
9828
0
              std::string_view(input.data() + label_start, label_size));
9829
0
        }
9830
2.34k
      } else {
9831
924
        output.append(std::string_view(input.data() + label_start, label_size));
9832
924
      }
9833
9.88k
    } else {
9834
9.88k
      output.append(label_view);
9835
9.88k
    }
9836
9837
13.1k
    if (!is_last_label) {
9838
9.67k
      output.push_back('.');
9839
9.67k
    }
9840
9841
13.1k
    label_start += label_size + 1;
9842
13.1k
  }
9843
9844
3.62k
  return output;
9845
3.62k
}
9846
}  // namespace ada::idna
9847
/* end file src/to_unicode.cpp */
9848
/* begin file src/identifier.cpp */
9849
9850
#include <algorithm>
9851
#include <array>
9852
#include <string>
9853
9854
/* begin file src/id_tables.cpp */
9855
// IDNA  17.0.0
9856
9857
// clang-format off
9858
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9859
#define ADA_IDNA_IDENTIFIER_TABLES_H
9860
#include <cstdint>
9861
9862
namespace ada::idna {
9863
9864
const uint32_t id_continue[1418][2] =
9865
{
9866
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9867
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9868
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9869
  {444, 447}, {448, 451}, {452, 659}, {660, 661},
9870
  {662, 687}, {688, 705}, {710, 721}, {736, 740},
9871
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9872
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9873
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9874
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9875
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9876
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9877
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9878
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9879
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9880
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9881
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9882
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9883
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9884
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9885
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9886
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9887
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9888
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9889
  {2185, 2191}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9890
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9891
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9892
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9893
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9894
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9895
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
9896
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
9897
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
9898
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
9899
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
9900
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
9901
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
9902
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
9903
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
9904
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
9905
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
9906
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
9907
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
9908
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
9909
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
9910
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
9911
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
9912
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
9913
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
9914
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
9915
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
9916
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
9917
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
9918
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
9919
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
9920
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
9921
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
9922
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
9923
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
9924
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
9925
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
9926
  {3157, 3158}, {3160, 3162}, {3164, 3165}, {3168, 3169},
9927
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
9928
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
9929
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
9930
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
9931
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
9932
  {3292, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
9933
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
9934
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
9935
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
9936
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
9937
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
9938
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
9939
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
9940
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
9941
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
9942
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
9943
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
9944
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
9945
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
9946
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
9947
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
9948
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
9949
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
9950
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
9951
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
9952
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
9953
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
9954
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
9955
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
9956
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
9957
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
9958
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
9959
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
9960
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
9961
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
9962
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
9963
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
9964
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
9965
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
9966
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
9967
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
9968
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
9969
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
9970
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
9971
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
9972
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
9973
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
9974
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
9975
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
9976
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
9977
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
9978
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
9979
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
9980
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
9981
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
9982
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
9983
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
9984
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
9985
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
9986
  {6832, 6845}, {6847, 6877}, {6880, 6891}, {6912, 6915},
9987
  {6916, 6916}, {6917, 6963}, {6964, 6964}, {6965, 6965},
9988
  {6966, 6970}, {6971, 6971}, {6972, 6972}, {6973, 6977},
9989
  {6978, 6978}, {6979, 6980}, {6981, 6988}, {6992, 7001},
9990
  {7019, 7027}, {7040, 7041}, {7042, 7042}, {7043, 7072},
9991
  {7073, 7073}, {7074, 7077}, {7078, 7079}, {7080, 7081},
9992
  {7082, 7082}, {7083, 7085}, {7086, 7087}, {7088, 7097},
9993
  {7098, 7141}, {7142, 7142}, {7143, 7143}, {7144, 7145},
9994
  {7146, 7148}, {7149, 7149}, {7150, 7150}, {7151, 7153},
9995
  {7154, 7155}, {7168, 7203}, {7204, 7211}, {7212, 7219},
9996
  {7220, 7221}, {7222, 7223}, {7232, 7241}, {7245, 7247},
9997
  {7248, 7257}, {7258, 7287}, {7288, 7293}, {7296, 7306},
9998
  {7312, 7354}, {7357, 7359}, {7376, 7378}, {7380, 7392},
9999
  {7393, 7393}, {7394, 7400}, {7401, 7404}, {7405, 7405},
10000
  {7406, 7411}, {7412, 7412}, {7413, 7414}, {7415, 7415},
10001
  {7416, 7417}, {7418, 7418}, {7424, 7467}, {7468, 7530},
10002
  {7531, 7543}, {7544, 7544}, {7545, 7578}, {7579, 7615},
10003
  {7616, 7679}, {7680, 7957}, {7960, 7965}, {7968, 8005},
10004
  {8008, 8013}, {8016, 8023}, {8025, 8025}, {8027, 8027},
10005
  {8029, 8029}, {8031, 8061}, {8064, 8116}, {8118, 8124},
10006
  {8126, 8126}, {8130, 8132}, {8134, 8140}, {8144, 8147},
10007
  {8150, 8155}, {8160, 8172}, {8178, 8180}, {8182, 8188},
10008
  {8204, 8205}, {8255, 8256}, {8276, 8276}, {8305, 8305},
10009
  {8319, 8319}, {8336, 8348}, {8400, 8412}, {8417, 8417},
10010
  {8421, 8432}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10011
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10012
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10013
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10014
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10015
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10016
  {11499, 11502}, {11503, 11505}, {11506, 11507}, {11520, 11557},
10017
  {11559, 11559}, {11565, 11565}, {11568, 11623}, {11631, 11631},
10018
  {11647, 11647}, {11648, 11670}, {11680, 11686}, {11688, 11694},
10019
  {11696, 11702}, {11704, 11710}, {11712, 11718}, {11720, 11726},
10020
  {11728, 11734}, {11736, 11742}, {11744, 11775}, {12293, 12293},
10021
  {12294, 12294}, {12295, 12295}, {12321, 12329}, {12330, 12333},
10022
  {12334, 12335}, {12337, 12341}, {12344, 12346}, {12347, 12347},
10023
  {12348, 12348}, {12353, 12438}, {12441, 12442}, {12443, 12444},
10024
  {12445, 12446}, {12447, 12447}, {12449, 12538}, {12539, 12539},
10025
  {12540, 12542}, {12543, 12543}, {12549, 12591}, {12593, 12686},
10026
  {12704, 12735}, {12784, 12799}, {13312, 19903}, {19968, 40980},
10027
  {40981, 40981}, {40982, 42124}, {42192, 42231}, {42232, 42237},
10028
  {42240, 42507}, {42508, 42508}, {42512, 42527}, {42528, 42537},
10029
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42607, 42607},
10030
  {42612, 42621}, {42623, 42623}, {42624, 42651}, {42652, 42653},
10031
  {42654, 42655}, {42656, 42725}, {42726, 42735}, {42736, 42737},
10032
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10033
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42972},
10034
  {42993, 42996}, {42997, 42998}, {42999, 42999}, {43000, 43001},
10035
  {43002, 43002}, {43003, 43009}, {43010, 43010}, {43011, 43013},
10036
  {43014, 43014}, {43015, 43018}, {43019, 43019}, {43020, 43042},
10037
  {43043, 43044}, {43045, 43046}, {43047, 43047}, {43052, 43052},
10038
  {43072, 43123}, {43136, 43137}, {43138, 43187}, {43188, 43203},
10039
  {43204, 43205}, {43216, 43225}, {43232, 43249}, {43250, 43255},
10040
  {43259, 43259}, {43261, 43262}, {43263, 43263}, {43264, 43273},
10041
  {43274, 43301}, {43302, 43309}, {43312, 43334}, {43335, 43345},
10042
  {43346, 43347}, {43360, 43388}, {43392, 43394}, {43395, 43395},
10043
  {43396, 43442}, {43443, 43443}, {43444, 43445}, {43446, 43449},
10044
  {43450, 43451}, {43452, 43453}, {43454, 43456}, {43471, 43471},
10045
  {43472, 43481}, {43488, 43492}, {43493, 43493}, {43494, 43494},
10046
  {43495, 43503}, {43504, 43513}, {43514, 43518}, {43520, 43560},
10047
  {43561, 43566}, {43567, 43568}, {43569, 43570}, {43571, 43572},
10048
  {43573, 43574}, {43584, 43586}, {43587, 43587}, {43588, 43595},
10049
  {43596, 43596}, {43597, 43597}, {43600, 43609}, {43616, 43631},
10050
  {43632, 43632}, {43633, 43638}, {43642, 43642}, {43643, 43643},
10051
  {43644, 43644}, {43645, 43645}, {43646, 43695}, {43696, 43696},
10052
  {43697, 43697}, {43698, 43700}, {43701, 43702}, {43703, 43704},
10053
  {43705, 43709}, {43710, 43711}, {43712, 43712}, {43713, 43713},
10054
  {43714, 43714}, {43739, 43740}, {43741, 43741}, {43744, 43754},
10055
  {43755, 43755}, {43756, 43757}, {43758, 43759}, {43762, 43762},
10056
  {43763, 43764}, {43765, 43765}, {43766, 43766}, {43777, 43782},
10057
  {43785, 43790}, {43793, 43798}, {43808, 43814}, {43816, 43822},
10058
  {43824, 43866}, {43868, 43871}, {43872, 43880}, {43881, 43881},
10059
  {43888, 43967}, {43968, 44002}, {44003, 44004}, {44005, 44005},
10060
  {44006, 44007}, {44008, 44008}, {44009, 44010}, {44012, 44012},
10061
  {44013, 44013}, {44016, 44025}, {44032, 55203}, {55216, 55238},
10062
  {55243, 55291}, {63744, 64109}, {64112, 64217}, {64256, 64262},
10063
  {64275, 64279}, {64285, 64285}, {64286, 64286}, {64287, 64296},
10064
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10065
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10066
  {64914, 64967}, {65008, 65019}, {65024, 65039}, {65056, 65071},
10067
  {65075, 65076}, {65101, 65103}, {65136, 65140}, {65142, 65276},
10068
  {65296, 65305}, {65313, 65338}, {65343, 65343}, {65345, 65370},
10069
  {65381, 65381}, {65382, 65391}, {65392, 65392}, {65393, 65437},
10070
  {65438, 65439}, {65440, 65470}, {65474, 65479}, {65482, 65487},
10071
  {65490, 65495}, {65498, 65500}, {65536, 65547}, {65549, 65574},
10072
  {65576, 65594}, {65596, 65597}, {65599, 65613}, {65616, 65629},
10073
  {65664, 65786}, {65856, 65908}, {66045, 66045}, {66176, 66204},
10074
  {66208, 66256}, {66272, 66272}, {66304, 66335}, {66349, 66368},
10075
  {66369, 66369}, {66370, 66377}, {66378, 66378}, {66384, 66421},
10076
  {66422, 66426}, {66432, 66461}, {66464, 66499}, {66504, 66511},
10077
  {66513, 66517}, {66560, 66639}, {66640, 66717}, {66720, 66729},
10078
  {66736, 66771}, {66776, 66811}, {66816, 66855}, {66864, 66915},
10079
  {66928, 66938}, {66940, 66954}, {66956, 66962}, {66964, 66965},
10080
  {66967, 66977}, {66979, 66993}, {66995, 67001}, {67003, 67004},
10081
  {67008, 67059}, {67072, 67382}, {67392, 67413}, {67424, 67431},
10082
  {67456, 67461}, {67463, 67504}, {67506, 67514}, {67584, 67589},
10083
  {67592, 67592}, {67594, 67637}, {67639, 67640}, {67644, 67644},
10084
  {67647, 67669}, {67680, 67702}, {67712, 67742}, {67808, 67826},
10085
  {67828, 67829}, {67840, 67861}, {67872, 67897}, {67904, 67929},
10086
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68097, 68099},
10087
  {68101, 68102}, {68108, 68111}, {68112, 68115}, {68117, 68119},
10088
  {68121, 68149}, {68152, 68154}, {68159, 68159}, {68192, 68220},
10089
  {68224, 68252}, {68288, 68295}, {68297, 68324}, {68325, 68326},
10090
  {68352, 68405}, {68416, 68437}, {68448, 68466}, {68480, 68497},
10091
  {68608, 68680}, {68736, 68786}, {68800, 68850}, {68864, 68899},
10092
  {68900, 68903}, {68912, 68921}, {68928, 68937}, {68938, 68941},
10093
  {68942, 68942}, {68943, 68943}, {68944, 68965}, {68969, 68973},
10094
  {68975, 68975}, {68976, 68997}, {69248, 69289}, {69291, 69292},
10095
  {69296, 69297}, {69314, 69316}, {69317, 69317}, {69318, 69319},
10096
  {69370, 69375}, {69376, 69404}, {69415, 69415}, {69424, 69445},
10097
  {69446, 69456}, {69488, 69505}, {69506, 69509}, {69552, 69572},
10098
  {69600, 69622}, {69632, 69632}, {69633, 69633}, {69634, 69634},
10099
  {69635, 69687}, {69688, 69702}, {69734, 69743}, {69744, 69744},
10100
  {69745, 69746}, {69747, 69748}, {69749, 69749}, {69759, 69761},
10101
  {69762, 69762}, {69763, 69807}, {69808, 69810}, {69811, 69814},
10102
  {69815, 69816}, {69817, 69818}, {69826, 69826}, {69840, 69864},
10103
  {69872, 69881}, {69888, 69890}, {69891, 69926}, {69927, 69931},
10104
  {69932, 69932}, {69933, 69940}, {69942, 69951}, {69956, 69956},
10105
  {69957, 69958}, {69959, 69959}, {69968, 70002}, {70003, 70003},
10106
  {70006, 70006}, {70016, 70017}, {70018, 70018}, {70019, 70066},
10107
  {70067, 70069}, {70070, 70078}, {70079, 70080}, {70081, 70084},
10108
  {70089, 70092}, {70094, 70094}, {70095, 70095}, {70096, 70105},
10109
  {70106, 70106}, {70108, 70108}, {70144, 70161}, {70163, 70187},
10110
  {70188, 70190}, {70191, 70193}, {70194, 70195}, {70196, 70196},
10111
  {70197, 70197}, {70198, 70199}, {70206, 70206}, {70207, 70208},
10112
  {70209, 70209}, {70272, 70278}, {70280, 70280}, {70282, 70285},
10113
  {70287, 70301}, {70303, 70312}, {70320, 70366}, {70367, 70367},
10114
  {70368, 70370}, {70371, 70378}, {70384, 70393}, {70400, 70401},
10115
  {70402, 70403}, {70405, 70412}, {70415, 70416}, {70419, 70440},
10116
  {70442, 70448}, {70450, 70451}, {70453, 70457}, {70459, 70460},
10117
  {70461, 70461}, {70462, 70463}, {70464, 70464}, {70465, 70468},
10118
  {70471, 70472}, {70475, 70477}, {70480, 70480}, {70487, 70487},
10119
  {70493, 70497}, {70498, 70499}, {70502, 70508}, {70512, 70516},
10120
  {70528, 70537}, {70539, 70539}, {70542, 70542}, {70544, 70581},
10121
  {70583, 70583}, {70584, 70586}, {70587, 70592}, {70594, 70594},
10122
  {70597, 70597}, {70599, 70602}, {70604, 70605}, {70606, 70606},
10123
  {70607, 70607}, {70608, 70608}, {70609, 70609}, {70610, 70610},
10124
  {70611, 70611}, {70625, 70626}, {70656, 70708}, {70709, 70711},
10125
  {70712, 70719}, {70720, 70721}, {70722, 70724}, {70725, 70725},
10126
  {70726, 70726}, {70727, 70730}, {70736, 70745}, {70750, 70750},
10127
  {70751, 70753}, {70784, 70831}, {70832, 70834}, {70835, 70840},
10128
  {70841, 70841}, {70842, 70842}, {70843, 70846}, {70847, 70848},
10129
  {70849, 70849}, {70850, 70851}, {70852, 70853}, {70855, 70855},
10130
  {70864, 70873}, {71040, 71086}, {71087, 71089}, {71090, 71093},
10131
  {71096, 71099}, {71100, 71101}, {71102, 71102}, {71103, 71104},
10132
  {71128, 71131}, {71132, 71133}, {71168, 71215}, {71216, 71218},
10133
  {71219, 71226}, {71227, 71228}, {71229, 71229}, {71230, 71230},
10134
  {71231, 71232}, {71236, 71236}, {71248, 71257}, {71296, 71338},
10135
  {71339, 71339}, {71340, 71340}, {71341, 71341}, {71342, 71343},
10136
  {71344, 71349}, {71350, 71350}, {71351, 71351}, {71352, 71352},
10137
  {71360, 71369}, {71376, 71395}, {71424, 71450}, {71453, 71453},
10138
  {71454, 71454}, {71455, 71455}, {71456, 71457}, {71458, 71461},
10139
  {71462, 71462}, {71463, 71467}, {71472, 71481}, {71488, 71494},
10140
  {71680, 71723}, {71724, 71726}, {71727, 71735}, {71736, 71736},
10141
  {71737, 71738}, {71840, 71903}, {71904, 71913}, {71935, 71942},
10142
  {71945, 71945}, {71948, 71955}, {71957, 71958}, {71960, 71983},
10143
  {71984, 71989}, {71991, 71992}, {71995, 71996}, {71997, 71997},
10144
  {71998, 71998}, {71999, 71999}, {72000, 72000}, {72001, 72001},
10145
  {72002, 72002}, {72003, 72003}, {72016, 72025}, {72096, 72103},
10146
  {72106, 72144}, {72145, 72147}, {72148, 72151}, {72154, 72155},
10147
  {72156, 72159}, {72160, 72160}, {72161, 72161}, {72163, 72163},
10148
  {72164, 72164}, {72192, 72192}, {72193, 72202}, {72203, 72242},
10149
  {72243, 72248}, {72249, 72249}, {72250, 72250}, {72251, 72254},
10150
  {72263, 72263}, {72272, 72272}, {72273, 72278}, {72279, 72280},
10151
  {72281, 72283}, {72284, 72329}, {72330, 72342}, {72343, 72343},
10152
  {72344, 72345}, {72349, 72349}, {72368, 72440}, {72544, 72544},
10153
  {72545, 72545}, {72546, 72548}, {72549, 72549}, {72550, 72550},
10154
  {72551, 72551}, {72640, 72672}, {72688, 72697}, {72704, 72712},
10155
  {72714, 72750}, {72751, 72751}, {72752, 72758}, {72760, 72765},
10156
  {72766, 72766}, {72767, 72767}, {72768, 72768}, {72784, 72793},
10157
  {72818, 72847}, {72850, 72871}, {72873, 72873}, {72874, 72880},
10158
  {72881, 72881}, {72882, 72883}, {72884, 72884}, {72885, 72886},
10159
  {72960, 72966}, {72968, 72969}, {72971, 73008}, {73009, 73014},
10160
  {73018, 73018}, {73020, 73021}, {73023, 73029}, {73030, 73030},
10161
  {73031, 73031}, {73040, 73049}, {73056, 73061}, {73063, 73064},
10162
  {73066, 73097}, {73098, 73102}, {73104, 73105}, {73107, 73108},
10163
  {73109, 73109}, {73110, 73110}, {73111, 73111}, {73112, 73112},
10164
  {73120, 73129}, {73136, 73176}, {73177, 73177}, {73178, 73179},
10165
  {73184, 73193}, {73440, 73458}, {73459, 73460}, {73461, 73462},
10166
  {73472, 73473}, {73474, 73474}, {73475, 73475}, {73476, 73488},
10167
  {73490, 73523}, {73524, 73525}, {73526, 73530}, {73534, 73535},
10168
  {73536, 73536}, {73537, 73537}, {73538, 73538}, {73552, 73561},
10169
  {73562, 73562}, {73648, 73648}, {73728, 74649}, {74752, 74862},
10170
  {74880, 75075}, {77712, 77808}, {77824, 78895}, {78912, 78912},
10171
  {78913, 78918}, {78919, 78933}, {78944, 82938}, {82944, 83526},
10172
  {90368, 90397}, {90398, 90409}, {90410, 90412}, {90413, 90415},
10173
  {90416, 90425}, {92160, 92728}, {92736, 92766}, {92768, 92777},
10174
  {92784, 92862}, {92864, 92873}, {92880, 92909}, {92912, 92916},
10175
  {92928, 92975}, {92976, 92982}, {92992, 92995}, {93008, 93017},
10176
  {93027, 93047}, {93053, 93071}, {93504, 93506}, {93507, 93546},
10177
  {93547, 93548}, {93552, 93561}, {93760, 93823}, {93856, 93880},
10178
  {93883, 93907}, {93952, 94026}, {94031, 94031}, {94032, 94032},
10179
  {94033, 94087}, {94095, 94098}, {94099, 94111}, {94176, 94177},
10180
  {94179, 94179}, {94180, 94180}, {94192, 94193}, {94194, 94195},
10181
  {94196, 94198}, {94208, 101589}, {101631, 101662}, {101760, 101874},
10182
  {110576, 110579}, {110581, 110587}, {110589, 110590}, {110592, 110882},
10183
  {110898, 110898}, {110928, 110930}, {110933, 110933}, {110948, 110951},
10184
  {110960, 111355}, {113664, 113770}, {113776, 113788}, {113792, 113800},
10185
  {113808, 113817}, {113821, 113822}, {118000, 118009}, {118528, 118573},
10186
  {118576, 118598}, {119141, 119142}, {119143, 119145}, {119149, 119154},
10187
  {119163, 119170}, {119173, 119179}, {119210, 119213}, {119362, 119364},
10188
  {119808, 119892}, {119894, 119964}, {119966, 119967}, {119970, 119970},
10189
  {119973, 119974}, {119977, 119980}, {119982, 119993}, {119995, 119995},
10190
  {119997, 120003}, {120005, 120069}, {120071, 120074}, {120077, 120084},
10191
  {120086, 120092}, {120094, 120121}, {120123, 120126}, {120128, 120132},
10192
  {120134, 120134}, {120138, 120144}, {120146, 120485}, {120488, 120512},
10193
  {120514, 120538}, {120540, 120570}, {120572, 120596}, {120598, 120628},
10194
  {120630, 120654}, {120656, 120686}, {120688, 120712}, {120714, 120744},
10195
  {120746, 120770}, {120772, 120779}, {120782, 120831}, {121344, 121398},
10196
  {121403, 121452}, {121461, 121461}, {121476, 121476}, {121499, 121503},
10197
  {121505, 121519}, {122624, 122633}, {122634, 122634}, {122635, 122654},
10198
  {122661, 122666}, {122880, 122886}, {122888, 122904}, {122907, 122913},
10199
  {122915, 122916}, {122918, 122922}, {122928, 122989}, {123023, 123023},
10200
  {123136, 123180}, {123184, 123190}, {123191, 123197}, {123200, 123209},
10201
  {123214, 123214}, {123536, 123565}, {123566, 123566}, {123584, 123627},
10202
  {123628, 123631}, {123632, 123641}, {124112, 124138}, {124139, 124139},
10203
  {124140, 124143}, {124144, 124153}, {124368, 124397}, {124398, 124399},
10204
  {124400, 124400}, {124401, 124410}, {124608, 124638}, {124640, 124642},
10205
  {124643, 124643}, {124644, 124645}, {124646, 124646}, {124647, 124653},
10206
  {124654, 124655}, {124656, 124660}, {124661, 124661}, {124670, 124670},
10207
  {124671, 124671}, {124896, 124902}, {124904, 124907}, {124909, 124910},
10208
  {124912, 124926}, {124928, 125124}, {125136, 125142}, {125184, 125251},
10209
  {125252, 125258}, {125259, 125259}, {125264, 125273}, {126464, 126467},
10210
  {126469, 126495}, {126497, 126498}, {126500, 126500}, {126503, 126503},
10211
  {126505, 126514}, {126516, 126519}, {126521, 126521}, {126523, 126523},
10212
  {126530, 126530}, {126535, 126535}, {126537, 126537}, {126539, 126539},
10213
  {126541, 126543}, {126545, 126546}, {126548, 126548}, {126551, 126551},
10214
  {126553, 126553}, {126555, 126555}, {126557, 126557}, {126559, 126559},
10215
  {126561, 126562}, {126564, 126564}, {126567, 126570}, {126572, 126578},
10216
  {126580, 126583}, {126585, 126588}, {126590, 126590}, {126592, 126601},
10217
  {126603, 126619}, {126625, 126627}, {126629, 126633}, {126635, 126651},
10218
  {130032, 130041}, {131072, 173791}, {173824, 178205}, {178208, 183981},
10219
  {183984, 191456}, {191472, 192093}, {194560, 195101}, {196608, 201546},
10220
  {201552, 210041}, {917760, 917999}
10221
};
10222
const uint32_t id_start[776][2] =
10223
{
10224
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10225
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10226
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10227
  {660, 661}, {662, 687}, {688, 705}, {710, 721},
10228
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10229
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10230
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10231
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10232
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10233
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10234
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10235
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10236
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10237
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10238
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10239
  {2160, 2183}, {2185, 2191}, {2208, 2248}, {2249, 2249},
10240
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10241
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10242
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10243
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10244
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10245
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10246
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10247
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10248
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10249
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10250
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10251
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10252
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10253
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10254
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10255
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10256
  {3160, 3162}, {3164, 3165}, {3168, 3169}, {3200, 3200},
10257
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10258
  {3253, 3257}, {3261, 3261}, {3292, 3294}, {3296, 3297},
10259
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10260
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10261
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10262
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10263
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10264
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10265
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10266
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10267
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10268
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10269
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10270
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10271
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10272
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10273
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10274
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10275
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10276
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10277
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10278
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10279
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10280
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10281
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10282
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10283
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10284
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10285
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10286
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10287
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10288
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10289
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10290
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10291
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10292
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10293
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10294
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10295
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10296
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10297
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10298
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10299
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10300
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10301
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10302
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10303
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10304
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10305
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10306
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10307
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10308
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10309
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10310
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10311
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10312
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10313
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10314
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42972},
10315
  {42993, 42996}, {42997, 42998}, {42999, 42999}, {43000, 43001},
10316
  {43002, 43002}, {43003, 43009}, {43011, 43013}, {43015, 43018},
10317
  {43020, 43042}, {43072, 43123}, {43138, 43187}, {43250, 43255},
10318
  {43259, 43259}, {43261, 43262}, {43274, 43301}, {43312, 43334},
10319
  {43360, 43388}, {43396, 43442}, {43471, 43471}, {43488, 43492},
10320
  {43494, 43494}, {43495, 43503}, {43514, 43518}, {43520, 43560},
10321
  {43584, 43586}, {43588, 43595}, {43616, 43631}, {43632, 43632},
10322
  {43633, 43638}, {43642, 43642}, {43646, 43695}, {43697, 43697},
10323
  {43701, 43702}, {43705, 43709}, {43712, 43712}, {43714, 43714},
10324
  {43739, 43740}, {43741, 43741}, {43744, 43754}, {43762, 43762},
10325
  {43763, 43764}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10326
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10327
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10328
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10329
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10330
  {64287, 64296}, {64298, 64310}, {64312, 64316}, {64318, 64318},
10331
  {64320, 64321}, {64323, 64324}, {64326, 64433}, {64467, 64829},
10332
  {64848, 64911}, {64914, 64967}, {65008, 65019}, {65136, 65140},
10333
  {65142, 65276}, {65313, 65338}, {65345, 65370}, {65382, 65391},
10334
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10335
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10336
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10337
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10338
  {66176, 66204}, {66208, 66256}, {66304, 66335}, {66349, 66368},
10339
  {66369, 66369}, {66370, 66377}, {66378, 66378}, {66384, 66421},
10340
  {66432, 66461}, {66464, 66499}, {66504, 66511}, {66513, 66517},
10341
  {66560, 66639}, {66640, 66717}, {66736, 66771}, {66776, 66811},
10342
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10343
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10344
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10345
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10346
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10347
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10348
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10349
  {67872, 67897}, {67904, 67929}, {67968, 68023}, {68030, 68031},
10350
  {68096, 68096}, {68112, 68115}, {68117, 68119}, {68121, 68149},
10351
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10352
  {68352, 68405}, {68416, 68437}, {68448, 68466}, {68480, 68497},
10353
  {68608, 68680}, {68736, 68786}, {68800, 68850}, {68864, 68899},
10354
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10355
  {68975, 68975}, {68976, 68997}, {69248, 69289}, {69296, 69297},
10356
  {69314, 69316}, {69317, 69317}, {69318, 69319}, {69376, 69404},
10357
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10358
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10359
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10360
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10361
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10362
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10363
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10364
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10365
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10366
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10367
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10368
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10369
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10370
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10371
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10372
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10373
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10374
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10375
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10376
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10377
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10378
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10379
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73136, 73176},
10380
  {73177, 73177}, {73178, 73179}, {73440, 73458}, {73474, 73474},
10381
  {73476, 73488}, {73490, 73523}, {73648, 73648}, {73728, 74649},
10382
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10383
  {78913, 78918}, {78944, 82938}, {82944, 83526}, {90368, 90397},
10384
  {92160, 92728}, {92736, 92766}, {92784, 92862}, {92880, 92909},
10385
  {92928, 92975}, {92992, 92995}, {93027, 93047}, {93053, 93071},
10386
  {93504, 93506}, {93507, 93546}, {93547, 93548}, {93760, 93823},
10387
  {93856, 93880}, {93883, 93907}, {93952, 94026}, {94032, 94032},
10388
  {94099, 94111}, {94176, 94177}, {94179, 94179}, {94194, 94195},
10389
  {94196, 94198}, {94208, 101589}, {101631, 101662}, {101760, 101874},
10390
  {110576, 110579}, {110581, 110587}, {110589, 110590}, {110592, 110882},
10391
  {110898, 110898}, {110928, 110930}, {110933, 110933}, {110948, 110951},
10392
  {110960, 111355}, {113664, 113770}, {113776, 113788}, {113792, 113800},
10393
  {113808, 113817}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10394
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10395
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10396
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10397
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10398
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10399
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10400
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {122624, 122633},
10401
  {122634, 122634}, {122635, 122654}, {122661, 122666}, {122928, 122989},
10402
  {123136, 123180}, {123191, 123197}, {123214, 123214}, {123536, 123565},
10403
  {123584, 123627}, {124112, 124138}, {124139, 124139}, {124368, 124397},
10404
  {124400, 124400}, {124608, 124638}, {124640, 124642}, {124644, 124645},
10405
  {124647, 124653}, {124656, 124660}, {124670, 124670}, {124671, 124671},
10406
  {124896, 124902}, {124904, 124907}, {124909, 124910}, {124912, 124926},
10407
  {124928, 125124}, {125184, 125251}, {125259, 125259}, {126464, 126467},
10408
  {126469, 126495}, {126497, 126498}, {126500, 126500}, {126503, 126503},
10409
  {126505, 126514}, {126516, 126519}, {126521, 126521}, {126523, 126523},
10410
  {126530, 126530}, {126535, 126535}, {126537, 126537}, {126539, 126539},
10411
  {126541, 126543}, {126545, 126546}, {126548, 126548}, {126551, 126551},
10412
  {126553, 126553}, {126555, 126555}, {126557, 126557}, {126559, 126559},
10413
  {126561, 126562}, {126564, 126564}, {126567, 126570}, {126572, 126578},
10414
  {126580, 126583}, {126585, 126588}, {126590, 126590}, {126592, 126601},
10415
  {126603, 126619}, {126625, 126627}, {126629, 126633}, {126635, 126651},
10416
  {131072, 173791}, {173824, 178205}, {178208, 183981}, {183984, 191456},
10417
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 210041}
10418
};
10419
10420
10421
} // namespace ada::idna
10422
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10423
/* end file src/id_tables.cpp */
10424
10425
namespace ada::idna {
10426
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10427
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10428
0
}
10429
10430
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10431
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10432
0
         (c >= '0' && c <= '9');
10433
0
}
10434
10435
0
bool valid_name_code_point(char32_t code_point, bool first) {
10436
  // https://tc39.es/ecma262/#prod-IdentifierStart
10437
  // Fast paths:
10438
0
  if (first &&
10439
0
      (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) {
10440
0
    return true;
10441
0
  }
10442
0
  if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) {
10443
0
    return true;
10444
0
  }
10445
  // Slow path...
10446
0
  if (code_point == 0xffffffff) {
10447
0
    return false;  // minimal error handling
10448
0
  }
10449
0
  if (first) {
10450
0
    auto iter = std::lower_bound(
10451
0
        std::begin(ada::idna::id_start), std::end(ada::idna::id_start),
10452
0
        code_point,
10453
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10454
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10455
0
  } else {
10456
0
    auto iter = std::lower_bound(
10457
0
        std::begin(id_continue), std::end(id_continue), code_point,
10458
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10459
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10460
0
  }
10461
0
}
10462
}  // namespace ada::idna
10463
/* end file src/identifier.cpp */
10464
/* end file src/idna.cpp */
10465
// NOLINTEND
10466
/* end file src/ada_idna.cpp */
10467
ADA_POP_DISABLE_WARNINGS
10468
10469
#include <algorithm>
10470
#if ADA_SSSE3
10471
#include <tmmintrin.h>
10472
#elif ADA_NEON
10473
#include <arm_neon.h>
10474
#elif ADA_SSE2
10475
#include <emmintrin.h>
10476
#elif ADA_LSX
10477
#include <lsxintrin.h>
10478
#elif ADA_RVV
10479
#include <riscv_vector.h>
10480
#endif
10481
10482
#include <ranges>
10483
10484
namespace ada::unicode {
10485
10486
0
constexpr bool is_tabs_or_newline(char c) noexcept {
10487
0
  return c == '\r' || c == '\n' || c == '\t';
10488
0
}
10489
10490
0
constexpr uint64_t broadcast(uint8_t v) noexcept {
10491
0
  return 0x101010101010101ull * v;
10492
0
}
10493
10494
0
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10495
0
  uint64_t broadcast_80 = broadcast(0x80);
10496
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10497
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10498
0
  uint64_t non_ascii = 0;
10499
0
  size_t i = 0;
10500
10501
0
  for (; i + 7 < length; i += 8) {
10502
0
    uint64_t word{};
10503
0
    memcpy(&word, input + i, sizeof(word));
10504
0
    non_ascii |= (word & broadcast_80);
10505
0
    word ^=
10506
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10507
0
    memcpy(input + i, &word, sizeof(word));
10508
0
  }
10509
0
  if (i < length) {
10510
0
    uint64_t word{};
10511
0
    memcpy(&word, input + i, length - i);
10512
0
    non_ascii |= (word & broadcast_80);
10513
0
    word ^=
10514
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10515
0
    memcpy(input + i, &word, length - i);
10516
0
  }
10517
0
  return non_ascii == 0;
10518
0
}
10519
#if ADA_SSSE3
10520
ada_really_inline bool has_tabs_or_newline(
10521
    std::string_view user_input) noexcept {
10522
  // first check for short strings in which case we do it naively.
10523
  if (user_input.size() < 16) {  // slow path
10524
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10525
  }
10526
  // fast path for long strings (expected to be common)
10527
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
10528
  size_t i = 0;
10529
  // Lookup table where positions 9, 10, 13 contain their own values
10530
  // Everything else is set to 1 so it won't match
10531
  const __m128i rnt =
10532
      _mm_setr_epi8(1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 13, 0, 0);
10533
  __m128i running = _mm_setzero_si128();
10534
  for (; i + 15 < user_input.size(); i += 16) {
10535
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10536
    // Shuffle the lookup table using input bytes as indices
10537
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10538
    // Compare: if shuffled value matches input, we found \t, \n, or \r
10539
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10540
    running = _mm_or_si128(running, matches);
10541
  }
10542
  if (i < user_input.size()) {
10543
    __m128i word = _mm_loadu_si128(
10544
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10545
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10546
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10547
    running = _mm_or_si128(running, matches);
10548
  }
10549
  return _mm_movemask_epi8(running) != 0;
10550
}
10551
#elif ADA_NEON
10552
ada_really_inline bool has_tabs_or_newline(
10553
    std::string_view user_input) noexcept {
10554
  // first check for short strings in which case we do it naively.
10555
  if (user_input.size() < 16) {  // slow path
10556
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10557
  }
10558
  // fast path for long strings (expected to be common)
10559
  size_t i = 0;
10560
  /**
10561
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10562
   * on table lookup instruction. We notice that these are all unique numbers
10563
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10564
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10565
   * input register. If the input had `\t` in position X then this shuffled
10566
   * register will also have '\t' in that position. Comparing input with this
10567
   * shuffled register will mark us all interesting characters in the input.
10568
   *
10569
   * credit for algorithmic idea: @aqrit, credit for description:
10570
   * @DenisYaroshevskiy
10571
   */
10572
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10573
                                  0, 9, 10, 0, 0, 13, 0, 0};
10574
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10575
  // m['0xd', '0xa', '0x9']
10576
  uint8x16_t running{0};
10577
  for (; i + 15 < user_input.size(); i += 16) {
10578
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10579
10580
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10581
  }
10582
  if (i < user_input.size()) {
10583
    uint8x16_t word =
10584
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10585
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10586
  }
10587
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10588
}
10589
#elif ADA_SSE2
10590
ada_really_inline bool has_tabs_or_newline(
10591
0
    std::string_view user_input) noexcept {
10592
  // first check for short strings in which case we do it naively.
10593
0
  if (user_input.size() < 16) {  // slow path
10594
0
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10595
0
  }
10596
  // fast path for long strings (expected to be common)
10597
0
  size_t i = 0;
10598
0
  const __m128i mask1 = _mm_set1_epi8('\r');
10599
0
  const __m128i mask2 = _mm_set1_epi8('\n');
10600
0
  const __m128i mask3 = _mm_set1_epi8('\t');
10601
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10602
0
  __m128i running{0};
10603
0
  for (; i + 15 < user_input.size(); i += 16) {
10604
0
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10605
0
    running = _mm_or_si128(
10606
0
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10607
0
                                           _mm_cmpeq_epi8(word, mask2))),
10608
0
        _mm_cmpeq_epi8(word, mask3));
10609
0
  }
10610
0
  if (i < user_input.size()) {
10611
0
    __m128i word = _mm_loadu_si128(
10612
0
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10613
0
    running = _mm_or_si128(
10614
0
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10615
0
                                           _mm_cmpeq_epi8(word, mask2))),
10616
0
        _mm_cmpeq_epi8(word, mask3));
10617
0
  }
10618
0
  return _mm_movemask_epi8(running) != 0;
10619
0
}
10620
#elif ADA_LSX
10621
ada_really_inline bool has_tabs_or_newline(
10622
    std::string_view user_input) noexcept {
10623
  // first check for short strings in which case we do it naively.
10624
  if (user_input.size() < 16) {  // slow path
10625
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10626
  }
10627
  // fast path for long strings (expected to be common)
10628
  size_t i = 0;
10629
  const __m128i mask1 = __lsx_vrepli_b('\r');
10630
  const __m128i mask2 = __lsx_vrepli_b('\n');
10631
  const __m128i mask3 = __lsx_vrepli_b('\t');
10632
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10633
  __m128i running{0};
10634
  for (; i + 15 < user_input.size(); i += 16) {
10635
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10636
    running = __lsx_vor_v(
10637
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10638
                                         __lsx_vseq_b(word, mask2))),
10639
        __lsx_vseq_b(word, mask3));
10640
  }
10641
  if (i < user_input.size()) {
10642
    __m128i word = __lsx_vld(
10643
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10644
    running = __lsx_vor_v(
10645
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10646
                                         __lsx_vseq_b(word, mask2))),
10647
        __lsx_vseq_b(word, mask3));
10648
  }
10649
  if (__lsx_bz_v(running)) return false;
10650
  return true;
10651
}
10652
#elif ADA_RVV
10653
ada_really_inline bool has_tabs_or_newline(
10654
    std::string_view user_input) noexcept {
10655
  uint8_t* src = (uint8_t*)user_input.data();
10656
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10657
    vl = __riscv_vsetvl_e8m1(n);
10658
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10659
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10660
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10661
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10662
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10663
    long idx = __riscv_vfirst(m, vl);
10664
    if (idx >= 0) return true;
10665
  }
10666
  return false;
10667
}
10668
#else
10669
ada_really_inline bool has_tabs_or_newline(
10670
    std::string_view user_input) noexcept {
10671
  auto has_zero_byte = [](uint64_t v) {
10672
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10673
  };
10674
  size_t i = 0;
10675
  uint64_t mask1 = broadcast('\r');
10676
  uint64_t mask2 = broadcast('\n');
10677
  uint64_t mask3 = broadcast('\t');
10678
  uint64_t running{0};
10679
  for (; i + 7 < user_input.size(); i += 8) {
10680
    uint64_t word{};
10681
    memcpy(&word, user_input.data() + i, sizeof(word));
10682
    uint64_t xor1 = word ^ mask1;
10683
    uint64_t xor2 = word ^ mask2;
10684
    uint64_t xor3 = word ^ mask3;
10685
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10686
  }
10687
  if (i < user_input.size()) {
10688
    uint64_t word{};
10689
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10690
    uint64_t xor1 = word ^ mask1;
10691
    uint64_t xor2 = word ^ mask2;
10692
    uint64_t xor3 = word ^ mask3;
10693
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10694
  }
10695
  return running;
10696
}
10697
#endif
10698
10699
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10700
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10701
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10702
// U+007C (|).
10703
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10704
    []() consteval {
10705
      std::array<uint8_t, 256> result{};
10706
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10707
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10708
        result[c] = true;
10709
      }
10710
      return result;
10711
    }();
10712
10713
ada_really_inline constexpr bool is_forbidden_host_code_point(
10714
0
    const char c) noexcept {
10715
0
  return is_forbidden_host_code_point_table[uint8_t(c)];
10716
0
}
10717
10718
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10719
    []() consteval {
10720
      std::array<uint8_t, 256> result{};
10721
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10722
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10723
        result[c] = true;
10724
      }
10725
      for (uint8_t c = 0; c <= 32; c++) {
10726
        result[c] = true;
10727
      }
10728
      for (size_t c = 127; c < 255; c++) {
10729
        result[c] = true;
10730
      }
10731
      return result;
10732
    }();
10733
10734
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10735
10736
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10737
0
    const char c) noexcept {
10738
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10739
0
}
10740
10741
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10742
0
    const char* input, size_t length) noexcept {
10743
0
  size_t i = 0;
10744
0
  uint8_t accumulator{};
10745
0
  for (; i + 4 <= length; i += 4) {
10746
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10747
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10748
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10749
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10750
0
  }
10751
0
  for (; i < length; i++) {
10752
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10753
0
  }
10754
0
  return accumulator;
10755
0
}
10756
10757
constexpr static std::array<uint8_t, 256>
10758
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10759
      std::array<uint8_t, 256> result{};
10760
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10761
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10762
        result[c] = 1;
10763
      }
10764
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10765
        result[c] = 2;
10766
      }
10767
      for (uint8_t c = 0; c <= 32; c++) {
10768
        result[c] = 1;
10769
      }
10770
      for (size_t c = 127; c < 255; c++) {
10771
        result[c] = 1;
10772
      }
10773
      return result;
10774
    }();
10775
10776
ada_really_inline constexpr uint8_t
10777
contains_forbidden_domain_code_point_or_upper(const char* input,
10778
0
                                              size_t length) noexcept {
10779
0
  size_t i = 0;
10780
0
  uint8_t accumulator{};
10781
0
  for (; i + 4 <= length; i += 4) {
10782
0
    accumulator |=
10783
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10784
0
    accumulator |=
10785
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10786
0
    accumulator |=
10787
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10788
0
    accumulator |=
10789
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10790
0
  }
10791
0
  for (; i < length; i++) {
10792
0
    accumulator |=
10793
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10794
0
  }
10795
0
  return accumulator;
10796
0
}
10797
10798
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10799
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10800
  std::array<bool, 256> result{};
10801
  for (size_t c = 0; c < 256; c++) {
10802
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10803
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10804
  }
10805
  return result;
10806
}();
10807
10808
0
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10809
0
  return is_alnum_plus_table[uint8_t(c)];
10810
  // A table is almost surely much faster than the
10811
  // following under most compilers: return
10812
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10813
0
}
10814
10815
0
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10816
0
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10817
0
         (c >= 'a' && c <= 'f');
10818
0
}
10819
10820
0
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10821
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10822
  // inclusive.
10823
0
  return (c >= '0' && c <= '9');
10824
0
}
10825
10826
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10827
  // If code point is between U+0000 and U+007F inclusive, then return true.
10828
0
  return c <= 0x7F;
10829
0
}
10830
10831
0
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10832
0
  return (unsigned char)c <= ' ';
10833
0
}
10834
10835
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10836
0
    const char c) noexcept {
10837
0
  return c == '\t' || c == '\n' || c == '\r';
10838
0
}
10839
10840
constexpr std::string_view table_is_double_dot_path_segment[] = {
10841
    "..", "%2e.", ".%2e", "%2e%2e"};
10842
10843
ada_really_inline constexpr bool is_double_dot_path_segment(
10844
0
    std::string_view input) noexcept {
10845
  // This will catch most cases:
10846
  // The length must be 2,4 or 6.
10847
  // We divide by two and require
10848
  // that the result be between 1 and 3 inclusively.
10849
0
  uint64_t half_length = uint64_t(input.size()) / 2;
10850
0
  if (half_length - 1 > 2) {
10851
0
    return false;
10852
0
  }
10853
  // We have a string of length 2, 4 or 6.
10854
  // We now check the first character:
10855
0
  if ((input[0] != '.') && (input[0] != '%')) {
10856
0
    return false;
10857
0
  }
10858
  // We are unlikely the get beyond this point.
10859
0
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10860
0
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10861
0
  if (target.size() != input.size()) {
10862
0
    return false;
10863
0
  }
10864
  // We almost never get here.
10865
  // Optimizing the rest is relatively unimportant.
10866
0
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10867
0
    uint16_t A, B;
10868
0
    memcpy(&A, a.data(), sizeof(A));
10869
0
    memcpy(&B, b.data(), sizeof(B));
10870
0
    return A == B;
10871
0
  };
10872
0
  if (!prefix_equal_unsafe(input, target)) {
10873
0
    return false;
10874
0
  }
10875
0
  for (size_t i = 2; i < input.size(); i++) {
10876
0
    char c = input[i];
10877
0
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10878
0
      return false;
10879
0
    }
10880
0
  }
10881
0
  return true;
10882
  // The above code might be a bit better than the code below. Compilers
10883
  // are not stupid and may use the fact that these strings have length 2,4 and
10884
  // 6 and other tricks.
10885
  // return input == ".." ||
10886
  //  input == ".%2e" || input == ".%2E" ||
10887
  //  input == "%2e." || input == "%2E." ||
10888
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10889
  //  "%2e%2E";
10890
0
}
10891
10892
ada_really_inline constexpr bool is_single_dot_path_segment(
10893
0
    std::string_view input) noexcept {
10894
0
  return input == "." || input == "%2e" || input == "%2E";
10895
0
}
10896
10897
0
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10898
0
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10899
0
}
10900
10901
constexpr static char hex_to_binary_table[] = {
10902
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10903
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10904
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10905
0
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10906
0
  return hex_to_binary_table[c - '0'];
10907
0
}
10908
10909
0
std::string percent_decode(const std::string_view input, size_t first_percent) {
10910
  // next line is for safety only, we expect users to avoid calling
10911
  // percent_decode when first_percent is outside the range.
10912
0
  if (first_percent == std::string_view::npos) {
10913
0
    return std::string(input);
10914
0
  }
10915
0
  std::string dest;
10916
0
  dest.reserve(input.length());
10917
0
  dest.append(input.substr(0, first_percent));
10918
0
  const char* pointer = input.data() + first_percent;
10919
0
  const char* end = input.data() + input.size();
10920
  // Optimization opportunity: if the following code gets
10921
  // called often, it can be optimized quite a bit.
10922
0
  while (pointer < end) {
10923
0
    const char ch = pointer[0];
10924
0
    size_t remaining = end - pointer - 1;
10925
0
    if (ch != '%' || remaining < 2 ||
10926
0
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10927
0
            (!is_ascii_hex_digit(pointer[1]) ||
10928
0
             !is_ascii_hex_digit(pointer[2])))) {
10929
0
      dest += ch;
10930
0
      pointer++;
10931
0
    } else {
10932
0
      unsigned a = convert_hex_to_binary(pointer[1]);
10933
0
      unsigned b = convert_hex_to_binary(pointer[2]);
10934
0
      char c = static_cast<char>(a * 16 + b);
10935
0
      dest += c;
10936
0
      pointer += 3;
10937
0
    }
10938
0
  }
10939
0
  return dest;
10940
0
}
10941
10942
std::string percent_encode(const std::string_view input,
10943
0
                           const uint8_t character_set[]) {
10944
0
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10945
0
    return character_sets::bit_at(character_set, c);
10946
0
  });
10947
  // Optimization: Don't iterate if percent encode is not required
10948
0
  if (pointer == input.end()) {
10949
0
    return std::string(input);
10950
0
  }
10951
10952
0
  std::string result;
10953
0
  result.reserve(input.length());  // in the worst case, percent encoding might
10954
                                   // produce 3 characters.
10955
0
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10956
10957
0
  for (; pointer != input.end(); pointer++) {
10958
0
    if (character_sets::bit_at(character_set, *pointer)) {
10959
0
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10960
0
    } else {
10961
0
      result += *pointer;
10962
0
    }
10963
0
  }
10964
10965
0
  return result;
10966
0
}
10967
10968
template <bool append>
10969
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10970
0
                    std::string& out) {
10971
0
  ada_log("percent_encode ", input, " to output string while ",
10972
0
          append ? "appending" : "overwriting");
10973
0
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10974
0
    return character_sets::bit_at(character_set, c);
10975
0
  });
Unexecuted instantiation: ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)::{lambda(char)#1}::operator()(char) const
Unexecuted instantiation: ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)::{lambda(char)#1}::operator()(char) const
10976
0
  ada_log("percent_encode done checking, moved to ",
10977
0
          std::distance(input.begin(), pointer));
10978
10979
  // Optimization: Don't iterate if percent encode is not required
10980
0
  if (pointer == input.end()) {
10981
0
    ada_log("percent_encode encoding not needed.");
10982
0
    return false;
10983
0
  }
10984
0
  if constexpr (!append) {
10985
0
    out.clear();
10986
0
  }
10987
0
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10988
0
          " bytes");
10989
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10990
0
  out.append(input.data(), std::distance(input.begin(), pointer));
10991
0
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10992
0
          " bytes");
10993
0
  for (; pointer != input.end(); pointer++) {
10994
0
    if (character_sets::bit_at(character_set, *pointer)) {
10995
0
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10996
0
    } else {
10997
0
      out += *pointer;
10998
0
    }
10999
0
  }
11000
0
  return true;
11001
0
}
Unexecuted instantiation: bool ada::unicode::percent_encode<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: bool ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
11002
11003
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
11004
0
              size_t first_percent) {
11005
0
  std::string percent_decoded_buffer;
11006
0
  std::string_view input = plain;
11007
0
  if (first_percent != std::string_view::npos) {
11008
0
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
11009
0
    input = percent_decoded_buffer;
11010
0
  }
11011
  // input is a non-empty UTF-8 string, must be percent decoded
11012
0
  std::string idna_ascii = ada::idna::to_ascii(input);
11013
0
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
11014
0
                                idna_ascii.data(), idna_ascii.size())) {
11015
0
    return false;
11016
0
  }
11017
0
  out = std::move(idna_ascii);
11018
0
  return true;
11019
0
}
11020
11021
std::string percent_encode(const std::string_view input,
11022
0
                           const uint8_t character_set[], size_t index) {
11023
0
  std::string out;
11024
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11025
0
  out.append(input.data(), index);
11026
0
  auto pointer = input.begin() + index;
11027
0
  for (; pointer != input.end(); pointer++) {
11028
0
    if (character_sets::bit_at(character_set, *pointer)) {
11029
0
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11030
0
    } else {
11031
0
      out += *pointer;
11032
0
    }
11033
0
  }
11034
0
  return out;
11035
0
}
11036
11037
}  // namespace ada::unicode
11038
/* end file src/unicode.cpp */
11039
/* begin file src/serializers.cpp */
11040
#include <array>
11041
#include <charconv>
11042
#include <string>
11043
11044
namespace ada::serializers {
11045
11046
void find_longest_sequence_of_ipv6_pieces(
11047
    const std::array<uint16_t, 8>& address, size_t& compress,
11048
0
    size_t& compress_length) noexcept {
11049
0
  for (size_t i = 0; i < 8; i++) {
11050
0
    if (address[i] == 0) {
11051
0
      size_t next = i + 1;
11052
0
      while (next != 8 && address[next] == 0) ++next;
11053
0
      const size_t count = next - i;
11054
0
      if (compress_length < count) {
11055
0
        compress_length = count;
11056
0
        compress = i;
11057
0
        if (next == 8) break;
11058
0
        i = next;
11059
0
      }
11060
0
    }
11061
0
  }
11062
0
}
11063
11064
0
std::string ipv6(const std::array<uint16_t, 8>& address) {
11065
0
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11066
0
  size_t compress = 0;         // The start of a long sequence of zeros.
11067
0
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11068
11069
0
  if (compress_length <= 1) {
11070
    // Optimization opportunity: Find a faster way then snprintf for imploding
11071
    // and return here.
11072
0
    compress = compress_length = 8;
11073
0
  }
11074
11075
0
  std::string output(4 * 8 + 7 + 2, '\0');
11076
0
  size_t piece_index = 0;
11077
0
  char* point = output.data();
11078
0
  char* point_end = output.data() + output.size();
11079
0
  *point++ = '[';
11080
0
  while (true) {
11081
0
    if (piece_index == compress) {
11082
0
      *point++ = ':';
11083
      // If we skip a value initially, we need to write '::', otherwise
11084
      // a single ':' will do since it follows a previous ':'.
11085
0
      if (piece_index == 0) {
11086
0
        *point++ = ':';
11087
0
      }
11088
0
      piece_index += compress_length;
11089
0
      if (piece_index == 8) {
11090
0
        break;
11091
0
      }
11092
0
    }
11093
0
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11094
0
    piece_index++;
11095
0
    if (piece_index == 8) {
11096
0
      break;
11097
0
    }
11098
0
    *point++ = ':';
11099
0
  }
11100
0
  *point++ = ']';
11101
0
  output.resize(point - output.data());
11102
0
  return output;
11103
0
}
11104
11105
0
std::string ipv4(const uint64_t address) {
11106
0
  std::string output(15, '\0');
11107
0
  char* point = output.data();
11108
0
  char* point_end = output.data() + output.size();
11109
0
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11110
0
  for (int i = 2; i >= 0; i--) {
11111
0
    *point++ = '.';
11112
0
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11113
0
  }
11114
0
  output.resize(point - output.data());
11115
0
  return output;
11116
0
}
11117
11118
}  // namespace ada::serializers
11119
/* end file src/serializers.cpp */
11120
/* begin file src/implementation.cpp */
11121
11122
#include <string_view>
11123
11124
11125
namespace ada {
11126
11127
template <class result_type>
11128
ada_warn_unused tl::expected<result_type, errors> parse(
11129
0
    std::string_view input, const result_type* base_url) {
11130
0
  result_type u =
11131
0
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11132
0
  if (!u.is_valid) {
11133
0
    return tl::unexpected(errors::type_error);
11134
0
  }
11135
0
  return u;
11136
0
}
Unexecuted instantiation: tl::expected<ada::url, ada::errors> ada::parse<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: tl::expected<ada::url_aggregator, ada::errors> ada::parse<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
11137
11138
template ada::result<url> parse<url>(std::string_view input,
11139
                                     const url* base_url = nullptr);
11140
template ada::result<url_aggregator> parse<url_aggregator>(
11141
    std::string_view input, const url_aggregator* base_url = nullptr);
11142
11143
0
std::string href_from_file(std::string_view input) {
11144
  // This is going to be much faster than constructing a URL.
11145
0
  std::string tmp_buffer;
11146
0
  std::string_view internal_input;
11147
0
  if (unicode::has_tabs_or_newline(input)) {
11148
0
    tmp_buffer = input;
11149
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11150
0
    internal_input = tmp_buffer;
11151
0
  } else {
11152
0
    internal_input = input;
11153
0
  }
11154
0
  std::string path;
11155
0
  if (internal_input.empty()) {
11156
0
    path = "/";
11157
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11158
0
    helpers::parse_prepared_path(internal_input.substr(1),
11159
0
                                 ada::scheme::type::FILE, path);
11160
0
  } else {
11161
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11162
0
  }
11163
0
  return "file://" + path;
11164
0
}
11165
11166
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
11167
0
  ada::url_aggregator base_aggregator;
11168
0
  ada::url_aggregator* base_pointer = nullptr;
11169
11170
0
  if (base_input != nullptr) {
11171
0
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11172
0
        *base_input, nullptr);
11173
0
    if (!base_aggregator.is_valid) {
11174
0
      return false;
11175
0
    }
11176
0
    base_pointer = &base_aggregator;
11177
0
  }
11178
11179
0
  ada::url_aggregator result =
11180
0
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11181
0
                                                              base_pointer);
11182
0
  return result.is_valid;
11183
0
}
11184
11185
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11186
0
  switch (type) {
11187
0
    case ada::encoding_type::UTF8:
11188
0
      return "UTF-8";
11189
0
    case ada::encoding_type::UTF_16LE:
11190
0
      return "UTF-16LE";
11191
0
    case ada::encoding_type::UTF_16BE:
11192
0
      return "UTF-16BE";
11193
0
    default:
11194
0
      unreachable();
11195
0
  }
11196
0
}
11197
11198
}  // namespace ada
11199
/* end file src/implementation.cpp */
11200
/* begin file src/helpers.cpp */
11201
#include <cstdint>
11202
#include <cstring>
11203
#include <sstream>
11204
11205
11206
#if ADA_SSSE3
11207
#include <tmmintrin.h>
11208
#endif
11209
11210
namespace ada::helpers {
11211
11212
template <typename out_iter>
11213
0
void encode_json(std::string_view view, out_iter out) {
11214
  // trivial implementation. could be faster.
11215
0
  const char* hexvalues =
11216
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11217
0
  for (uint8_t c : view) {
11218
0
    if (c == '\\') {
11219
0
      *out++ = '\\';
11220
0
      *out++ = '\\';
11221
0
    } else if (c == '"') {
11222
0
      *out++ = '\\';
11223
0
      *out++ = '"';
11224
0
    } else if (c <= 0x1f) {
11225
0
      *out++ = '\\';
11226
0
      *out++ = 'u';
11227
0
      *out++ = '0';
11228
0
      *out++ = '0';
11229
0
      *out++ = hexvalues[2 * c];
11230
0
      *out++ = hexvalues[2 * c + 1];
11231
0
    } else {
11232
0
      *out++ = c;
11233
0
    }
11234
0
  }
11235
0
}
11236
11237
0
ada_unused std::string get_state(ada::state s) {
11238
0
  switch (s) {
11239
0
    case ada::state::AUTHORITY:
11240
0
      return "Authority";
11241
0
    case ada::state::SCHEME_START:
11242
0
      return "Scheme Start";
11243
0
    case ada::state::SCHEME:
11244
0
      return "Scheme";
11245
0
    case ada::state::HOST:
11246
0
      return "Host";
11247
0
    case ada::state::NO_SCHEME:
11248
0
      return "No Scheme";
11249
0
    case ada::state::FRAGMENT:
11250
0
      return "Fragment";
11251
0
    case ada::state::RELATIVE_SCHEME:
11252
0
      return "Relative Scheme";
11253
0
    case ada::state::RELATIVE_SLASH:
11254
0
      return "Relative Slash";
11255
0
    case ada::state::FILE:
11256
0
      return "File";
11257
0
    case ada::state::FILE_HOST:
11258
0
      return "File Host";
11259
0
    case ada::state::FILE_SLASH:
11260
0
      return "File Slash";
11261
0
    case ada::state::PATH_OR_AUTHORITY:
11262
0
      return "Path or Authority";
11263
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11264
0
      return "Special Authority Ignore Slashes";
11265
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11266
0
      return "Special Authority Slashes";
11267
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11268
0
      return "Special Relative or Authority";
11269
0
    case ada::state::QUERY:
11270
0
      return "Query";
11271
0
    case ada::state::PATH:
11272
0
      return "Path";
11273
0
    case ada::state::PATH_START:
11274
0
      return "Path Start";
11275
0
    case ada::state::OPAQUE_PATH:
11276
0
      return "Opaque Path";
11277
0
    case ada::state::PORT:
11278
0
      return "Port";
11279
0
    default:
11280
0
      return "unknown state";
11281
0
  }
11282
0
}
11283
11284
ada_really_inline std::optional<std::string_view> prune_hash(
11285
0
    std::string_view& input) noexcept {
11286
  // compiles down to 20--30 instructions including a class to memchr (C
11287
  // function). this function should be quite fast.
11288
0
  size_t location_of_first = input.find('#');
11289
0
  if (location_of_first == std::string_view::npos) {
11290
0
    return std::nullopt;
11291
0
  }
11292
0
  std::string_view hash = input;
11293
0
  hash.remove_prefix(location_of_first + 1);
11294
0
  input.remove_suffix(input.size() - location_of_first);
11295
0
  return hash;
11296
0
}
11297
11298
0
ada_really_inline bool shorten_path(std::string& path, ada::scheme::type type) {
11299
  // Let path be url's path.
11300
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11301
  // Windows drive letter, then return.
11302
0
  if (type == ada::scheme::type::FILE &&
11303
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11304
0
    if (checkers::is_normalized_windows_drive_letter(
11305
0
            helpers::substring(path, 1))) {
11306
0
      return false;
11307
0
    }
11308
0
  }
11309
11310
  // Remove path's last item, if any.
11311
0
  size_t last_delimiter = path.rfind('/');
11312
0
  if (last_delimiter != std::string::npos) {
11313
0
    path.erase(last_delimiter);
11314
0
    return true;
11315
0
  }
11316
11317
0
  return false;
11318
0
}
11319
11320
ada_really_inline bool shorten_path(std::string_view& path,
11321
0
                                    ada::scheme::type type) {
11322
  // Let path be url's path.
11323
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11324
  // Windows drive letter, then return.
11325
0
  if (type == ada::scheme::type::FILE &&
11326
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11327
0
    if (checkers::is_normalized_windows_drive_letter(
11328
0
            helpers::substring(path, 1))) {
11329
0
      return false;
11330
0
    }
11331
0
  }
11332
11333
  // Remove path's last item, if any.
11334
0
  if (!path.empty()) {
11335
0
    size_t slash_loc = path.rfind('/');
11336
0
    if (slash_loc != std::string_view::npos) {
11337
0
      path.remove_suffix(path.size() - slash_loc);
11338
0
      return true;
11339
0
    }
11340
0
  }
11341
11342
0
  return false;
11343
0
}
11344
11345
0
ada_really_inline void remove_ascii_tab_or_newline(std::string& input) {
11346
  // if this ever becomes a performance issue, we could use an approach similar
11347
  // to has_tabs_or_newline
11348
0
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11349
0
}
11350
11351
ada_really_inline constexpr std::string_view substring(std::string_view input,
11352
0
                                                       size_t pos) {
11353
0
  ADA_ASSERT_TRUE(pos <= input.size());
11354
  // The following is safer but unneeded if we have the above line:
11355
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11356
0
  return input.substr(pos);
11357
0
}
11358
11359
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11360
0
  ADA_ASSERT_TRUE(pos <= input.size());
11361
0
  input.remove_suffix(input.size() - pos);
11362
0
}
11363
11364
// computes the number of trailing zeroes
11365
// this is a private inline function only defined in this source file.
11366
0
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11367
#ifdef ADA_REGULAR_VISUAL_STUDIO
11368
  unsigned long ret;
11369
  // Search the mask data from least significant bit (LSB)
11370
  // to the most significant bit (MSB) for a set bit (1).
11371
  _BitScanForward(&ret, input_num);
11372
  return (int)ret;
11373
#else   // ADA_REGULAR_VISUAL_STUDIO
11374
0
  return __builtin_ctzl(input_num);
11375
0
#endif  // ADA_REGULAR_VISUAL_STUDIO
11376
0
}
11377
11378
// starting at index location, this finds the next location of a character
11379
// :, /, \\, ? or [. If none is found, view.size() is returned.
11380
// For use within get_host_delimiter_location.
11381
#if ADA_SSSE3
11382
ada_really_inline size_t find_next_host_delimiter_special(
11383
    std::string_view view, size_t location) noexcept {
11384
  // first check for short strings in which case we do it naively.
11385
  if (view.size() - location < 16) {  // slow path
11386
    for (size_t i = location; i < view.size(); i++) {
11387
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11388
          view[i] == '?' || view[i] == '[') {
11389
        return i;
11390
      }
11391
    }
11392
    return size_t(view.size());
11393
  }
11394
  // fast path for long strings (expected to be common)
11395
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
11396
  size_t i = location;
11397
  const __m128i low_mask =
11398
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11399
                    0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11400
  const __m128i high_mask =
11401
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11402
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11403
  const __m128i fmask = _mm_set1_epi8(0xf);
11404
  const __m128i zero = _mm_setzero_si128();
11405
  for (; i + 15 < view.size(); i += 16) {
11406
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11407
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11408
    __m128i highpart = _mm_shuffle_epi8(
11409
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11410
    __m128i classify = _mm_and_si128(lowpart, highpart);
11411
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11412
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11413
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11414
    // avoid false positives.
11415
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11416
    if (mask != 0) {
11417
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11418
    }
11419
  }
11420
  if (i < view.size()) {
11421
    __m128i word =
11422
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11423
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11424
    __m128i highpart = _mm_shuffle_epi8(
11425
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11426
    __m128i classify = _mm_and_si128(lowpart, highpart);
11427
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11428
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11429
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11430
    // avoid false positives.
11431
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11432
    if (mask != 0) {
11433
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11434
    }
11435
  }
11436
  return size_t(view.size());
11437
}
11438
#elif ADA_NEON
11439
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11440
// support direct initialization of uint8x16_t. See
11441
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11442
#ifndef ada_make_uint8x16_t
11443
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11444
                            x13, x14, x15, x16)                                \
11445
  ([=]() {                                                                     \
11446
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11447
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11448
    return vld1q_u8(array);                                                    \
11449
  }())
11450
#endif
11451
11452
ada_really_inline size_t find_next_host_delimiter_special(
11453
    std::string_view view, size_t location) noexcept {
11454
  // first check for short strings in which case we do it naively.
11455
  if (view.size() - location < 16) {  // slow path
11456
    for (size_t i = location; i < view.size(); i++) {
11457
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11458
          view[i] == '?' || view[i] == '[') {
11459
        return i;
11460
      }
11461
    }
11462
    return size_t(view.size());
11463
  }
11464
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11465
    uint8x16_t bit_mask =
11466
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11467
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11468
    uint8x16_t minput = vandq_u8(input, bit_mask);
11469
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11470
    tmp = vpaddq_u8(tmp, tmp);
11471
    tmp = vpaddq_u8(tmp, tmp);
11472
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11473
  };
11474
11475
  // fast path for long strings (expected to be common)
11476
  size_t i = location;
11477
  uint8x16_t low_mask =
11478
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11479
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11480
  uint8x16_t high_mask =
11481
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11482
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11483
  uint8x16_t fmask = vmovq_n_u8(0xf);
11484
  uint8x16_t zero{0};
11485
  for (; i + 15 < view.size(); i += 16) {
11486
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11487
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11488
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11489
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11490
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11491
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11492
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11493
      return i + trailing_zeroes(is_non_zero);
11494
    }
11495
  }
11496
11497
  if (i < view.size()) {
11498
    uint8x16_t word =
11499
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11500
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11501
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11502
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11503
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11504
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11505
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11506
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11507
    }
11508
  }
11509
  return size_t(view.size());
11510
}
11511
#elif ADA_SSE2
11512
ada_really_inline size_t find_next_host_delimiter_special(
11513
0
    std::string_view view, size_t location) noexcept {
11514
  // first check for short strings in which case we do it naively.
11515
0
  if (view.size() - location < 16) {  // slow path
11516
0
    for (size_t i = location; i < view.size(); i++) {
11517
0
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11518
0
          view[i] == '?' || view[i] == '[') {
11519
0
        return i;
11520
0
      }
11521
0
    }
11522
0
    return size_t(view.size());
11523
0
  }
11524
  // fast path for long strings (expected to be common)
11525
0
  size_t i = location;
11526
0
  const __m128i mask1 = _mm_set1_epi8(':');
11527
0
  const __m128i mask2 = _mm_set1_epi8('/');
11528
0
  const __m128i mask3 = _mm_set1_epi8('\\');
11529
0
  const __m128i mask4 = _mm_set1_epi8('?');
11530
0
  const __m128i mask5 = _mm_set1_epi8('[');
11531
11532
0
  for (; i + 15 < view.size(); i += 16) {
11533
0
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11534
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11535
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11536
0
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11537
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11538
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11539
0
    __m128i m = _mm_or_si128(
11540
0
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11541
0
    int mask = _mm_movemask_epi8(m);
11542
0
    if (mask != 0) {
11543
0
      return i + trailing_zeroes(mask);
11544
0
    }
11545
0
  }
11546
0
  if (i < view.size()) {
11547
0
    __m128i word =
11548
0
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11549
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11550
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11551
0
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11552
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11553
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11554
0
    __m128i m = _mm_or_si128(
11555
0
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11556
0
    int mask = _mm_movemask_epi8(m);
11557
0
    if (mask != 0) {
11558
0
      return view.length() - 16 + trailing_zeroes(mask);
11559
0
    }
11560
0
  }
11561
0
  return size_t(view.length());
11562
0
}
11563
#elif ADA_LSX
11564
ada_really_inline size_t find_next_host_delimiter_special(
11565
    std::string_view view, size_t location) noexcept {
11566
  // first check for short strings in which case we do it naively.
11567
  if (view.size() - location < 16) {  // slow path
11568
    for (size_t i = location; i < view.size(); i++) {
11569
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11570
          view[i] == '?' || view[i] == '[') {
11571
        return i;
11572
      }
11573
    }
11574
    return size_t(view.size());
11575
  }
11576
  // fast path for long strings (expected to be common)
11577
  size_t i = location;
11578
  const __m128i mask1 = __lsx_vrepli_b(':');
11579
  const __m128i mask2 = __lsx_vrepli_b('/');
11580
  const __m128i mask3 = __lsx_vrepli_b('\\');
11581
  const __m128i mask4 = __lsx_vrepli_b('?');
11582
  const __m128i mask5 = __lsx_vrepli_b('[');
11583
11584
  for (; i + 15 < view.size(); i += 16) {
11585
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11586
    __m128i m1 = __lsx_vseq_b(word, mask1);
11587
    __m128i m2 = __lsx_vseq_b(word, mask2);
11588
    __m128i m3 = __lsx_vseq_b(word, mask3);
11589
    __m128i m4 = __lsx_vseq_b(word, mask4);
11590
    __m128i m5 = __lsx_vseq_b(word, mask5);
11591
    __m128i m =
11592
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11593
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11594
    if (mask != 0) {
11595
      return i + trailing_zeroes(mask);
11596
    }
11597
  }
11598
  if (i < view.size()) {
11599
    __m128i word =
11600
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11601
    __m128i m1 = __lsx_vseq_b(word, mask1);
11602
    __m128i m2 = __lsx_vseq_b(word, mask2);
11603
    __m128i m3 = __lsx_vseq_b(word, mask3);
11604
    __m128i m4 = __lsx_vseq_b(word, mask4);
11605
    __m128i m5 = __lsx_vseq_b(word, mask5);
11606
    __m128i m =
11607
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11608
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11609
    if (mask != 0) {
11610
      return view.length() - 16 + trailing_zeroes(mask);
11611
    }
11612
  }
11613
  return size_t(view.length());
11614
}
11615
#elif ADA_RVV
11616
ada_really_inline size_t find_next_host_delimiter_special(
11617
    std::string_view view, size_t location) noexcept {
11618
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
11619
  // being faster on future hardware.
11620
#if 0
11621
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
11622
  static const uint8_t tbl[16] = {
11623
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
11624
  };
11625
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
11626
#endif
11627
  uint8_t* src = (uint8_t*)view.data() + location;
11628
  for (size_t vl, n = view.size() - location; n > 0;
11629
       n -= vl, src += vl, location += vl) {
11630
    vl = __riscv_vsetvl_e8m1(n);
11631
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11632
#if 0
11633
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
11634
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
11635
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
11636
#else
11637
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11638
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11639
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11640
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11641
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
11642
    vbool8_t m = __riscv_vmor(
11643
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
11644
        m5, vl);
11645
#endif
11646
    long idx = __riscv_vfirst(m, vl);
11647
    if (idx >= 0) return location + idx;
11648
  }
11649
  return size_t(view.size());
11650
}
11651
#else
11652
// : / [ \\ ?
11653
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11654
    []() consteval {
11655
      std::array<uint8_t, 256> result{};
11656
      for (int i : {':', '/', '[', '\\', '?'}) {
11657
        result[i] = 1;
11658
      }
11659
      return result;
11660
    }();
11661
// credit: @the-moisrex recommended a table-based approach
11662
ada_really_inline size_t find_next_host_delimiter_special(
11663
    std::string_view view, size_t location) noexcept {
11664
  auto const str = view.substr(location);
11665
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11666
    if (special_host_delimiters[(uint8_t)*pos]) {
11667
      return pos - str.begin() + location;
11668
    }
11669
  }
11670
  return size_t(view.size());
11671
}
11672
#endif
11673
11674
// starting at index location, this finds the next location of a character
11675
// :, /, ? or [. If none is found, view.size() is returned.
11676
// For use within get_host_delimiter_location.
11677
#if ADA_SSSE3
11678
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11679
                                                  size_t location) noexcept {
11680
  // first check for short strings in which case we do it naively.
11681
  if (view.size() - location < 16) {  // slow path
11682
    for (size_t i = location; i < view.size(); i++) {
11683
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11684
          view[i] == '[') {
11685
        return i;
11686
      }
11687
    }
11688
    return size_t(view.size());
11689
  }
11690
  // fast path for long strings (expected to be common)
11691
  size_t i = location;
11692
  // Lookup tables for bit classification:
11693
  // ':' (0x3A): low[0xA]=0x01, high[0x3]=0x01 -> match
11694
  // '/' (0x2F): low[0xF]=0x02, high[0x2]=0x02 -> match
11695
  // '?' (0x3F): low[0xF]=0x01, high[0x3]=0x01 -> match
11696
  // '[' (0x5B): low[0xB]=0x04, high[0x5]=0x04 -> match
11697
  const __m128i low_mask =
11698
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11699
                    0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11700
  const __m128i high_mask =
11701
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11702
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11703
  const __m128i fmask = _mm_set1_epi8(0xf);
11704
  const __m128i zero = _mm_setzero_si128();
11705
11706
  for (; i + 15 < view.size(); i += 16) {
11707
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11708
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11709
    __m128i highpart = _mm_shuffle_epi8(
11710
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11711
    __m128i classify = _mm_and_si128(lowpart, highpart);
11712
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11713
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11714
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11715
    // avoid false positives.
11716
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11717
    if (mask != 0) {
11718
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11719
    }
11720
  }
11721
11722
  if (i < view.size()) {
11723
    __m128i word =
11724
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11725
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11726
    __m128i highpart = _mm_shuffle_epi8(
11727
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11728
    __m128i classify = _mm_and_si128(lowpart, highpart);
11729
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11730
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11731
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11732
    // avoid false positives.
11733
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11734
    if (mask != 0) {
11735
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11736
    }
11737
  }
11738
  return size_t(view.size());
11739
}
11740
#elif ADA_NEON
11741
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11742
                                                  size_t location) noexcept {
11743
  // first check for short strings in which case we do it naively.
11744
  if (view.size() - location < 16) {  // slow path
11745
    for (size_t i = location; i < view.size(); i++) {
11746
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11747
          view[i] == '[') {
11748
        return i;
11749
      }
11750
    }
11751
    return size_t(view.size());
11752
  }
11753
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11754
    uint8x16_t bit_mask =
11755
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11756
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11757
    uint8x16_t minput = vandq_u8(input, bit_mask);
11758
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11759
    tmp = vpaddq_u8(tmp, tmp);
11760
    tmp = vpaddq_u8(tmp, tmp);
11761
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11762
  };
11763
11764
  // fast path for long strings (expected to be common)
11765
  size_t i = location;
11766
  uint8x16_t low_mask =
11767
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11768
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11769
  uint8x16_t high_mask =
11770
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11771
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11772
  uint8x16_t fmask = vmovq_n_u8(0xf);
11773
  uint8x16_t zero{0};
11774
  for (; i + 15 < view.size(); i += 16) {
11775
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11776
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11777
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11778
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11779
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11780
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11781
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11782
      return i + trailing_zeroes(is_non_zero);
11783
    }
11784
  }
11785
11786
  if (i < view.size()) {
11787
    uint8x16_t word =
11788
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11789
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11790
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11791
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11792
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11793
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11794
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11795
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11796
    }
11797
  }
11798
  return size_t(view.size());
11799
}
11800
#elif ADA_SSE2
11801
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11802
0
                                                  size_t location) noexcept {
11803
  // first check for short strings in which case we do it naively.
11804
0
  if (view.size() - location < 16) {  // slow path
11805
0
    for (size_t i = location; i < view.size(); i++) {
11806
0
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11807
0
          view[i] == '[') {
11808
0
        return i;
11809
0
      }
11810
0
    }
11811
0
    return size_t(view.size());
11812
0
  }
11813
  // fast path for long strings (expected to be common)
11814
0
  size_t i = location;
11815
0
  const __m128i mask1 = _mm_set1_epi8(':');
11816
0
  const __m128i mask2 = _mm_set1_epi8('/');
11817
0
  const __m128i mask4 = _mm_set1_epi8('?');
11818
0
  const __m128i mask5 = _mm_set1_epi8('[');
11819
11820
0
  for (; i + 15 < view.size(); i += 16) {
11821
0
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11822
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11823
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11824
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11825
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11826
0
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11827
0
    int mask = _mm_movemask_epi8(m);
11828
0
    if (mask != 0) {
11829
0
      return i + trailing_zeroes(mask);
11830
0
    }
11831
0
  }
11832
0
  if (i < view.size()) {
11833
0
    __m128i word =
11834
0
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11835
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11836
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11837
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11838
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11839
0
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11840
0
    int mask = _mm_movemask_epi8(m);
11841
0
    if (mask != 0) {
11842
0
      return view.length() - 16 + trailing_zeroes(mask);
11843
0
    }
11844
0
  }
11845
0
  return size_t(view.length());
11846
0
}
11847
#elif ADA_LSX
11848
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11849
                                                  size_t location) noexcept {
11850
  // first check for short strings in which case we do it naively.
11851
  if (view.size() - location < 16) {  // slow path
11852
    for (size_t i = location; i < view.size(); i++) {
11853
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11854
          view[i] == '[') {
11855
        return i;
11856
      }
11857
    }
11858
    return size_t(view.size());
11859
  }
11860
  // fast path for long strings (expected to be common)
11861
  size_t i = location;
11862
  const __m128i mask1 = __lsx_vrepli_b(':');
11863
  const __m128i mask2 = __lsx_vrepli_b('/');
11864
  const __m128i mask4 = __lsx_vrepli_b('?');
11865
  const __m128i mask5 = __lsx_vrepli_b('[');
11866
11867
  for (; i + 15 < view.size(); i += 16) {
11868
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11869
    __m128i m1 = __lsx_vseq_b(word, mask1);
11870
    __m128i m2 = __lsx_vseq_b(word, mask2);
11871
    __m128i m4 = __lsx_vseq_b(word, mask4);
11872
    __m128i m5 = __lsx_vseq_b(word, mask5);
11873
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11874
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11875
    if (mask != 0) {
11876
      return i + trailing_zeroes(mask);
11877
    }
11878
  }
11879
  if (i < view.size()) {
11880
    __m128i word =
11881
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11882
    __m128i m1 = __lsx_vseq_b(word, mask1);
11883
    __m128i m2 = __lsx_vseq_b(word, mask2);
11884
    __m128i m4 = __lsx_vseq_b(word, mask4);
11885
    __m128i m5 = __lsx_vseq_b(word, mask5);
11886
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11887
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11888
    if (mask != 0) {
11889
      return view.length() - 16 + trailing_zeroes(mask);
11890
    }
11891
  }
11892
  return size_t(view.length());
11893
}
11894
#elif ADA_RVV
11895
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11896
                                                  size_t location) noexcept {
11897
  uint8_t* src = (uint8_t*)view.data() + location;
11898
  for (size_t vl, n = view.size() - location; n > 0;
11899
       n -= vl, src += vl, location += vl) {
11900
    vl = __riscv_vsetvl_e8m1(n);
11901
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11902
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11903
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11904
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11905
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11906
    vbool8_t m =
11907
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
11908
    long idx = __riscv_vfirst(m, vl);
11909
    if (idx >= 0) return location + idx;
11910
  }
11911
  return size_t(view.size());
11912
}
11913
#else
11914
// : / [ ?
11915
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11916
  std::array<uint8_t, 256> result{};
11917
  for (int i : {':', '/', '?', '['}) {
11918
    result[i] = 1;
11919
  }
11920
  return result;
11921
}();
11922
// credit: @the-moisrex recommended a table-based approach
11923
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11924
                                                  size_t location) noexcept {
11925
  auto const str = view.substr(location);
11926
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11927
    if (host_delimiters[(uint8_t)*pos]) {
11928
      return pos - str.begin() + location;
11929
    }
11930
  }
11931
  return size_t(view.size());
11932
}
11933
#endif
11934
11935
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11936
0
    const bool is_special, std::string_view& view) noexcept {
11937
  /**
11938
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11939
   * compute a variable called insideBrackets but this variable is only used
11940
   * once, to check whether a ':' character was found outside brackets. Exact
11941
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11942
   * It is conceptually simpler and arguably more efficient to just return a
11943
   * Boolean indicating whether ':' was found outside brackets.
11944
   */
11945
0
  const size_t view_size = view.size();
11946
0
  size_t location = 0;
11947
0
  bool found_colon = false;
11948
  /**
11949
   * Performance analysis:
11950
   *
11951
   * We are basically seeking the end of the hostname which can be indicated
11952
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11953
   * (where '\\' is only applicable for special URLs). However, these must
11954
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11955
   * '?' does not count.
11956
   *
11957
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11958
   * the set of delimiters, and that we handle it first.
11959
   *
11960
   * So the trick is to have a fast function that locates the next delimiter.
11961
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11962
   * function would be provided by the C++ standard library, but it seems that
11963
   * find_first_of is not very fast, so we are forced to roll our own.
11964
   *
11965
   * We do not break into two loops for speed, but for clarity.
11966
   */
11967
0
  if (is_special) {
11968
    // We move to the next delimiter.
11969
0
    location = find_next_host_delimiter_special(view, location);
11970
    // Unless we find '[' then we are going only going to have to call
11971
    // find_next_host_delimiter_special once.
11972
0
    for (; location < view_size;
11973
0
         location = find_next_host_delimiter_special(view, location)) {
11974
0
      if (view[location] == '[') {
11975
0
        location = view.find(']', location);
11976
0
        if (location == std::string_view::npos) {
11977
          // performance: view.find might get translated to a memchr, which
11978
          // has no notion of std::string_view::npos, so the code does not
11979
          // reflect the assembly.
11980
0
          location = view_size;
11981
0
          break;
11982
0
        }
11983
0
      } else {
11984
0
        found_colon = view[location] == ':';
11985
0
        break;
11986
0
      }
11987
0
    }
11988
0
  } else {
11989
    // We move to the next delimiter.
11990
0
    location = find_next_host_delimiter(view, location);
11991
    // Unless we find '[' then we are going only going to have to call
11992
    // find_next_host_delimiter_special once.
11993
0
    for (; location < view_size;
11994
0
         location = find_next_host_delimiter(view, location)) {
11995
0
      if (view[location] == '[') {
11996
0
        location = view.find(']', location);
11997
0
        if (location == std::string_view::npos) {
11998
          // performance: view.find might get translated to a memchr, which
11999
          // has no notion of std::string_view::npos, so the code does not
12000
          // reflect the assembly.
12001
0
          location = view_size;
12002
0
          break;
12003
0
        }
12004
0
      } else {
12005
0
        found_colon = view[location] == ':';
12006
0
        break;
12007
0
      }
12008
0
    }
12009
0
  }
12010
  // performance: remove_suffix may translate into a single instruction.
12011
0
  view.remove_suffix(view_size - location);
12012
0
  return {location, found_colon};
12013
0
}
12014
12015
0
void trim_c0_whitespace(std::string_view& input) noexcept {
12016
0
  while (!input.empty() &&
12017
0
         ada::unicode::is_c0_control_or_space(input.front())) {
12018
0
    input.remove_prefix(1);
12019
0
  }
12020
0
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
12021
0
    input.remove_suffix(1);
12022
0
  }
12023
0
}
12024
12025
ada_really_inline void parse_prepared_path(std::string_view input,
12026
                                           ada::scheme::type type,
12027
0
                                           std::string& path) {
12028
0
  ada_log("parse_prepared_path ", input);
12029
0
  uint8_t accumulator = checkers::path_signature(input);
12030
  // Let us first detect a trivial case.
12031
  // If it is special, we check that we have no dot, no %,  no \ and no
12032
  // character needing percent encoding. Otherwise, we check that we have no %,
12033
  // no dot, and no character needing percent encoding.
12034
0
  constexpr uint8_t need_encoding = 1;
12035
0
  constexpr uint8_t backslash_char = 2;
12036
0
  constexpr uint8_t dot_char = 4;
12037
0
  constexpr uint8_t percent_char = 8;
12038
0
  bool special = type != ada::scheme::NOT_SPECIAL;
12039
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12040
0
                                      checkers::is_windows_drive_letter(input));
12041
0
  bool trivial_path =
12042
0
      (special ? (accumulator == 0)
12043
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12044
0
                  0)) &&
12045
0
      (!may_need_slow_file_handling);
12046
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
12047
    // '4' means that we have at least one dot, but nothing that requires
12048
    // percent encoding or decoding. The only part that is not trivial is
12049
    // that we may have single dots and double dots path segments.
12050
    // If we have such segments, then we either have a path that begins
12051
    // with '.' (easy to check), or we have the sequence './'.
12052
    // Note: input cannot be empty, it must at least contain one character ('.')
12053
    // Note: we know that '\' is not present.
12054
0
    if (input[0] != '.') {
12055
0
      size_t slashdot = 0;
12056
0
      bool dot_is_file = true;
12057
0
      for (;;) {
12058
0
        slashdot = input.find("/.", slashdot);
12059
0
        if (slashdot == std::string_view::npos) {  // common case
12060
0
          break;
12061
0
        } else {  // uncommon
12062
          // only three cases matter: /./, /.. or a final /
12063
0
          slashdot += 2;
12064
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12065
0
                           input[slashdot] == '/');
12066
0
        }
12067
0
      }
12068
0
      trivial_path = dot_is_file;
12069
0
    }
12070
0
  }
12071
0
  if (trivial_path) {
12072
0
    ada_log("parse_path trivial");
12073
0
    path += '/';
12074
0
    path += input;
12075
0
    return;
12076
0
  }
12077
  // We are going to need to look a bit at the path, but let us see if we can
12078
  // ignore percent encoding *and* backslashes *and* percent characters.
12079
  // Except for the trivial case, this is likely to capture 99% of paths out
12080
  // there.
12081
0
  bool fast_path =
12082
0
      (special &&
12083
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12084
0
      (type != ada::scheme::type::FILE);
12085
0
  if (fast_path) {
12086
0
    ada_log("parse_prepared_path fast");
12087
    // Here we don't need to worry about \ or percent encoding.
12088
    // We also do not have a file protocol. We might have dots, however,
12089
    // but dots must as appear as '.', and they cannot be encoded because
12090
    // the symbol '%' is not present.
12091
0
    size_t previous_location = 0;  // We start at 0.
12092
0
    do {
12093
0
      size_t new_location = input.find('/', previous_location);
12094
      // std::string_view path_view = input;
12095
      //  We process the last segment separately:
12096
0
      if (new_location == std::string_view::npos) {
12097
0
        std::string_view path_view = input.substr(previous_location);
12098
0
        if (path_view == "..") {  // The path ends with ..
12099
          // e.g., if you receive ".." with an empty path, you go to "/".
12100
0
          if (path.empty()) {
12101
0
            path = '/';
12102
0
            return;
12103
0
          }
12104
          // Fast case where we have nothing to do:
12105
0
          if (path.back() == '/') {
12106
0
            return;
12107
0
          }
12108
          // If you have the path "/joe/myfriend",
12109
          // then you delete 'myfriend'.
12110
0
          path.resize(path.rfind('/') + 1);
12111
0
          return;
12112
0
        }
12113
0
        path += '/';
12114
0
        if (path_view != ".") {
12115
0
          path.append(path_view);
12116
0
        }
12117
0
        return;
12118
0
      } else {
12119
        // This is a non-final segment.
12120
0
        std::string_view path_view =
12121
0
            input.substr(previous_location, new_location - previous_location);
12122
0
        previous_location = new_location + 1;
12123
0
        if (path_view == "..") {
12124
0
          size_t last_delimiter = path.rfind('/');
12125
0
          if (last_delimiter != std::string::npos) {
12126
0
            path.erase(last_delimiter);
12127
0
          }
12128
0
        } else if (path_view != ".") {
12129
0
          path += '/';
12130
0
          path.append(path_view);
12131
0
        }
12132
0
      }
12133
0
    } while (true);
12134
0
  } else {
12135
0
    ada_log("parse_path slow");
12136
    // we have reached the general case
12137
0
    bool needs_percent_encoding = (accumulator & 1);
12138
0
    std::string path_buffer_tmp;
12139
0
    do {
12140
0
      size_t location = (special && (accumulator & 2))
12141
0
                            ? input.find_first_of("/\\")
12142
0
                            : input.find('/');
12143
0
      std::string_view path_view = input;
12144
0
      if (location != std::string_view::npos) {
12145
0
        path_view.remove_suffix(path_view.size() - location);
12146
0
        input.remove_prefix(location + 1);
12147
0
      }
12148
      // path_buffer is either path_view or it might point at a percent encoded
12149
      // temporary file.
12150
0
      std::string_view path_buffer =
12151
0
          (needs_percent_encoding &&
12152
0
           ada::unicode::percent_encode<false>(
12153
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12154
0
              ? path_buffer_tmp
12155
0
              : path_view;
12156
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12157
0
        helpers::shorten_path(path, type);
12158
0
        if (location == std::string_view::npos) {
12159
0
          path += '/';
12160
0
        }
12161
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12162
0
                 (location == std::string_view::npos)) {
12163
0
        path += '/';
12164
0
      }
12165
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12166
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
12167
        // If url's scheme is "file", url's path is empty, and path_buffer is a
12168
        // Windows drive letter, then replace the second code point in
12169
        // path_buffer with U+003A (:).
12170
0
        if (type == ada::scheme::type::FILE && path.empty() &&
12171
0
            checkers::is_windows_drive_letter(path_buffer)) {
12172
0
          path += '/';
12173
0
          path += path_buffer[0];
12174
0
          path += ':';
12175
0
          path_buffer.remove_prefix(2);
12176
0
          path.append(path_buffer);
12177
0
        } else {
12178
          // Append path_buffer to url's path.
12179
0
          path += '/';
12180
0
          path.append(path_buffer);
12181
0
        }
12182
0
      }
12183
0
      if (location == std::string_view::npos) {
12184
0
        return;
12185
0
      }
12186
0
    } while (true);
12187
0
  }
12188
0
}
12189
12190
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12191
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12192
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12193
0
          input2.size(), " bytes]");
12194
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12195
0
         input1.data() < input2.data() + input2.size();
12196
0
}
12197
12198
template <class url_type>
12199
0
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12200
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12201
0
  if (!url.has_opaque_path) return;
12202
0
  if (url.has_hash()) return;
12203
0
  if (url.has_search()) return;
12204
12205
0
  auto path = std::string(url.get_pathname());
12206
0
  while (!path.empty() && path.back() == ' ') {
12207
0
    path.resize(path.size() - 1);
12208
0
  }
12209
0
  url.update_base_pathname(path);
12210
0
}
Unexecuted instantiation: void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Unexecuted instantiation: void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
12211
12212
// @ / \\ ?
12213
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12214
    []() consteval {
12215
      std::array<uint8_t, 256> result{};
12216
      for (uint8_t i : {'@', '/', '\\', '?'}) {
12217
        result[i] = 1;
12218
      }
12219
      return result;
12220
    }();
12221
// credit: @the-moisrex recommended a table-based approach
12222
ada_really_inline size_t
12223
0
find_authority_delimiter_special(std::string_view view) noexcept {
12224
  // performance note: we might be able to gain further performance
12225
  // with SIMD intrinsics.
12226
0
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12227
0
    if (authority_delimiter_special[(uint8_t)*pos]) {
12228
0
      return pos - view.begin();
12229
0
    }
12230
0
  }
12231
0
  return size_t(view.size());
12232
0
}
12233
12234
// @ / ?
12235
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12236
  std::array<uint8_t, 256> result{};
12237
  for (uint8_t i : {'@', '/', '?'}) {
12238
    result[i] = 1;
12239
  }
12240
  return result;
12241
}();
12242
// credit: @the-moisrex recommended a table-based approach
12243
ada_really_inline size_t
12244
0
find_authority_delimiter(std::string_view view) noexcept {
12245
  // performance note: we might be able to gain further performance
12246
  // with SIMD instrinsics.
12247
0
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12248
0
    if (authority_delimiter[(uint8_t)*pos]) {
12249
0
      return pos - view.begin();
12250
0
    }
12251
0
  }
12252
0
  return size_t(view.size());
12253
0
}
12254
12255
}  // namespace ada::helpers
12256
12257
namespace ada {
12258
0
ada_warn_unused std::string to_string(ada::state state) {
12259
0
  return ada::helpers::get_state(state);
12260
0
}
12261
#undef ada_make_uint8x16_t
12262
}  // namespace ada
12263
/* end file src/helpers.cpp */
12264
/* begin file src/url.cpp */
12265
12266
#include <numeric>
12267
#include <algorithm>
12268
#include <iterator>
12269
#include <ranges>
12270
#include <string>
12271
#include <string_view>
12272
12273
namespace ada {
12274
12275
0
bool url::parse_opaque_host(std::string_view input) {
12276
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12277
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12278
0
    return is_valid = false;
12279
0
  }
12280
12281
  // Return the result of running UTF-8 percent-encode on input using the C0
12282
  // control percent-encode set.
12283
0
  host = ada::unicode::percent_encode(
12284
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12285
0
  return true;
12286
0
}
12287
12288
0
bool url::parse_ipv4(std::string_view input) {
12289
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12290
0
  if (input.back() == '.') {
12291
0
    input.remove_suffix(1);
12292
0
  }
12293
0
  size_t digit_count{0};
12294
0
  int pure_decimal_count = 0;  // entries that are decimal
12295
0
  std::string_view original_input =
12296
0
      input;  // we might use this if pure_decimal_count == 4.
12297
0
  uint64_t ipv4{0};
12298
  // we could unroll for better performance?
12299
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12300
0
    uint32_t
12301
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12302
0
    bool is_hex = checkers::has_hex_prefix(input);
12303
0
    if (is_hex && ((input.length() == 2) ||
12304
0
                   ((input.length() > 2) && (input[2] == '.')))) {
12305
      // special case
12306
0
      segment_result = 0;
12307
0
      input.remove_prefix(2);
12308
0
    } else {
12309
0
      std::from_chars_result r{};
12310
0
      if (is_hex) {
12311
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12312
0
                            segment_result, 16);
12313
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
12314
0
                 checkers::is_digit(input[1])) {
12315
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12316
0
                            segment_result, 8);
12317
0
      } else {
12318
0
        pure_decimal_count++;
12319
0
        r = std::from_chars(input.data(), input.data() + input.size(),
12320
0
                            segment_result, 10);
12321
0
      }
12322
0
      if (r.ec != std::errc()) {
12323
0
        return is_valid = false;
12324
0
      }
12325
0
      input.remove_prefix(r.ptr - input.data());
12326
0
    }
12327
0
    if (input.empty()) {
12328
      // We have the last value.
12329
      // At this stage, ipv4 contains digit_count*8 bits.
12330
      // So we have 32-digit_count*8 bits left.
12331
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12332
0
        return is_valid = false;
12333
0
      }
12334
0
      ipv4 <<= (32 - digit_count * 8);
12335
0
      ipv4 |= segment_result;
12336
0
      goto final;
12337
0
    } else {
12338
      // There is more, so that the value must no be larger than 255
12339
      // and we must have a '.'.
12340
0
      if ((segment_result > 255) || (input[0] != '.')) {
12341
0
        return is_valid = false;
12342
0
      }
12343
0
      ipv4 <<= 8;
12344
0
      ipv4 |= segment_result;
12345
0
      input.remove_prefix(1);  // remove '.'
12346
0
    }
12347
0
  }
12348
0
  if ((digit_count != 4) || (!input.empty())) {
12349
0
    return is_valid = false;
12350
0
  }
12351
0
final:
12352
  // We could also check r.ptr to see where the parsing ended.
12353
0
  if (pure_decimal_count == 4) {
12354
0
    host = original_input;  // The original input was already all decimal and we
12355
                            // validated it.
12356
0
  } else {
12357
0
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12358
0
  }
12359
0
  host_type = IPV4;
12360
0
  return true;
12361
0
}
12362
12363
0
bool url::parse_ipv6(std::string_view input) {
12364
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12365
12366
0
  if (input.empty()) {
12367
0
    return is_valid = false;
12368
0
  }
12369
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12370
0
  std::array<uint16_t, 8> address{};
12371
12372
  // Let pieceIndex be 0.
12373
0
  int piece_index = 0;
12374
12375
  // Let compress be null.
12376
0
  std::optional<int> compress{};
12377
12378
  // Let pointer be a pointer for input.
12379
0
  std::string_view::iterator pointer = input.begin();
12380
12381
  // If c is U+003A (:), then:
12382
0
  if (input[0] == ':') {
12383
    // If remaining does not start with U+003A (:), validation error, return
12384
    // failure.
12385
0
    if (input.size() == 1 || input[1] != ':') {
12386
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12387
0
      return is_valid = false;
12388
0
    }
12389
12390
    // Increase pointer by 2.
12391
0
    pointer += 2;
12392
12393
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12394
0
    compress = ++piece_index;
12395
0
  }
12396
12397
  // While c is not the EOF code point:
12398
0
  while (pointer != input.end()) {
12399
    // If pieceIndex is 8, validation error, return failure.
12400
0
    if (piece_index == 8) {
12401
0
      ada_log("parse_ipv6 piece_index == 8");
12402
0
      return is_valid = false;
12403
0
    }
12404
12405
    // If c is U+003A (:), then:
12406
0
    if (*pointer == ':') {
12407
      // If compress is non-null, validation error, return failure.
12408
0
      if (compress.has_value()) {
12409
0
        ada_log("parse_ipv6 compress is non-null");
12410
0
        return is_valid = false;
12411
0
      }
12412
12413
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12414
      // then continue.
12415
0
      pointer++;
12416
0
      compress = ++piece_index;
12417
0
      continue;
12418
0
    }
12419
12420
    // Let value and length be 0.
12421
0
    uint16_t value = 0, length = 0;
12422
12423
    // While length is less than 4 and c is an ASCII hex digit,
12424
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12425
    // increase pointer and length by 1.
12426
0
    while (length < 4 && pointer != input.end() &&
12427
0
           unicode::is_ascii_hex_digit(*pointer)) {
12428
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12429
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12430
0
      pointer++;
12431
0
      length++;
12432
0
    }
12433
12434
    // If c is U+002E (.), then:
12435
0
    if (pointer != input.end() && *pointer == '.') {
12436
      // If length is 0, validation error, return failure.
12437
0
      if (length == 0) {
12438
0
        ada_log("parse_ipv6 length is 0");
12439
0
        return is_valid = false;
12440
0
      }
12441
12442
      // Decrease pointer by length.
12443
0
      pointer -= length;
12444
12445
      // If pieceIndex is greater than 6, validation error, return failure.
12446
0
      if (piece_index > 6) {
12447
0
        ada_log("parse_ipv6 piece_index > 6");
12448
0
        return is_valid = false;
12449
0
      }
12450
12451
      // Let numbersSeen be 0.
12452
0
      int numbers_seen = 0;
12453
12454
      // While c is not the EOF code point:
12455
0
      while (pointer != input.end()) {
12456
        // Let ipv4Piece be null.
12457
0
        std::optional<uint16_t> ipv4_piece{};
12458
12459
        // If numbersSeen is greater than 0, then:
12460
0
        if (numbers_seen > 0) {
12461
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12462
          // pointer by 1.
12463
0
          if (*pointer == '.' && numbers_seen < 4) {
12464
0
            pointer++;
12465
0
          }
12466
          // Otherwise, validation error, return failure.
12467
0
          else {
12468
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12469
0
            return is_valid = false;
12470
0
          }
12471
0
        }
12472
12473
        // If c is not an ASCII digit, validation error, return failure.
12474
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12475
0
          ada_log(
12476
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12477
0
              "failure");
12478
0
          return is_valid = false;
12479
0
        }
12480
12481
        // While c is an ASCII digit:
12482
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12483
          // Let number be c interpreted as decimal number.
12484
0
          int number = *pointer - '0';
12485
12486
          // If ipv4Piece is null, then set ipv4Piece to number.
12487
0
          if (!ipv4_piece.has_value()) {
12488
0
            ipv4_piece = number;
12489
0
          }
12490
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12491
0
          else if (ipv4_piece == 0) {
12492
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12493
0
            return is_valid = false;
12494
0
          }
12495
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12496
0
          else {
12497
0
            ipv4_piece = *ipv4_piece * 10 + number;
12498
0
          }
12499
12500
          // If ipv4Piece is greater than 255, validation error, return failure.
12501
0
          if (ipv4_piece > 255) {
12502
0
            ada_log("parse_ipv6 ipv4_piece > 255");
12503
0
            return is_valid = false;
12504
0
          }
12505
12506
          // Increase pointer by 1.
12507
0
          pointer++;
12508
0
        }
12509
12510
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12511
        // ipv4Piece.
12512
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12513
0
        address[piece_index] =
12514
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12515
12516
        // Increase numbersSeen by 1.
12517
0
        numbers_seen++;
12518
12519
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12520
0
        if (numbers_seen == 2 || numbers_seen == 4) {
12521
0
          piece_index++;
12522
0
        }
12523
0
      }
12524
12525
      // If numbersSeen is not 4, validation error, return failure.
12526
0
      if (numbers_seen != 4) {
12527
0
        return is_valid = false;
12528
0
      }
12529
12530
      // Break.
12531
0
      break;
12532
0
    }
12533
    // Otherwise, if c is U+003A (:):
12534
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
12535
      // Increase pointer by 1.
12536
0
      pointer++;
12537
12538
      // If c is the EOF code point, validation error, return failure.
12539
0
      if (pointer == input.end()) {
12540
0
        ada_log(
12541
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
12542
0
            "failure");
12543
0
        return is_valid = false;
12544
0
      }
12545
0
    }
12546
    // Otherwise, if c is not the EOF code point, validation error, return
12547
    // failure.
12548
0
    else if (pointer != input.end()) {
12549
0
      ada_log(
12550
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12551
0
          "error, return failure");
12552
0
      return is_valid = false;
12553
0
    }
12554
12555
    // Set address[pieceIndex] to value.
12556
0
    address[piece_index] = value;
12557
12558
    // Increase pieceIndex by 1.
12559
0
    piece_index++;
12560
0
  }
12561
12562
  // If compress is non-null, then:
12563
0
  if (compress.has_value()) {
12564
    // Let swaps be pieceIndex - compress.
12565
0
    int swaps = piece_index - *compress;
12566
12567
    // Set pieceIndex to 7.
12568
0
    piece_index = 7;
12569
12570
    // While pieceIndex is not 0 and swaps is greater than 0,
12571
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12572
    // decrease both pieceIndex and swaps by 1.
12573
0
    while (piece_index != 0 && swaps > 0) {
12574
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12575
0
      piece_index--;
12576
0
      swaps--;
12577
0
    }
12578
0
  }
12579
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12580
  // return failure.
12581
0
  else if (piece_index != 8) {
12582
0
    ada_log(
12583
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12584
0
        "error, return failure");
12585
0
    return is_valid = false;
12586
0
  }
12587
0
  host = ada::serializers::ipv6(address);
12588
0
  ada_log("parse_ipv6 ", *host);
12589
0
  host_type = IPV6;
12590
0
  return true;
12591
0
}
12592
12593
template <bool has_state_override>
12594
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12595
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
12596
0
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12597
  /**
12598
   * In the common case, we will immediately recognize a special scheme (e.g.,
12599
   *http, https), in which case, we can go really fast.
12600
   **/
12601
0
  if (is_input_special) {  // fast path!!!
12602
0
    if constexpr (has_state_override) {
12603
      // If url's scheme is not a special scheme and buffer is a special scheme,
12604
      // then return.
12605
0
      if (is_special() != is_input_special) {
12606
0
        return false;
12607
0
      }
12608
12609
      // If url includes credentials or has a non-null port, and buffer is
12610
      // "file", then return.
12611
0
      if ((has_credentials() || port.has_value()) &&
12612
0
          parsed_type == ada::scheme::type::FILE) {
12613
0
        return false;
12614
0
      }
12615
12616
      // If url's scheme is "file" and its host is an empty host, then return.
12617
      // An empty host is the empty string.
12618
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12619
0
          host.value().empty()) {
12620
0
        return false;
12621
0
      }
12622
0
    }
12623
12624
0
    type = parsed_type;
12625
12626
0
    if constexpr (has_state_override) {
12627
      // This is uncommon.
12628
0
      uint16_t urls_scheme_port = get_special_port();
12629
12630
0
      if (urls_scheme_port) {
12631
        // If url's port is url's scheme's default port, then set url's port to
12632
        // null.
12633
0
        if (port.has_value() && *port == urls_scheme_port) {
12634
0
          port = std::nullopt;
12635
0
        }
12636
0
      }
12637
0
    }
12638
0
  } else {  // slow path
12639
0
    std::string _buffer(input);
12640
    // Next function is only valid if the input is ASCII and returns false
12641
    // otherwise, but it seems that we always have ascii content so we do not
12642
    // need to check the return value.
12643
    // bool is_ascii =
12644
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12645
12646
0
    if constexpr (has_state_override) {
12647
      // If url's scheme is a special scheme and buffer is not a special scheme,
12648
      // then return. If url's scheme is not a special scheme and buffer is a
12649
      // special scheme, then return.
12650
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
12651
0
        return true;
12652
0
      }
12653
12654
      // If url includes credentials or has a non-null port, and buffer is
12655
      // "file", then return.
12656
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12657
0
        return true;
12658
0
      }
12659
12660
      // If url's scheme is "file" and its host is an empty host, then return.
12661
      // An empty host is the empty string.
12662
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12663
0
          host.value().empty()) {
12664
0
        return true;
12665
0
      }
12666
0
    }
12667
12668
0
    set_scheme(std::move(_buffer));
12669
12670
0
    if constexpr (has_state_override) {
12671
      // This is uncommon.
12672
0
      uint16_t urls_scheme_port = get_special_port();
12673
12674
0
      if (urls_scheme_port) {
12675
        // If url's port is url's scheme's default port, then set url's port to
12676
        // null.
12677
0
        if (port.has_value() && *port == urls_scheme_port) {
12678
0
          port = std::nullopt;
12679
0
        }
12680
0
      }
12681
0
    }
12682
0
  }
12683
12684
0
  return true;
12685
0
}
Unexecuted instantiation: bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
12686
12687
0
ada_really_inline bool url::parse_host(std::string_view input) {
12688
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12689
0
  if (input.empty()) {
12690
0
    return is_valid = false;
12691
0
  }  // technically unnecessary.
12692
  // If input starts with U+005B ([), then:
12693
0
  if (input[0] == '[') {
12694
    // If input does not end with U+005D (]), validation error, return failure.
12695
0
    if (input.back() != ']') {
12696
0
      return is_valid = false;
12697
0
    }
12698
0
    ada_log("parse_host ipv6");
12699
12700
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12701
    // trailing U+005D (]) removed.
12702
0
    input.remove_prefix(1);
12703
0
    input.remove_suffix(1);
12704
0
    return parse_ipv6(input);
12705
0
  }
12706
12707
  // If isNotSpecial is true, then return the result of opaque-host parsing
12708
  // input.
12709
0
  if (!is_special()) {
12710
0
    return parse_opaque_host(input);
12711
0
  }
12712
12713
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
12714
0
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
12715
0
  if (fast_result < checkers::ipv4_fast_fail) {
12716
    // Fast path succeeded - input is pure decimal IPv4
12717
0
    if (!input.empty() && input.back() == '.') {
12718
0
      host = input.substr(0, input.size() - 1);
12719
0
    } else {
12720
0
      host = input;
12721
0
    }
12722
0
    host_type = IPV4;
12723
0
    ada_log("parse_host fast path decimal ipv4");
12724
0
    return true;
12725
0
  }
12726
  // Let domain be the result of running UTF-8 decode without BOM on the
12727
  // percent-decoding of input. Let asciiDomain be the result of running domain
12728
  // to ASCII with domain and false. The most common case is an ASCII input, in
12729
  // which case we do not need to call the expensive 'to_ascii' if a few
12730
  // conditions are met: no '%' and no 'xn-' subsequence.
12731
0
  std::string buffer = std::string(input);
12732
  // This next function checks that the result is ascii, but we are going to
12733
  // to check anyhow with is_forbidden.
12734
  // bool is_ascii =
12735
0
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12736
0
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12737
0
      buffer.data(), buffer.size());
12738
0
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12739
    // fast path
12740
0
    host = std::move(buffer);
12741
12742
    // Check for other IPv4 formats (hex, octal, etc.)
12743
0
    if (checkers::is_ipv4(host.value())) {
12744
0
      ada_log("parse_host fast path ipv4");
12745
0
      return parse_ipv4(host.value());
12746
0
    }
12747
0
    ada_log("parse_host fast path ", *host);
12748
0
    return true;
12749
0
  }
12750
0
  ada_log("parse_host calling to_ascii");
12751
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12752
0
  if (!is_valid) {
12753
0
    ada_log("parse_host to_ascii returns false");
12754
0
    return is_valid = false;
12755
0
  }
12756
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12757
0
          " bytes]");
12758
12759
0
  if (std::any_of(host.value().begin(), host.value().end(),
12760
0
                  ada::unicode::is_forbidden_domain_code_point)) {
12761
0
    host = std::nullopt;
12762
0
    return is_valid = false;
12763
0
  }
12764
12765
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12766
  // asciiDomain.
12767
0
  if (checkers::is_ipv4(host.value())) {
12768
0
    ada_log("parse_host got ipv4 ", *host);
12769
0
    return parse_ipv4(host.value());
12770
0
  }
12771
12772
0
  return true;
12773
0
}
12774
12775
0
ada_really_inline void url::parse_path(std::string_view input) {
12776
0
  ada_log("parse_path ", input);
12777
0
  std::string tmp_buffer;
12778
0
  std::string_view internal_input;
12779
0
  if (unicode::has_tabs_or_newline(input)) {
12780
0
    tmp_buffer = input;
12781
    // Optimization opportunity: Instead of copying and then pruning, we could
12782
    // just directly build the string from user_input.
12783
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12784
0
    internal_input = tmp_buffer;
12785
0
  } else {
12786
0
    internal_input = input;
12787
0
  }
12788
12789
  // If url is special, then:
12790
0
  if (is_special()) {
12791
0
    if (internal_input.empty()) {
12792
0
      path = "/";
12793
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12794
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12795
0
    } else {
12796
0
      helpers::parse_prepared_path(internal_input, type, path);
12797
0
    }
12798
0
  } else if (!internal_input.empty()) {
12799
0
    if (internal_input[0] == '/') {
12800
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12801
0
    } else {
12802
0
      helpers::parse_prepared_path(internal_input, type, path);
12803
0
    }
12804
0
  } else {
12805
0
    if (!host.has_value()) {
12806
0
      path = "/";
12807
0
    }
12808
0
  }
12809
0
}
12810
12811
0
[[nodiscard]] std::string url::to_string() const {
12812
0
  if (!is_valid) {
12813
0
    return "null";
12814
0
  }
12815
0
  std::string answer;
12816
0
  auto back = std::back_insert_iterator(answer);
12817
0
  answer.append("{\n");
12818
0
  answer.append("\t\"protocol\":\"");
12819
0
  helpers::encode_json(get_protocol(), back);
12820
0
  answer.append("\",\n");
12821
0
  if (has_credentials()) {
12822
0
    answer.append("\t\"username\":\"");
12823
0
    helpers::encode_json(username, back);
12824
0
    answer.append("\",\n");
12825
0
    answer.append("\t\"password\":\"");
12826
0
    helpers::encode_json(password, back);
12827
0
    answer.append("\",\n");
12828
0
  }
12829
0
  if (host.has_value()) {
12830
0
    answer.append("\t\"host\":\"");
12831
0
    helpers::encode_json(host.value(), back);
12832
0
    answer.append("\",\n");
12833
0
  }
12834
0
  if (port.has_value()) {
12835
0
    answer.append("\t\"port\":\"");
12836
0
    answer.append(std::to_string(port.value()));
12837
0
    answer.append("\",\n");
12838
0
  }
12839
0
  answer.append("\t\"path\":\"");
12840
0
  helpers::encode_json(path, back);
12841
0
  answer.append("\",\n");
12842
0
  answer.append("\t\"opaque path\":");
12843
0
  answer.append((has_opaque_path ? "true" : "false"));
12844
0
  if (has_search()) {
12845
0
    answer.append(",\n");
12846
0
    answer.append("\t\"query\":\"");
12847
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12848
0
    helpers::encode_json(query.value(), back);
12849
0
    answer.append("\"");
12850
0
  }
12851
0
  if (hash.has_value()) {
12852
0
    answer.append(",\n");
12853
0
    answer.append("\t\"hash\":\"");
12854
0
    helpers::encode_json(hash.value(), back);
12855
0
    answer.append("\"");
12856
0
  }
12857
0
  answer.append("\n}");
12858
0
  return answer;
12859
0
}
12860
12861
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12862
0
  if (!host.has_value()) {
12863
0
    return false;
12864
0
  }
12865
0
  return checkers::verify_dns_length(host.value());
12866
0
}
12867
12868
0
[[nodiscard]] std::string url::get_origin() const {
12869
0
  if (is_special()) {
12870
    // Return a new opaque origin.
12871
0
    if (type == scheme::FILE) {
12872
0
      return "null";
12873
0
    }
12874
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
12875
0
  }
12876
12877
0
  if (non_special_scheme == "blob") {
12878
0
    if (!path.empty()) {
12879
0
      auto result = ada::parse<ada::url>(path);
12880
0
      if (result &&
12881
0
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12882
        // If pathURL's scheme is not "http" and not "https", then return a
12883
        // new opaque origin.
12884
0
        return ada::helpers::concat(result->get_protocol(), "//",
12885
0
                                    result->get_host());
12886
0
      }
12887
0
    }
12888
0
  }
12889
12890
  // Return a new opaque origin.
12891
0
  return "null";
12892
0
}
12893
12894
0
[[nodiscard]] std::string url::get_protocol() const {
12895
0
  if (is_special()) {
12896
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12897
0
  }
12898
  // We only move the 'scheme' if it is non-special.
12899
0
  return helpers::concat(non_special_scheme, ":");
12900
0
}
12901
12902
0
[[nodiscard]] std::string url::get_host() const {
12903
  // If url's host is null, then return the empty string.
12904
  // If url's port is null, return url's host, serialized.
12905
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12906
  // serialized.
12907
0
  if (!host.has_value()) {
12908
0
    return "";
12909
0
  }
12910
0
  if (port.has_value()) {
12911
0
    return host.value() + ":" + get_port();
12912
0
  }
12913
0
  return host.value();
12914
0
}
12915
12916
0
[[nodiscard]] std::string url::get_hostname() const {
12917
0
  return host.value_or("");
12918
0
}
12919
12920
0
[[nodiscard]] std::string url::get_search() const {
12921
  // If this's URL's query is either null or the empty string, then return the
12922
  // empty string. Return U+003F (?), followed by this's URL's query.
12923
0
  return (!query.has_value() || (query.value().empty())) ? ""
12924
0
                                                         : "?" + query.value();
12925
0
}
12926
12927
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
12928
0
  return username;
12929
0
}
12930
12931
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
12932
0
  return password;
12933
0
}
12934
12935
0
[[nodiscard]] std::string url::get_port() const {
12936
0
  return port.has_value() ? std::to_string(port.value()) : "";
12937
0
}
12938
12939
0
[[nodiscard]] std::string url::get_hash() const {
12940
  // If this's URL's fragment is either null or the empty string, then return
12941
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12942
0
  return (!hash.has_value() || (hash.value().empty())) ? ""
12943
0
                                                       : "#" + hash.value();
12944
0
}
12945
12946
template <bool override_hostname>
12947
0
bool url::set_host_or_hostname(const std::string_view input) {
12948
0
  if (has_opaque_path) {
12949
0
    return false;
12950
0
  }
12951
12952
0
  std::optional<std::string> previous_host = host;
12953
0
  std::optional<uint16_t> previous_port = port;
12954
12955
0
  size_t host_end_pos = input.find('#');
12956
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12957
0
                                      ? host_end_pos
12958
0
                                      : input.size());
12959
0
  helpers::remove_ascii_tab_or_newline(_host);
12960
0
  std::string_view new_host(_host);
12961
12962
  // If url's scheme is "file", then set state to file host state, instead of
12963
  // host state.
12964
0
  if (type != ada::scheme::type::FILE) {
12965
0
    std::string_view host_view(_host.data(), _host.length());
12966
0
    auto [location, found_colon] =
12967
0
        helpers::get_host_delimiter_location(is_special(), host_view);
12968
12969
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12970
    // Note: the 'found_colon' value is true if and only if a colon was
12971
    // encountered while not inside brackets.
12972
0
    if (found_colon) {
12973
      // If buffer is the empty string, host-missing validation error, return
12974
      // failure.
12975
0
      std::string_view buffer = host_view.substr(0, location);
12976
0
      if (buffer.empty()) {
12977
0
        return false;
12978
0
      }
12979
12980
      // If state override is given and state override is hostname state, then
12981
      // return failure.
12982
0
      if constexpr (override_hostname) {
12983
0
        return false;
12984
0
      }
12985
12986
      // Let host be the result of host parsing buffer with url is not special.
12987
0
      bool succeeded = parse_host(buffer);
12988
0
      if (!succeeded) {
12989
0
        host = std::move(previous_host);
12990
0
        update_base_port(previous_port);
12991
0
        return false;
12992
0
      }
12993
12994
      // Set url's host to host, buffer to the empty string, and state to port
12995
      // state.
12996
0
      std::string_view port_buffer = new_host.substr(location + 1);
12997
0
      if (!port_buffer.empty()) {
12998
0
        set_port(port_buffer);
12999
0
      }
13000
0
      return true;
13001
0
    }
13002
    // Otherwise, if one of the following is true:
13003
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13004
    // - url is special and c is U+005C (\)
13005
0
    else {
13006
      // If url is special and host_view is the empty string, host-missing
13007
      // validation error, return failure.
13008
0
      if (host_view.empty() && is_special()) {
13009
0
        return false;
13010
0
      }
13011
13012
      // Otherwise, if state override is given, host_view is the empty string,
13013
      // and either url includes credentials or url's port is non-null, then
13014
      // return failure.
13015
0
      if (host_view.empty() && (has_credentials() || port.has_value())) {
13016
0
        return false;
13017
0
      }
13018
13019
      // Let host be the result of host parsing host_view with url is not
13020
      // special.
13021
0
      if (host_view.empty() && !is_special()) {
13022
0
        host = "";
13023
0
        return true;
13024
0
      }
13025
13026
0
      bool succeeded = parse_host(host_view);
13027
0
      if (!succeeded) {
13028
0
        host = std::move(previous_host);
13029
0
        update_base_port(previous_port);
13030
0
        return false;
13031
0
      }
13032
0
      return true;
13033
0
    }
13034
0
  }
13035
13036
0
  size_t location = new_host.find_first_of("/\\?");
13037
0
  if (location != std::string_view::npos) {
13038
0
    new_host.remove_suffix(new_host.length() - location);
13039
0
  }
13040
13041
0
  if (new_host.empty()) {
13042
    // Set url's host to the empty string.
13043
0
    host = "";
13044
0
  } else {
13045
    // Let host be the result of host parsing buffer with url is not special.
13046
0
    if (!parse_host(new_host)) {
13047
0
      host = std::move(previous_host);
13048
0
      update_base_port(previous_port);
13049
0
      return false;
13050
0
    }
13051
13052
    // If host is "localhost", then set host to the empty string.
13053
0
    if (host == "localhost") {
13054
0
      host = "";
13055
0
    }
13056
0
  }
13057
0
  return true;
13058
0
}
Unexecuted instantiation: bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
13059
13060
0
bool url::set_host(const std::string_view input) {
13061
0
  return set_host_or_hostname<false>(input);
13062
0
}
13063
13064
0
bool url::set_hostname(const std::string_view input) {
13065
0
  return set_host_or_hostname<true>(input);
13066
0
}
13067
13068
0
bool url::set_username(const std::string_view input) {
13069
0
  if (cannot_have_credentials_or_port()) {
13070
0
    return false;
13071
0
  }
13072
0
  username = ada::unicode::percent_encode(
13073
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13074
0
  return true;
13075
0
}
13076
13077
0
bool url::set_password(const std::string_view input) {
13078
0
  if (cannot_have_credentials_or_port()) {
13079
0
    return false;
13080
0
  }
13081
0
  password = ada::unicode::percent_encode(
13082
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13083
0
  return true;
13084
0
}
13085
13086
0
bool url::set_port(const std::string_view input) {
13087
0
  if (cannot_have_credentials_or_port()) {
13088
0
    return false;
13089
0
  }
13090
13091
0
  if (input.empty()) {
13092
0
    port = std::nullopt;
13093
0
    return true;
13094
0
  }
13095
13096
0
  std::string trimmed(input);
13097
0
  helpers::remove_ascii_tab_or_newline(trimmed);
13098
13099
0
  if (trimmed.empty()) {
13100
0
    return true;
13101
0
  }
13102
13103
  // Input should not start with a non-digit character.
13104
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13105
0
    return false;
13106
0
  }
13107
13108
  // Find the first non-digit character to determine the length of digits
13109
0
  auto first_non_digit =
13110
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13111
0
  std::string_view digits_to_parse =
13112
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13113
13114
  // Revert changes if parse_port fails.
13115
0
  std::optional<uint16_t> previous_port = port;
13116
0
  parse_port(digits_to_parse);
13117
0
  if (is_valid) {
13118
0
    return true;
13119
0
  }
13120
0
  port = std::move(previous_port);
13121
0
  is_valid = true;
13122
0
  return false;
13123
0
}
13124
13125
0
void url::set_hash(const std::string_view input) {
13126
0
  if (input.empty()) {
13127
0
    hash = std::nullopt;
13128
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13129
0
    return;
13130
0
  }
13131
13132
0
  std::string new_value;
13133
0
  new_value = input[0] == '#' ? input.substr(1) : input;
13134
0
  helpers::remove_ascii_tab_or_newline(new_value);
13135
0
  hash = unicode::percent_encode(new_value,
13136
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13137
0
}
13138
13139
0
void url::set_search(const std::string_view input) {
13140
0
  if (input.empty()) {
13141
0
    query = std::nullopt;
13142
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13143
0
    return;
13144
0
  }
13145
13146
0
  std::string new_value;
13147
0
  new_value = input[0] == '?' ? input.substr(1) : input;
13148
0
  helpers::remove_ascii_tab_or_newline(new_value);
13149
13150
0
  auto query_percent_encode_set =
13151
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13152
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13153
13154
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13155
0
}
13156
13157
0
bool url::set_pathname(const std::string_view input) {
13158
0
  if (has_opaque_path) {
13159
0
    return false;
13160
0
  }
13161
0
  path.clear();
13162
0
  parse_path(input);
13163
0
  return true;
13164
0
}
13165
13166
0
bool url::set_protocol(const std::string_view input) {
13167
0
  std::string view(input);
13168
0
  helpers::remove_ascii_tab_or_newline(view);
13169
0
  if (view.empty()) {
13170
0
    return true;
13171
0
  }
13172
13173
  // Schemes should start with alpha values.
13174
0
  if (!checkers::is_alpha(view[0])) {
13175
0
    return false;
13176
0
  }
13177
13178
0
  view.append(":");
13179
13180
0
  std::string::iterator pointer =
13181
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13182
13183
0
  if (pointer != view.end() && *pointer == ':') {
13184
0
    return parse_scheme<true>(
13185
0
        std::string_view(view.data(), pointer - view.begin()));
13186
0
  }
13187
0
  return false;
13188
0
}
13189
13190
0
bool url::set_href(const std::string_view input) {
13191
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13192
13193
0
  if (out) {
13194
0
    *this = *out;
13195
0
  }
13196
13197
0
  return out.has_value();
13198
0
}
13199
13200
}  // namespace ada
13201
/* end file src/url.cpp */
13202
/* begin file src/parser.cpp */
13203
13204
#include <limits>
13205
#include <ranges>
13206
13207
13208
namespace ada::parser {
13209
13210
template <class result_type, bool store_values>
13211
result_type parse_url_impl(std::string_view user_input,
13212
0
                           const result_type* base_url) {
13213
  // We can specialize the implementation per type.
13214
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13215
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13216
  // something else } is free (at runtime). This means that ada::url_aggregator
13217
  // and ada::url **do not have to support the exact same API**.
13218
0
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13219
0
  constexpr bool result_type_is_ada_url_aggregator =
13220
0
      std::is_same_v<url_aggregator, result_type>;
13221
0
  static_assert(result_type_is_ada_url ||
13222
0
                result_type_is_ada_url_aggregator);  // We don't support
13223
                                                     // anything else for now.
13224
13225
0
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13226
0
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13227
0
          ")");
13228
13229
0
  state state = state::SCHEME_START;
13230
0
  result_type url{};
13231
13232
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13233
  // surely the result of a bug or are otherwise a security concern.
13234
0
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13235
0
    url.is_valid = false;
13236
0
  }
13237
  // Going forward, user_input.size() is in [0,
13238
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13239
  // base, or the optional_url was invalid, we must return.
13240
0
  if (base_url != nullptr) {
13241
0
    url.is_valid &= base_url->is_valid;
13242
0
  }
13243
0
  if (!url.is_valid) {
13244
0
    return url;
13245
0
  }
13246
0
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13247
    // Most of the time, we just need user_input.size().
13248
    // In some instances, we may need a bit more.
13249
    ///////////////////////////
13250
    // This is *very* important. This line should *not* be removed
13251
    // hastily. There are principled reasons why reserve is important
13252
    // for performance. If you have a benchmark with small inputs,
13253
    // it may not matter, but in other instances, it could.
13254
    ////
13255
    // This rounds up to the next power of two.
13256
    // We know that user_input.size() is in [0,
13257
    // std::numeric_limits<uint32_t>::max).
13258
0
    uint32_t reserve_capacity =
13259
0
        (0xFFFFFFFF >>
13260
0
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13261
0
        1;
13262
0
    url.reserve(reserve_capacity);
13263
0
  }
13264
0
  std::string tmp_buffer;
13265
0
  std::string_view url_data;
13266
0
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13267
0
    tmp_buffer = user_input;
13268
    // Optimization opportunity: Instead of copying and then pruning, we could
13269
    // just directly build the string from user_input.
13270
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13271
0
    url_data = tmp_buffer;
13272
0
  } else [[likely]] {
13273
0
    url_data = user_input;
13274
0
  }
13275
13276
  // Leading and trailing control characters are uncommon and easy to deal with
13277
  // (no performance concern).
13278
0
  helpers::trim_c0_whitespace(url_data);
13279
13280
  // Optimization opportunity. Most websites do not have fragment.
13281
0
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13282
  // We add it last so that an implementation like ada::url_aggregator
13283
  // can append it last to its internal buffer, thus improving performance.
13284
13285
  // Here url_data no longer has its fragment.
13286
  // We are going to access the data from url_data (it is immutable).
13287
  // At any given time, we are pointing at byte 'input_position' in url_data.
13288
  // The input_position variable should range from 0 to input_size.
13289
  // It is illegal to access url_data at input_size.
13290
0
  size_t input_position = 0;
13291
0
  const size_t input_size = url_data.size();
13292
  // Keep running the following state machine by switching on state.
13293
  // If after a run pointer points to the EOF code point, go to the next step.
13294
  // Otherwise, increase pointer by 1 and continue with the state machine.
13295
  // We never decrement input_position.
13296
0
  while (input_position <= input_size) {
13297
0
    ada_log("In parsing at ", input_position, " out of ", input_size,
13298
0
            " in state ", ada::to_string(state));
13299
0
    switch (state) {
13300
0
      case state::SCHEME_START: {
13301
0
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13302
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13303
        // state to scheme state.
13304
0
        if ((input_position != input_size) &&
13305
0
            checkers::is_alpha(url_data[input_position])) {
13306
0
          state = state::SCHEME;
13307
0
          input_position++;
13308
0
        } else {
13309
          // Otherwise, if state override is not given, set state to no scheme
13310
          // state and decrease pointer by 1.
13311
0
          state = state::NO_SCHEME;
13312
0
        }
13313
0
        break;
13314
0
      }
13315
0
      case state::SCHEME: {
13316
0
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13317
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13318
        // append c, lowercased, to buffer.
13319
0
        while ((input_position != input_size) &&
13320
0
               (unicode::is_alnum_plus(url_data[input_position]))) {
13321
0
          input_position++;
13322
0
        }
13323
        // Otherwise, if c is U+003A (:), then:
13324
0
        if ((input_position != input_size) &&
13325
0
            (url_data[input_position] == ':')) {
13326
0
          ada_log("SCHEME the scheme should be ",
13327
0
                  url_data.substr(0, input_position));
13328
0
          if constexpr (result_type_is_ada_url) {
13329
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13330
0
              return url;
13331
0
            }
13332
0
          } else {
13333
            // we pass the colon along instead of painfully adding it back.
13334
0
            if (!url.parse_scheme_with_colon(
13335
0
                    url_data.substr(0, input_position + 1))) {
13336
0
              return url;
13337
0
            }
13338
0
          }
13339
0
          ada_log("SCHEME the scheme is ", url.get_protocol());
13340
13341
          // If url's scheme is "file", then:
13342
0
          if (url.type == scheme::type::FILE) {
13343
            // Set state to file state.
13344
0
            state = state::FILE;
13345
0
          }
13346
          // Otherwise, if url is special, base is non-null, and base's scheme
13347
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13348
          // != nullptr is false.
13349
0
          else if (url.is_special() && base_url != nullptr &&
13350
0
                   base_url->type == url.type) {
13351
            // Set state to special relative or authority state.
13352
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13353
0
          }
13354
          // Otherwise, if url is special, set state to special authority
13355
          // slashes state.
13356
0
          else if (url.is_special()) {
13357
0
            state = state::SPECIAL_AUTHORITY_SLASHES;
13358
0
          }
13359
          // Otherwise, if remaining starts with an U+002F (/), set state to
13360
          // path or authority state and increase pointer by 1.
13361
0
          else if (input_position + 1 < input_size &&
13362
0
                   url_data[input_position + 1] == '/') {
13363
0
            state = state::PATH_OR_AUTHORITY;
13364
0
            input_position++;
13365
0
          }
13366
          // Otherwise, set url's path to the empty string and set state to
13367
          // opaque path state.
13368
0
          else {
13369
0
            state = state::OPAQUE_PATH;
13370
0
          }
13371
0
        }
13372
        // Otherwise, if state override is not given, set buffer to the empty
13373
        // string, state to no scheme state, and start over (from the first code
13374
        // point in input).
13375
0
        else {
13376
0
          state = state::NO_SCHEME;
13377
0
          input_position = 0;
13378
0
          break;
13379
0
        }
13380
0
        input_position++;
13381
0
        break;
13382
0
      }
13383
0
      case state::NO_SCHEME: {
13384
0
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13385
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13386
        // validation error, return failure.
13387
0
        if (base_url == nullptr ||
13388
0
            (base_url->has_opaque_path && !fragment.has_value())) {
13389
0
          ada_log("NO_SCHEME validation error");
13390
0
          url.is_valid = false;
13391
0
          return url;
13392
0
        }
13393
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13394
        // set url's scheme to base's scheme, url's path to base's path, url's
13395
        // query to base's query, and set state to fragment state.
13396
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13397
0
                 input_position == input_size) {
13398
0
          ada_log("NO_SCHEME opaque base with fragment");
13399
0
          url.copy_scheme(*base_url);
13400
0
          url.has_opaque_path = base_url->has_opaque_path;
13401
13402
0
          if constexpr (result_type_is_ada_url) {
13403
0
            url.path = base_url->path;
13404
0
            url.query = base_url->query;
13405
0
          } else {
13406
0
            url.update_base_pathname(base_url->get_pathname());
13407
0
            url.update_base_search(base_url->get_search());
13408
0
          }
13409
0
          url.update_unencoded_base_hash(*fragment);
13410
0
          return url;
13411
0
        }
13412
        // Otherwise, if base's scheme is not "file", set state to relative
13413
        // state and decrease pointer by 1.
13414
0
        else if (base_url->type != scheme::type::FILE) {
13415
0
          ada_log("NO_SCHEME non-file relative path");
13416
0
          state = state::RELATIVE_SCHEME;
13417
0
        }
13418
        // Otherwise, set state to file state and decrease pointer by 1.
13419
0
        else {
13420
0
          ada_log("NO_SCHEME file base type");
13421
0
          state = state::FILE;
13422
0
        }
13423
0
        break;
13424
0
      }
13425
0
      case state::AUTHORITY: {
13426
0
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13427
        // most URLs have no @. Having no @ tells us that we don't have to worry
13428
        // about AUTHORITY. Of course, we could have @ and still not have to
13429
        // worry about AUTHORITY.
13430
        // TODO: Instead of just collecting a bool, collect the location of the
13431
        // '@' and do something useful with it.
13432
        // TODO: We could do various processing early on, using a single pass
13433
        // over the string to collect information about it, e.g., telling us
13434
        // whether there is a @ and if so, where (or how many).
13435
13436
        // Check if url data contains an @.
13437
0
        if (url_data.find('@', input_position) == std::string_view::npos) {
13438
0
          state = state::HOST;
13439
0
          break;
13440
0
        }
13441
0
        bool at_sign_seen{false};
13442
0
        bool password_token_seen{false};
13443
        /**
13444
         * We expect something of the sort...
13445
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13446
         * --------^
13447
         */
13448
0
        do {
13449
0
          std::string_view view = url_data.substr(input_position);
13450
          // The delimiters are @, /, ? \\.
13451
0
          size_t location =
13452
0
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13453
0
                               : helpers::find_authority_delimiter(view);
13454
0
          std::string_view authority_view = view.substr(0, location);
13455
0
          size_t end_of_authority = input_position + authority_view.size();
13456
          // If c is U+0040 (@), then:
13457
0
          if ((end_of_authority != input_size) &&
13458
0
              (url_data[end_of_authority] == '@')) {
13459
            // If atSignSeen is true, then prepend "%40" to buffer.
13460
0
            if (at_sign_seen) {
13461
0
              if (password_token_seen) {
13462
0
                if constexpr (result_type_is_ada_url) {
13463
0
                  url.password += "%40";
13464
0
                } else {
13465
0
                  url.append_base_password("%40");
13466
0
                }
13467
0
              } else {
13468
0
                if constexpr (result_type_is_ada_url) {
13469
0
                  url.username += "%40";
13470
0
                } else {
13471
0
                  url.append_base_username("%40");
13472
0
                }
13473
0
              }
13474
0
            }
13475
13476
0
            at_sign_seen = true;
13477
13478
0
            if (!password_token_seen) {
13479
0
              size_t password_token_location = authority_view.find(':');
13480
0
              password_token_seen =
13481
0
                  password_token_location != std::string_view::npos;
13482
13483
0
              if constexpr (store_values) {
13484
0
                if (!password_token_seen) {
13485
0
                  if constexpr (result_type_is_ada_url) {
13486
0
                    url.username += unicode::percent_encode(
13487
0
                        authority_view,
13488
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13489
0
                  } else {
13490
0
                    url.append_base_username(unicode::percent_encode(
13491
0
                        authority_view,
13492
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13493
0
                  }
13494
0
                } else {
13495
0
                  if constexpr (result_type_is_ada_url) {
13496
0
                    url.username += unicode::percent_encode(
13497
0
                        authority_view.substr(0, password_token_location),
13498
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13499
0
                    url.password += unicode::percent_encode(
13500
0
                        authority_view.substr(password_token_location + 1),
13501
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13502
0
                  } else {
13503
0
                    url.append_base_username(unicode::percent_encode(
13504
0
                        authority_view.substr(0, password_token_location),
13505
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13506
0
                    url.append_base_password(unicode::percent_encode(
13507
0
                        authority_view.substr(password_token_location + 1),
13508
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13509
0
                  }
13510
0
                }
13511
0
              }
13512
0
            } else if constexpr (store_values) {
13513
0
              if constexpr (result_type_is_ada_url) {
13514
0
                url.password += unicode::percent_encode(
13515
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13516
0
              } else {
13517
0
                url.append_base_password(unicode::percent_encode(
13518
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13519
0
              }
13520
0
            }
13521
0
          }
13522
          // Otherwise, if one of the following is true:
13523
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13524
          // - url is special and c is U+005C (\)
13525
0
          else if (end_of_authority == input_size ||
13526
0
                   url_data[end_of_authority] == '/' ||
13527
0
                   url_data[end_of_authority] == '?' ||
13528
0
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13529
            // If atSignSeen is true and authority_view is the empty string,
13530
            // validation error, return failure.
13531
0
            if (at_sign_seen && authority_view.empty()) {
13532
0
              url.is_valid = false;
13533
0
              return url;
13534
0
            }
13535
0
            state = state::HOST;
13536
0
            break;
13537
0
          }
13538
0
          if (end_of_authority == input_size) {
13539
0
            if constexpr (store_values) {
13540
0
              if (fragment.has_value()) {
13541
0
                url.update_unencoded_base_hash(*fragment);
13542
0
              }
13543
0
            }
13544
0
            return url;
13545
0
          }
13546
0
          input_position = end_of_authority + 1;
13547
0
        } while (true);
13548
13549
0
        break;
13550
0
      }
13551
0
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13552
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13553
0
                helpers::substring(url_data, input_position));
13554
13555
        // If c is U+002F (/) and remaining starts with U+002F (/),
13556
        // then set state to special authority ignore slashes state and increase
13557
        // pointer by 1.
13558
0
        if (url_data.substr(input_position, 2) == "//") {
13559
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13560
0
          input_position += 2;
13561
0
        } else {
13562
          // Otherwise, validation error, set state to relative state and
13563
          // decrease pointer by 1.
13564
0
          state = state::RELATIVE_SCHEME;
13565
0
        }
13566
13567
0
        break;
13568
0
      }
13569
0
      case state::PATH_OR_AUTHORITY: {
13570
0
        ada_log("PATH_OR_AUTHORITY ",
13571
0
                helpers::substring(url_data, input_position));
13572
13573
        // If c is U+002F (/), then set state to authority state.
13574
0
        if ((input_position != input_size) &&
13575
0
            (url_data[input_position] == '/')) {
13576
0
          state = state::AUTHORITY;
13577
0
          input_position++;
13578
0
        } else {
13579
          // Otherwise, set state to path state, and decrease pointer by 1.
13580
0
          state = state::PATH;
13581
0
        }
13582
13583
0
        break;
13584
0
      }
13585
0
      case state::RELATIVE_SCHEME: {
13586
0
        ada_log("RELATIVE_SCHEME ",
13587
0
                helpers::substring(url_data, input_position));
13588
13589
        // Set url's scheme to base's scheme.
13590
0
        url.copy_scheme(*base_url);
13591
13592
        // If c is U+002F (/), then set state to relative slash state.
13593
0
        if ((input_position != input_size) &&
13594
            // NOLINTNEXTLINE(bugprone-branch-clone)
13595
0
            (url_data[input_position] == '/')) {
13596
0
          ada_log(
13597
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13598
0
              "slash state");
13599
0
          state = state::RELATIVE_SLASH;
13600
0
        } else if (url.is_special() && (input_position != input_size) &&
13601
0
                   (url_data[input_position] == '\\')) {
13602
          // Otherwise, if url is special and c is U+005C (\), validation error,
13603
          // set state to relative slash state.
13604
0
          ada_log(
13605
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13606
0
              "error, set state to relative slash state");
13607
0
          state = state::RELATIVE_SLASH;
13608
0
        } else {
13609
0
          ada_log("RELATIVE_SCHEME otherwise");
13610
          // Set url's username to base's username, url's password to base's
13611
          // password, url's host to base's host, url's port to base's port,
13612
          // url's path to a clone of base's path, and url's query to base's
13613
          // query.
13614
0
          if constexpr (result_type_is_ada_url) {
13615
0
            url.username = base_url->username;
13616
0
            url.password = base_url->password;
13617
0
            url.host = base_url->host;
13618
0
            url.port = base_url->port;
13619
            // cloning the base path includes cloning the has_opaque_path flag
13620
0
            url.has_opaque_path = base_url->has_opaque_path;
13621
0
            url.path = base_url->path;
13622
0
            url.query = base_url->query;
13623
0
          } else {
13624
0
            url.update_base_authority(base_url->get_href(),
13625
0
                                      base_url->get_components());
13626
0
            url.update_host_to_base_host(base_url->get_hostname());
13627
0
            url.update_base_port(base_url->retrieve_base_port());
13628
            // cloning the base path includes cloning the has_opaque_path flag
13629
0
            url.has_opaque_path = base_url->has_opaque_path;
13630
0
            url.update_base_pathname(base_url->get_pathname());
13631
0
            url.update_base_search(base_url->get_search());
13632
0
          }
13633
13634
0
          url.has_opaque_path = base_url->has_opaque_path;
13635
13636
          // If c is U+003F (?), then set url's query to the empty string, and
13637
          // state to query state.
13638
0
          if ((input_position != input_size) &&
13639
0
              (url_data[input_position] == '?')) {
13640
0
            state = state::QUERY;
13641
0
          }
13642
          // Otherwise, if c is not the EOF code point:
13643
0
          else if (input_position != input_size) {
13644
            // Set url's query to null.
13645
0
            url.clear_search();
13646
0
            if constexpr (result_type_is_ada_url) {
13647
              // Shorten url's path.
13648
0
              helpers::shorten_path(url.path, url.type);
13649
0
            } else {
13650
0
              std::string_view path = url.get_pathname();
13651
0
              if (helpers::shorten_path(path, url.type)) {
13652
0
                url.update_base_pathname(std::move(std::string(path)));
13653
0
              }
13654
0
            }
13655
            // Set state to path state and decrease pointer by 1.
13656
0
            state = state::PATH;
13657
0
            break;
13658
0
          }
13659
0
        }
13660
0
        input_position++;
13661
0
        break;
13662
0
      }
13663
0
      case state::RELATIVE_SLASH: {
13664
0
        ada_log("RELATIVE_SLASH ",
13665
0
                helpers::substring(url_data, input_position));
13666
13667
        // If url is special and c is U+002F (/) or U+005C (\), then:
13668
0
        if (url.is_special() && (input_position != input_size) &&
13669
0
            (url_data[input_position] == '/' ||
13670
0
             url_data[input_position] == '\\')) {
13671
          // Set state to special authority ignore slashes state.
13672
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13673
0
        }
13674
        // Otherwise, if c is U+002F (/), then set state to authority state.
13675
0
        else if ((input_position != input_size) &&
13676
0
                 (url_data[input_position] == '/')) {
13677
0
          state = state::AUTHORITY;
13678
0
        }
13679
        // Otherwise, set
13680
        // - url's username to base's username,
13681
        // - url's password to base's password,
13682
        // - url's host to base's host,
13683
        // - url's port to base's port,
13684
        // - state to path state, and then, decrease pointer by 1.
13685
0
        else {
13686
0
          if constexpr (result_type_is_ada_url) {
13687
0
            url.username = base_url->username;
13688
0
            url.password = base_url->password;
13689
0
            url.host = base_url->host;
13690
0
            url.port = base_url->port;
13691
0
          } else {
13692
0
            url.update_base_authority(base_url->get_href(),
13693
0
                                      base_url->get_components());
13694
0
            url.update_host_to_base_host(base_url->get_hostname());
13695
0
            url.update_base_port(base_url->retrieve_base_port());
13696
0
          }
13697
0
          state = state::PATH;
13698
0
          break;
13699
0
        }
13700
13701
0
        input_position++;
13702
0
        break;
13703
0
      }
13704
0
      case state::SPECIAL_AUTHORITY_SLASHES: {
13705
0
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13706
0
                helpers::substring(url_data, input_position));
13707
13708
        // If c is U+002F (/) and remaining starts with U+002F (/),
13709
        // then set state to special authority ignore slashes state and increase
13710
        // pointer by 1.
13711
0
        if (url_data.substr(input_position, 2) == "//") {
13712
0
          input_position += 2;
13713
0
        }
13714
13715
0
        [[fallthrough]];
13716
0
      }
13717
0
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13718
0
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13719
0
                helpers::substring(url_data, input_position));
13720
13721
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13722
        // authority state and decrease pointer by 1.
13723
0
        while ((input_position != input_size) &&
13724
0
               ((url_data[input_position] == '/') ||
13725
0
                (url_data[input_position] == '\\'))) {
13726
0
          input_position++;
13727
0
        }
13728
0
        state = state::AUTHORITY;
13729
13730
0
        break;
13731
0
      }
13732
0
      case state::QUERY: {
13733
0
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13734
0
        if constexpr (store_values) {
13735
          // Let queryPercentEncodeSet be the special-query percent-encode set
13736
          // if url is special; otherwise the query percent-encode set.
13737
0
          const uint8_t* query_percent_encode_set =
13738
0
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13739
0
                               : character_sets::QUERY_PERCENT_ENCODE;
13740
13741
          // Percent-encode after encoding, with encoding, buffer, and
13742
          // queryPercentEncodeSet, and append the result to url's query.
13743
0
          url.update_base_search(url_data.substr(input_position),
13744
0
                                 query_percent_encode_set);
13745
0
          ada_log("QUERY update_base_search completed ");
13746
0
          if (fragment.has_value()) {
13747
0
            url.update_unencoded_base_hash(*fragment);
13748
0
          }
13749
0
        }
13750
0
        return url;
13751
0
      }
13752
0
      case state::HOST: {
13753
0
        ada_log("HOST ", helpers::substring(url_data, input_position));
13754
13755
0
        std::string_view host_view = url_data.substr(input_position);
13756
0
        auto [location, found_colon] =
13757
0
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13758
0
        input_position = (location != std::string_view::npos)
13759
0
                             ? input_position + location
13760
0
                             : input_size;
13761
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13762
        // Note: the 'found_colon' value is true if and only if a colon was
13763
        // encountered while not inside brackets.
13764
0
        if (found_colon) {
13765
          // If buffer is the empty string, validation error, return failure.
13766
          // Let host be the result of host parsing buffer with url is not
13767
          // special.
13768
0
          ada_log("HOST parsing ", host_view);
13769
0
          if (!url.parse_host(host_view)) {
13770
0
            return url;
13771
0
          }
13772
0
          ada_log("HOST parsing results in ", url.get_hostname());
13773
          // Set url's host to host, buffer to the empty string, and state to
13774
          // port state.
13775
0
          state = state::PORT;
13776
0
          input_position++;
13777
0
        }
13778
        // Otherwise, if one of the following is true:
13779
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13780
        // - url is special and c is U+005C (\)
13781
        // The get_host_delimiter_location function either brings us to
13782
        // the colon outside of the bracket, or to one of those characters.
13783
0
        else {
13784
          // If url is special and host_view is the empty string, validation
13785
          // error, return failure.
13786
0
          if (host_view.empty() && url.is_special()) {
13787
0
            url.is_valid = false;
13788
0
            return url;
13789
0
          }
13790
0
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13791
          // Let host be the result of host parsing host_view with url is not
13792
          // special.
13793
0
          if (host_view.empty()) {
13794
0
            url.update_base_hostname("");
13795
0
          } else if (!url.parse_host(host_view)) {
13796
0
            return url;
13797
0
          }
13798
0
          ada_log("HOST parsing results in ", url.get_hostname(),
13799
0
                  " href=", url.get_href());
13800
13801
          // Set url's host to host, and state to path start state.
13802
0
          state = state::PATH_START;
13803
0
        }
13804
13805
0
        break;
13806
0
      }
13807
0
      case state::OPAQUE_PATH: {
13808
0
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13809
0
        std::string_view view = url_data.substr(input_position);
13810
        // If c is U+003F (?), then set url's query to the empty string and
13811
        // state to query state.
13812
0
        size_t location = view.find('?');
13813
0
        if (location != std::string_view::npos) {
13814
0
          view.remove_suffix(view.size() - location);
13815
0
          state = state::QUERY;
13816
0
          input_position += location + 1;
13817
0
        } else {
13818
0
          input_position = input_size + 1;
13819
0
        }
13820
0
        url.has_opaque_path = true;
13821
13822
        // This is a really unlikely scenario in real world. We should not seek
13823
        // to optimize it.
13824
0
        if (view.ends_with(' ')) {
13825
0
          std::string modified_view =
13826
0
              std::string(view.substr(0, view.size() - 1)) + "%20";
13827
0
          url.update_base_pathname(unicode::percent_encode(
13828
0
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13829
0
        } else {
13830
0
          url.update_base_pathname(unicode::percent_encode(
13831
0
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13832
0
        }
13833
0
        break;
13834
0
      }
13835
0
      case state::PORT: {
13836
0
        ada_log("PORT ", helpers::substring(url_data, input_position));
13837
0
        std::string_view port_view = url_data.substr(input_position);
13838
0
        input_position += url.parse_port(port_view, true);
13839
0
        if (!url.is_valid) {
13840
0
          return url;
13841
0
        }
13842
0
        state = state::PATH_START;
13843
0
        [[fallthrough]];
13844
0
      }
13845
0
      case state::PATH_START: {
13846
0
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13847
13848
        // If url is special, then:
13849
0
        if (url.is_special()) {
13850
          // Set state to path state.
13851
0
          state = state::PATH;
13852
13853
          // Optimization: Avoiding going into PATH state improves the
13854
          // performance of urls ending with /.
13855
0
          if (input_position == input_size) {
13856
0
            if constexpr (store_values) {
13857
0
              url.update_base_pathname("/");
13858
0
              if (fragment.has_value()) {
13859
0
                url.update_unencoded_base_hash(*fragment);
13860
0
              }
13861
0
            }
13862
0
            return url;
13863
0
          }
13864
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13865
          // by 1. We know that (input_position == input_size) is impossible
13866
          // here, because of the previous if-check.
13867
0
          if ((url_data[input_position] != '/') &&
13868
0
              (url_data[input_position] != '\\')) {
13869
0
            break;
13870
0
          }
13871
0
        }
13872
        // Otherwise, if state override is not given and c is U+003F (?),
13873
        // set url's query to the empty string and state to query state.
13874
0
        else if ((input_position != input_size) &&
13875
0
                 (url_data[input_position] == '?')) {
13876
0
          state = state::QUERY;
13877
0
        }
13878
        // Otherwise, if c is not the EOF code point:
13879
0
        else if (input_position != input_size) {
13880
          // Set state to path state.
13881
0
          state = state::PATH;
13882
13883
          // If c is not U+002F (/), then decrease pointer by 1.
13884
0
          if (url_data[input_position] != '/') {
13885
0
            break;
13886
0
          }
13887
0
        }
13888
13889
0
        input_position++;
13890
0
        break;
13891
0
      }
13892
0
      case state::PATH: {
13893
0
        ada_log("PATH ", helpers::substring(url_data, input_position));
13894
0
        std::string_view view = url_data.substr(input_position);
13895
13896
        // Most time, we do not need percent encoding.
13897
        // Furthermore, we can immediately locate the '?'.
13898
0
        size_t locofquestionmark = view.find('?');
13899
0
        if (locofquestionmark != std::string_view::npos) {
13900
0
          state = state::QUERY;
13901
0
          view.remove_suffix(view.size() - locofquestionmark);
13902
0
          input_position += locofquestionmark + 1;
13903
0
        } else {
13904
0
          input_position = input_size + 1;
13905
0
        }
13906
0
        if constexpr (store_values) {
13907
0
          if constexpr (result_type_is_ada_url) {
13908
0
            helpers::parse_prepared_path(view, url.type, url.path);
13909
0
          } else {
13910
0
            url.consume_prepared_path(view);
13911
0
            ADA_ASSERT_TRUE(url.validate());
13912
0
          }
13913
0
        }
13914
0
        break;
13915
0
      }
13916
0
      case state::FILE_SLASH: {
13917
0
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13918
13919
        // If c is U+002F (/) or U+005C (\), then:
13920
0
        if ((input_position != input_size) &&
13921
0
            (url_data[input_position] == '/' ||
13922
0
             url_data[input_position] == '\\')) {
13923
0
          ada_log("FILE_SLASH c is U+002F or U+005C");
13924
          // Set state to file host state.
13925
0
          state = state::FILE_HOST;
13926
0
          input_position++;
13927
0
        } else {
13928
0
          ada_log("FILE_SLASH otherwise");
13929
          // If base is non-null and base's scheme is "file", then:
13930
          // Note: it is unsafe to do base_url->scheme unless you know that
13931
          // base_url_has_value() is true.
13932
0
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13933
            // Set url's host to base's host.
13934
0
            if constexpr (result_type_is_ada_url) {
13935
0
              url.host = base_url->host;
13936
0
            } else {
13937
0
              url.update_host_to_base_host(base_url->get_host());
13938
0
            }
13939
            // If the code point substring from pointer to the end of input does
13940
            // not start with a Windows drive letter and base's path[0] is a
13941
            // normalized Windows drive letter, then append base's path[0] to
13942
            // url's path.
13943
0
            if (!base_url->get_pathname().empty()) {
13944
0
              if (!checkers::is_windows_drive_letter(
13945
0
                      url_data.substr(input_position))) {
13946
0
                std::string_view first_base_url_path =
13947
0
                    base_url->get_pathname().substr(1);
13948
0
                size_t loc = first_base_url_path.find('/');
13949
0
                if (loc != std::string_view::npos) {
13950
0
                  helpers::resize(first_base_url_path, loc);
13951
0
                }
13952
0
                if (checkers::is_normalized_windows_drive_letter(
13953
0
                        first_base_url_path)) {
13954
0
                  if constexpr (result_type_is_ada_url) {
13955
0
                    url.path += '/';
13956
0
                    url.path += first_base_url_path;
13957
0
                  } else {
13958
0
                    url.append_base_pathname(
13959
0
                        helpers::concat("/", first_base_url_path));
13960
0
                  }
13961
0
                }
13962
0
              }
13963
0
            }
13964
0
          }
13965
13966
          // Set state to path state, and decrease pointer by 1.
13967
0
          state = state::PATH;
13968
0
        }
13969
13970
0
        break;
13971
0
      }
13972
0
      case state::FILE_HOST: {
13973
0
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13974
0
        std::string_view view = url_data.substr(input_position);
13975
13976
0
        size_t location = view.find_first_of("/\\?");
13977
0
        std::string_view file_host_buffer(
13978
0
            view.data(),
13979
0
            (location != std::string_view::npos) ? location : view.size());
13980
13981
0
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13982
0
          state = state::PATH;
13983
0
        } else if (file_host_buffer.empty()) {
13984
          // Set url's host to the empty string.
13985
0
          if constexpr (result_type_is_ada_url) {
13986
0
            url.host = "";
13987
0
          } else {
13988
0
            url.update_base_hostname("");
13989
0
          }
13990
          // Set state to path start state.
13991
0
          state = state::PATH_START;
13992
0
        } else {
13993
0
          size_t consumed_bytes = file_host_buffer.size();
13994
0
          input_position += consumed_bytes;
13995
          // Let host be the result of host parsing buffer with url is not
13996
          // special.
13997
0
          if (!url.parse_host(file_host_buffer)) {
13998
0
            return url;
13999
0
          }
14000
14001
0
          if constexpr (result_type_is_ada_url) {
14002
            // If host is "localhost", then set host to the empty string.
14003
0
            if (url.host.has_value() && url.host.value() == "localhost") {
14004
0
              url.host = "";
14005
0
            }
14006
0
          } else {
14007
0
            if (url.get_hostname() == "localhost") {
14008
0
              url.update_base_hostname("");
14009
0
            }
14010
0
          }
14011
14012
          // Set buffer to the empty string and state to path start state.
14013
0
          state = state::PATH_START;
14014
0
        }
14015
14016
0
        break;
14017
0
      }
14018
0
      case state::FILE: {
14019
0
        ada_log("FILE ", helpers::substring(url_data, input_position));
14020
0
        std::string_view file_view = url_data.substr(input_position);
14021
14022
0
        url.set_protocol_as_file();
14023
0
        if constexpr (result_type_is_ada_url) {
14024
          // Set url's host to the empty string.
14025
0
          url.host = "";
14026
0
        } else {
14027
0
          url.update_base_hostname("");
14028
0
        }
14029
        // If c is U+002F (/) or U+005C (\), then:
14030
0
        if (input_position != input_size &&
14031
0
            (url_data[input_position] == '/' ||
14032
0
             url_data[input_position] == '\\')) {
14033
0
          ada_log("FILE c is U+002F or U+005C");
14034
          // Set state to file slash state.
14035
0
          state = state::FILE_SLASH;
14036
0
        }
14037
        // Otherwise, if base is non-null and base's scheme is "file":
14038
0
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14039
          // Set url's host to base's host, url's path to a clone of base's
14040
          // path, and url's query to base's query.
14041
0
          ada_log("FILE base non-null");
14042
0
          if constexpr (result_type_is_ada_url) {
14043
0
            url.host = base_url->host;
14044
0
            url.path = base_url->path;
14045
0
            url.query = base_url->query;
14046
0
          } else {
14047
0
            url.update_host_to_base_host(base_url->get_hostname());
14048
0
            url.update_base_pathname(base_url->get_pathname());
14049
0
            url.update_base_search(base_url->get_search());
14050
0
          }
14051
0
          url.has_opaque_path = base_url->has_opaque_path;
14052
14053
          // If c is U+003F (?), then set url's query to the empty string and
14054
          // state to query state.
14055
0
          if (input_position != input_size && url_data[input_position] == '?') {
14056
0
            state = state::QUERY;
14057
0
          }
14058
          // Otherwise, if c is not the EOF code point:
14059
0
          else if (input_position != input_size) {
14060
            // Set url's query to null.
14061
0
            url.clear_search();
14062
            // If the code point substring from pointer to the end of input does
14063
            // not start with a Windows drive letter, then shorten url's path.
14064
0
            if (!checkers::is_windows_drive_letter(file_view)) {
14065
0
              if constexpr (result_type_is_ada_url) {
14066
0
                helpers::shorten_path(url.path, url.type);
14067
0
              } else {
14068
0
                std::string_view path = url.get_pathname();
14069
0
                if (helpers::shorten_path(path, url.type)) {
14070
0
                  url.update_base_pathname(std::move(std::string(path)));
14071
0
                }
14072
0
              }
14073
0
            }
14074
            // Otherwise:
14075
0
            else {
14076
              // Set url's path to an empty list.
14077
0
              url.clear_pathname();
14078
0
              url.has_opaque_path = true;
14079
0
            }
14080
14081
            // Set state to path state and decrease pointer by 1.
14082
0
            state = state::PATH;
14083
0
            break;
14084
0
          }
14085
0
        }
14086
        // Otherwise, set state to path state, and decrease pointer by 1.
14087
0
        else {
14088
0
          ada_log("FILE go to path");
14089
0
          state = state::PATH;
14090
0
          break;
14091
0
        }
14092
14093
0
        input_position++;
14094
0
        break;
14095
0
      }
14096
0
      default:
14097
0
        unreachable();
14098
0
    }
14099
0
  }
14100
0
  if constexpr (store_values) {
14101
0
    if (fragment.has_value()) {
14102
0
      url.update_unencoded_base_hash(*fragment);
14103
0
    }
14104
0
  }
14105
0
  return url;
14106
0
}
Unexecuted instantiation: ada::url ada::parser::parse_url_impl<ada::url, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url_impl<ada::url_aggregator, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url_impl<ada::url_aggregator, false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
14107
14108
template url parse_url_impl(std::string_view user_input,
14109
                            const url* base_url = nullptr);
14110
template url_aggregator parse_url_impl(
14111
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14112
14113
template <class result_type>
14114
result_type parse_url(std::string_view user_input,
14115
0
                      const result_type* base_url) {
14116
0
  return parse_url_impl<result_type, true>(user_input, base_url);
14117
0
}
Unexecuted instantiation: ada::url ada::parser::parse_url<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
14118
14119
template url parse_url<url>(std::string_view user_input,
14120
                            const url* base_url = nullptr);
14121
template url_aggregator parse_url<url_aggregator>(
14122
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14123
}  // namespace ada::parser
14124
/* end file src/parser.cpp */
14125
/* begin file src/url_components.cpp */
14126
14127
#include <iterator>
14128
#include <string>
14129
14130
namespace ada {
14131
14132
0
[[nodiscard]] std::string url_components::to_string() const {
14133
0
  std::string answer;
14134
0
  auto back = std::back_insert_iterator(answer);
14135
0
  answer.append("{\n");
14136
14137
0
  answer.append("\t\"protocol_end\":\"");
14138
0
  helpers::encode_json(std::to_string(protocol_end), back);
14139
0
  answer.append("\",\n");
14140
14141
0
  answer.append("\t\"username_end\":\"");
14142
0
  helpers::encode_json(std::to_string(username_end), back);
14143
0
  answer.append("\",\n");
14144
14145
0
  answer.append("\t\"host_start\":\"");
14146
0
  helpers::encode_json(std::to_string(host_start), back);
14147
0
  answer.append("\",\n");
14148
14149
0
  answer.append("\t\"host_end\":\"");
14150
0
  helpers::encode_json(std::to_string(host_end), back);
14151
0
  answer.append("\",\n");
14152
14153
0
  answer.append("\t\"port\":\"");
14154
0
  helpers::encode_json(std::to_string(port), back);
14155
0
  answer.append("\",\n");
14156
14157
0
  answer.append("\t\"pathname_start\":\"");
14158
0
  helpers::encode_json(std::to_string(pathname_start), back);
14159
0
  answer.append("\",\n");
14160
14161
0
  answer.append("\t\"search_start\":\"");
14162
0
  helpers::encode_json(std::to_string(search_start), back);
14163
0
  answer.append("\",\n");
14164
14165
0
  answer.append("\t\"hash_start\":\"");
14166
0
  helpers::encode_json(std::to_string(hash_start), back);
14167
0
  answer.append("\",\n");
14168
14169
0
  answer.append("\n}");
14170
0
  return answer;
14171
0
}
14172
14173
}  // namespace ada
14174
/* end file src/url_components.cpp */
14175
/* begin file src/url_aggregator.cpp */
14176
14177
#include <iterator>
14178
#include <ranges>
14179
#include <string>
14180
#include <string_view>
14181
14182
namespace ada {
14183
template <bool has_state_override>
14184
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
14185
0
    const std::string_view input_with_colon) {
14186
0
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14187
0
  ADA_ASSERT_TRUE(validate());
14188
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14189
0
  std::string_view input{input_with_colon};
14190
0
  input.remove_suffix(1);
14191
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
14192
0
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14193
  /**
14194
   * In the common case, we will immediately recognize a special scheme (e.g.,
14195
   *http, https), in which case, we can go really fast.
14196
   **/
14197
0
  if (is_input_special) {  // fast path!!!
14198
0
    if constexpr (has_state_override) {
14199
      // If url's scheme is not a special scheme and buffer is a special scheme,
14200
      // then return.
14201
0
      if (is_special() != is_input_special) {
14202
0
        return false;
14203
0
      }
14204
14205
      // If url includes credentials or has a non-null port, and buffer is
14206
      // "file", then return.
14207
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14208
0
          parsed_type == ada::scheme::type::FILE) {
14209
0
        return false;
14210
0
      }
14211
14212
      // If url's scheme is "file" and its host is an empty host, then return.
14213
      // An empty host is the empty string.
14214
0
      if (type == ada::scheme::type::FILE &&
14215
0
          components.host_start == components.host_end) {
14216
0
        return false;
14217
0
      }
14218
0
    }
14219
14220
0
    type = parsed_type;
14221
0
    set_scheme_from_view_with_colon(input_with_colon);
14222
14223
0
    if constexpr (has_state_override) {
14224
      // This is uncommon.
14225
0
      uint16_t urls_scheme_port = get_special_port();
14226
14227
      // If url's port is url's scheme's default port, then set url's port to
14228
      // null.
14229
0
      if (components.port == urls_scheme_port) {
14230
0
        clear_port();
14231
0
      }
14232
0
    }
14233
0
  } else {  // slow path
14234
0
    std::string _buffer(input);
14235
    // Next function is only valid if the input is ASCII and returns false
14236
    // otherwise, but it seems that we always have ascii content so we do not
14237
    // need to check the return value.
14238
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14239
14240
0
    if constexpr (has_state_override) {
14241
      // If url's scheme is a special scheme and buffer is not a special scheme,
14242
      // then return. If url's scheme is not a special scheme and buffer is a
14243
      // special scheme, then return.
14244
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
14245
0
        return true;
14246
0
      }
14247
14248
      // If url includes credentials or has a non-null port, and buffer is
14249
      // "file", then return.
14250
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14251
0
          _buffer == "file") {
14252
0
        return true;
14253
0
      }
14254
14255
      // If url's scheme is "file" and its host is an empty host, then return.
14256
      // An empty host is the empty string.
14257
0
      if (type == ada::scheme::type::FILE &&
14258
0
          components.host_start == components.host_end) {
14259
0
        return true;
14260
0
      }
14261
0
    }
14262
14263
0
    set_scheme(_buffer);
14264
14265
0
    if constexpr (has_state_override) {
14266
      // This is uncommon.
14267
0
      uint16_t urls_scheme_port = get_special_port();
14268
14269
      // If url's port is url's scheme's default port, then set url's port to
14270
      // null.
14271
0
      if (components.port == urls_scheme_port) {
14272
0
        clear_port();
14273
0
      }
14274
0
    }
14275
0
  }
14276
0
  ADA_ASSERT_TRUE(validate());
14277
0
  return true;
14278
0
}
Unexecuted instantiation: bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
14279
14280
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) {
14281
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14282
0
  ADA_ASSERT_TRUE(validate());
14283
  // next line could overflow but unsigned arithmetic has well-defined
14284
  // overflows.
14285
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14286
0
  type = u.type;
14287
0
  buffer.erase(0, components.protocol_end);
14288
0
  buffer.insert(0, u.get_protocol());
14289
0
  components.protocol_end = u.components.protocol_end;
14290
14291
  // No need to update the components
14292
0
  if (new_difference == 0) {
14293
0
    return;
14294
0
  }
14295
14296
  // Update the rest of the components.
14297
0
  components.username_end += new_difference;
14298
0
  components.host_start += new_difference;
14299
0
  components.host_end += new_difference;
14300
0
  components.pathname_start += new_difference;
14301
0
  if (components.search_start != url_components::omitted) {
14302
0
    components.search_start += new_difference;
14303
0
  }
14304
0
  if (components.hash_start != url_components::omitted) {
14305
0
    components.hash_start += new_difference;
14306
0
  }
14307
0
  ADA_ASSERT_TRUE(validate());
14308
0
}
14309
14310
inline void url_aggregator::set_scheme_from_view_with_colon(
14311
0
    std::string_view new_scheme_with_colon) {
14312
0
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14313
0
          new_scheme_with_colon);
14314
0
  ADA_ASSERT_TRUE(validate());
14315
0
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14316
0
                  new_scheme_with_colon.back() == ':');
14317
  // next line could overflow but unsigned arithmetic has well-defined
14318
  // overflows.
14319
0
  uint32_t new_difference =
14320
0
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14321
14322
0
  if (buffer.empty()) {
14323
0
    buffer.append(new_scheme_with_colon);
14324
0
  } else {
14325
0
    buffer.erase(0, components.protocol_end);
14326
0
    buffer.insert(0, new_scheme_with_colon);
14327
0
  }
14328
0
  components.protocol_end += new_difference;
14329
14330
  // Update the rest of the components.
14331
0
  components.username_end += new_difference;
14332
0
  components.host_start += new_difference;
14333
0
  components.host_end += new_difference;
14334
0
  components.pathname_start += new_difference;
14335
0
  if (components.search_start != url_components::omitted) {
14336
0
    components.search_start += new_difference;
14337
0
  }
14338
0
  if (components.hash_start != url_components::omitted) {
14339
0
    components.hash_start += new_difference;
14340
0
  }
14341
0
  ADA_ASSERT_TRUE(validate());
14342
0
}
14343
14344
0
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14345
0
  ada_log("url_aggregator::set_scheme ", new_scheme);
14346
0
  ADA_ASSERT_TRUE(validate());
14347
0
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14348
  // next line could overflow but unsigned arithmetic has well-defined
14349
  // overflows.
14350
0
  uint32_t new_difference =
14351
0
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14352
14353
0
  type = ada::scheme::get_scheme_type(new_scheme);
14354
0
  if (buffer.empty()) {
14355
0
    buffer.append(helpers::concat(new_scheme, ":"));
14356
0
  } else {
14357
0
    buffer.erase(0, components.protocol_end);
14358
0
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14359
0
  }
14360
0
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14361
14362
  // Update the rest of the components.
14363
0
  components.username_end += new_difference;
14364
0
  components.host_start += new_difference;
14365
0
  components.host_end += new_difference;
14366
0
  components.pathname_start += new_difference;
14367
0
  if (components.search_start != url_components::omitted) {
14368
0
    components.search_start += new_difference;
14369
0
  }
14370
0
  if (components.hash_start != url_components::omitted) {
14371
0
    components.hash_start += new_difference;
14372
0
  }
14373
0
  ADA_ASSERT_TRUE(validate());
14374
0
}
14375
14376
0
bool url_aggregator::set_protocol(const std::string_view input) {
14377
0
  ada_log("url_aggregator::set_protocol ", input);
14378
0
  ADA_ASSERT_TRUE(validate());
14379
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14380
0
  std::string view(input);
14381
0
  helpers::remove_ascii_tab_or_newline(view);
14382
0
  if (view.empty()) {
14383
0
    return true;
14384
0
  }
14385
14386
  // Schemes should start with alpha values.
14387
0
  if (!checkers::is_alpha(view[0])) {
14388
0
    return false;
14389
0
  }
14390
14391
0
  view.append(":");
14392
14393
0
  std::string::iterator pointer =
14394
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14395
14396
0
  if (pointer != view.end() && *pointer == ':') {
14397
0
    return parse_scheme_with_colon<true>(
14398
0
        view.substr(0, pointer - view.begin() + 1));
14399
0
  }
14400
0
  return false;
14401
0
}
14402
14403
0
bool url_aggregator::set_username(const std::string_view input) {
14404
0
  ada_log("url_aggregator::set_username '", input, "' ");
14405
0
  ADA_ASSERT_TRUE(validate());
14406
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14407
0
  if (cannot_have_credentials_or_port()) {
14408
0
    return false;
14409
0
  }
14410
0
  size_t idx = ada::unicode::percent_encode_index(
14411
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14412
0
  if (idx == input.size()) {
14413
0
    update_base_username(input);
14414
0
  } else {
14415
    // We only create a temporary string if we have to!
14416
0
    update_base_username(ada::unicode::percent_encode(
14417
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14418
0
  }
14419
0
  ADA_ASSERT_TRUE(validate());
14420
0
  return true;
14421
0
}
14422
14423
0
bool url_aggregator::set_password(const std::string_view input) {
14424
0
  ada_log("url_aggregator::set_password '", input, "'");
14425
0
  ADA_ASSERT_TRUE(validate());
14426
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14427
0
  if (cannot_have_credentials_or_port()) {
14428
0
    return false;
14429
0
  }
14430
0
  size_t idx = ada::unicode::percent_encode_index(
14431
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14432
0
  if (idx == input.size()) {
14433
0
    update_base_password(input);
14434
0
  } else {
14435
    // We only create a temporary string if we have to!
14436
0
    update_base_password(ada::unicode::percent_encode(
14437
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14438
0
  }
14439
0
  ADA_ASSERT_TRUE(validate());
14440
0
  return true;
14441
0
}
14442
14443
0
bool url_aggregator::set_port(const std::string_view input) {
14444
0
  ada_log("url_aggregator::set_port ", input);
14445
0
  ADA_ASSERT_TRUE(validate());
14446
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14447
0
  if (cannot_have_credentials_or_port()) {
14448
0
    return false;
14449
0
  }
14450
14451
0
  if (input.empty()) {
14452
0
    clear_port();
14453
0
    return true;
14454
0
  }
14455
14456
0
  std::string trimmed(input);
14457
0
  helpers::remove_ascii_tab_or_newline(trimmed);
14458
14459
0
  if (trimmed.empty()) {
14460
0
    return true;
14461
0
  }
14462
14463
  // Input should not start with a non-digit character.
14464
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14465
0
    return false;
14466
0
  }
14467
14468
  // Find the first non-digit character to determine the length of digits
14469
0
  auto first_non_digit =
14470
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14471
0
  std::string_view digits_to_parse =
14472
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14473
14474
  // Revert changes if parse_port fails.
14475
0
  uint32_t previous_port = components.port;
14476
0
  parse_port(digits_to_parse);
14477
0
  if (is_valid) {
14478
0
    return true;
14479
0
  }
14480
0
  update_base_port(previous_port);
14481
0
  is_valid = true;
14482
0
  ADA_ASSERT_TRUE(validate());
14483
0
  return false;
14484
0
}
14485
14486
0
bool url_aggregator::set_pathname(const std::string_view input) {
14487
0
  ada_log("url_aggregator::set_pathname ", input);
14488
0
  ADA_ASSERT_TRUE(validate());
14489
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14490
0
  if (has_opaque_path) {
14491
0
    return false;
14492
0
  }
14493
0
  clear_pathname();
14494
0
  parse_path(input);
14495
0
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14496
0
    buffer.insert(components.pathname_start, "/.");
14497
0
    components.pathname_start += 2;
14498
0
    if (components.search_start != url_components::omitted) {
14499
0
      components.search_start += 2;
14500
0
    }
14501
0
    if (components.hash_start != url_components::omitted) {
14502
0
      components.hash_start += 2;
14503
0
    }
14504
0
  }
14505
0
  ADA_ASSERT_TRUE(validate());
14506
0
  return true;
14507
0
}
14508
14509
0
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14510
0
  ada_log("url_aggregator::parse_path ", input);
14511
0
  ADA_ASSERT_TRUE(validate());
14512
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14513
0
  std::string tmp_buffer;
14514
0
  std::string_view internal_input;
14515
0
  if (unicode::has_tabs_or_newline(input)) {
14516
0
    tmp_buffer = input;
14517
    // Optimization opportunity: Instead of copying and then pruning, we could
14518
    // just directly build the string from user_input.
14519
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14520
0
    internal_input = tmp_buffer;
14521
0
  } else {
14522
0
    internal_input = input;
14523
0
  }
14524
14525
  // If url is special, then:
14526
0
  if (is_special()) {
14527
0
    if (internal_input.empty()) {
14528
0
      update_base_pathname("/");
14529
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14530
0
      consume_prepared_path(internal_input.substr(1));
14531
0
    } else {
14532
0
      consume_prepared_path(internal_input);
14533
0
    }
14534
0
  } else if (!internal_input.empty()) {
14535
0
    if (internal_input[0] == '/') {
14536
0
      consume_prepared_path(internal_input.substr(1));
14537
0
    } else {
14538
0
      consume_prepared_path(internal_input);
14539
0
    }
14540
0
  } else {
14541
    // Non-special URLs with an empty host can have their paths erased
14542
    // Path-only URLs cannot have their paths erased
14543
0
    if (components.host_start == components.host_end && !has_authority()) {
14544
0
      update_base_pathname("/");
14545
0
    }
14546
0
  }
14547
0
  ADA_ASSERT_TRUE(validate());
14548
0
}
14549
14550
0
void url_aggregator::set_search(const std::string_view input) {
14551
0
  ada_log("url_aggregator::set_search ", input);
14552
0
  ADA_ASSERT_TRUE(validate());
14553
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14554
0
  if (input.empty()) {
14555
0
    clear_search();
14556
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14557
0
    return;
14558
0
  }
14559
14560
0
  std::string new_value;
14561
0
  new_value = input[0] == '?' ? input.substr(1) : input;
14562
0
  helpers::remove_ascii_tab_or_newline(new_value);
14563
14564
0
  auto query_percent_encode_set =
14565
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14566
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14567
14568
0
  update_base_search(new_value, query_percent_encode_set);
14569
0
  ADA_ASSERT_TRUE(validate());
14570
0
}
14571
14572
0
void url_aggregator::set_hash(const std::string_view input) {
14573
0
  ada_log("url_aggregator::set_hash ", input);
14574
0
  ADA_ASSERT_TRUE(validate());
14575
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14576
0
  if (input.empty()) {
14577
0
    if (components.hash_start != url_components::omitted) {
14578
0
      buffer.resize(components.hash_start);
14579
0
      components.hash_start = url_components::omitted;
14580
0
    }
14581
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14582
0
    return;
14583
0
  }
14584
14585
0
  std::string new_value;
14586
0
  new_value = input[0] == '#' ? input.substr(1) : input;
14587
0
  helpers::remove_ascii_tab_or_newline(new_value);
14588
0
  update_unencoded_base_hash(new_value);
14589
0
  ADA_ASSERT_TRUE(validate());
14590
0
}
14591
14592
0
bool url_aggregator::set_href(const std::string_view input) {
14593
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14594
0
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14595
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14596
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
14597
14598
0
  if (out) {
14599
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14600
    // TODO: Figure out why the following line puts test to never finish.
14601
0
    *this = *out;
14602
0
  }
14603
14604
0
  return out.has_value();
14605
0
}
14606
14607
0
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14608
0
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14609
0
          " bytes]");
14610
0
  ADA_ASSERT_TRUE(validate());
14611
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14612
0
  if (input.empty()) {
14613
0
    return is_valid = false;
14614
0
  }  // technically unnecessary.
14615
  // If input starts with U+005B ([), then:
14616
0
  if (input[0] == '[') {
14617
    // If input does not end with U+005D (]), validation error, return failure.
14618
0
    if (input.back() != ']') {
14619
0
      return is_valid = false;
14620
0
    }
14621
0
    ada_log("parse_host ipv6");
14622
14623
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14624
    // trailing U+005D (]) removed.
14625
0
    input.remove_prefix(1);
14626
0
    input.remove_suffix(1);
14627
0
    return parse_ipv6(input);
14628
0
  }
14629
14630
  // If isNotSpecial is true, then return the result of opaque-host parsing
14631
  // input.
14632
0
  if (!is_special()) {
14633
0
    return parse_opaque_host(input);
14634
0
  }
14635
  // Let domain be the result of running UTF-8 decode without BOM on the
14636
  // percent-decoding of input. Let asciiDomain be the result of running domain
14637
  // to ASCII with domain and false. The most common case is an ASCII input, in
14638
  // which case we do not need to call the expensive 'to_ascii' if a few
14639
  // conditions are met: no '%' and no 'xn-' subsequence.
14640
14641
  // Often, the input does not contain any forbidden code points, and no upper
14642
  // case ASCII letter, then we can just copy it to the buffer. We want to
14643
  // optimize for such a common case.
14644
14645
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
14646
0
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14647
0
  if (fast_result < checkers::ipv4_fast_fail) {
14648
    // Fast path succeeded - input is pure decimal IPv4
14649
0
    if (!input.empty() && input.back() == '.') {
14650
0
      update_base_hostname(input.substr(0, input.size() - 1));
14651
0
    } else {
14652
0
      update_base_hostname(input);
14653
0
    }
14654
0
    host_type = IPV4;
14655
0
    ada_log("parse_host fast path decimal ipv4");
14656
0
    ADA_ASSERT_TRUE(validate());
14657
0
    return true;
14658
0
  }
14659
0
  uint8_t is_forbidden_or_upper =
14660
0
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14661
0
                                                             input.size());
14662
  // Minor optimization opportunity:
14663
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14664
  // the presence of characters that cannot appear in the ipv4 address and we
14665
  // could also check whether x and n and - are present, and so we could skip
14666
  // some of the checks below. However, the gains are likely to be small, and
14667
  // the code would be more complex.
14668
0
  if (is_forbidden_or_upper == 0 &&
14669
0
      input.find("xn-") == std::string_view::npos) {
14670
    // fast path
14671
0
    update_base_hostname(input);
14672
14673
    // Check for other IPv4 formats (hex, octal, etc.)
14674
0
    if (checkers::is_ipv4(get_hostname())) {
14675
0
      ada_log("parse_host fast path ipv4");
14676
0
      return parse_ipv4(get_hostname(), true);
14677
0
    }
14678
0
    ada_log("parse_host fast path ", get_hostname());
14679
0
    return true;
14680
0
  }
14681
  // We have encountered at least one forbidden code point or the input contains
14682
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14683
  // conversion.
14684
14685
0
  ada_log("parse_host calling to_ascii");
14686
0
  std::optional<std::string> host = std::string(get_hostname());
14687
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14688
0
  if (!is_valid) {
14689
0
    ada_log("parse_host to_ascii returns false");
14690
0
    return is_valid = false;
14691
0
  }
14692
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14693
0
          " bytes]");
14694
14695
0
  if (std::ranges::any_of(host.value(),
14696
0
                          ada::unicode::is_forbidden_domain_code_point)) {
14697
0
    return is_valid = false;
14698
0
  }
14699
14700
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14701
  // asciiDomain.
14702
0
  if (checkers::is_ipv4(host.value())) {
14703
0
    ada_log("parse_host got ipv4 ", *host);
14704
0
    return parse_ipv4(host.value(), false);
14705
0
  }
14706
14707
0
  update_base_hostname(host.value());
14708
0
  ADA_ASSERT_TRUE(validate());
14709
0
  return true;
14710
0
}
14711
14712
template <bool override_hostname>
14713
0
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14714
0
  ada_log("url_aggregator::set_host_or_hostname ", input);
14715
0
  ADA_ASSERT_TRUE(validate());
14716
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14717
0
  if (has_opaque_path) {
14718
0
    return false;
14719
0
  }
14720
14721
0
  std::string previous_host(get_hostname());
14722
0
  uint32_t previous_port = components.port;
14723
14724
0
  size_t host_end_pos = input.find('#');
14725
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14726
0
                                      ? host_end_pos
14727
0
                                      : input.size());
14728
0
  helpers::remove_ascii_tab_or_newline(_host);
14729
0
  std::string_view new_host(_host);
14730
14731
  // If url's scheme is "file", then set state to file host state, instead of
14732
  // host state.
14733
0
  if (type != ada::scheme::type::FILE) {
14734
0
    std::string_view host_view(_host.data(), _host.length());
14735
0
    auto [location, found_colon] =
14736
0
        helpers::get_host_delimiter_location(is_special(), host_view);
14737
14738
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14739
    // Note: the 'found_colon' value is true if and only if a colon was
14740
    // encountered while not inside brackets.
14741
0
    if (found_colon) {
14742
      // If buffer is the empty string, host-missing validation error, return
14743
      // failure.
14744
0
      std::string_view host_buffer = host_view.substr(0, location);
14745
0
      if (host_buffer.empty()) {
14746
0
        return false;
14747
0
      }
14748
14749
      // If state override is given and state override is hostname state, then
14750
      // return failure.
14751
0
      if constexpr (override_hostname) {
14752
0
        return false;
14753
0
      }
14754
14755
      // Let host be the result of host parsing buffer with url is not special.
14756
0
      bool succeeded = parse_host(host_buffer);
14757
0
      if (!succeeded) {
14758
0
        update_base_hostname(previous_host);
14759
0
        update_base_port(previous_port);
14760
0
        return false;
14761
0
      }
14762
14763
      // Set url's host to host, buffer to the empty string, and state to port
14764
      // state.
14765
0
      std::string_view port_buffer = new_host.substr(location + 1);
14766
0
      if (!port_buffer.empty()) {
14767
0
        set_port(port_buffer);
14768
0
      }
14769
0
      return true;
14770
0
    }
14771
    // Otherwise, if one of the following is true:
14772
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14773
    // - url is special and c is U+005C (\)
14774
0
    else {
14775
      // If url is special and host_view is the empty string, host-missing
14776
      // validation error, return failure.
14777
0
      if (host_view.empty() && is_special()) {
14778
0
        return false;
14779
0
      }
14780
14781
      // Otherwise, if state override is given, host_view is the empty string,
14782
      // and either url includes credentials or url's port is non-null, then
14783
      // return failure.
14784
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14785
0
        return false;
14786
0
      }
14787
14788
      // Let host be the result of host parsing host_view with url is not
14789
      // special.
14790
0
      if (host_view.empty() && !is_special()) {
14791
0
        if (has_hostname()) {
14792
0
          clear_hostname();  // easy!
14793
0
        } else if (has_dash_dot()) {
14794
0
          add_authority_slashes_if_needed();
14795
0
          delete_dash_dot();
14796
0
        }
14797
0
        return true;
14798
0
      }
14799
14800
0
      bool succeeded = parse_host(host_view);
14801
0
      if (!succeeded) {
14802
0
        update_base_hostname(previous_host);
14803
0
        update_base_port(previous_port);
14804
0
        return false;
14805
0
      } else if (has_dash_dot()) {
14806
        // Should remove dash_dot from pathname
14807
0
        delete_dash_dot();
14808
0
      }
14809
0
      return true;
14810
0
    }
14811
0
  }
14812
14813
0
  size_t location = new_host.find_first_of("/\\?");
14814
0
  if (location != std::string_view::npos) {
14815
0
    new_host.remove_suffix(new_host.length() - location);
14816
0
  }
14817
14818
0
  if (new_host.empty()) {
14819
    // Set url's host to the empty string.
14820
0
    clear_hostname();
14821
0
  } else {
14822
    // Let host be the result of host parsing buffer with url is not special.
14823
0
    if (!parse_host(new_host)) {
14824
0
      update_base_hostname(previous_host);
14825
0
      update_base_port(previous_port);
14826
0
      return false;
14827
0
    }
14828
14829
    // If host is "localhost", then set host to the empty string.
14830
0
    if (helpers::substring(buffer, components.host_start,
14831
0
                           components.host_end) == "localhost") {
14832
0
      clear_hostname();
14833
0
    }
14834
0
  }
14835
0
  ADA_ASSERT_TRUE(validate());
14836
0
  return true;
14837
0
}
Unexecuted instantiation: bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
14838
14839
0
bool url_aggregator::set_host(const std::string_view input) {
14840
0
  ada_log("url_aggregator::set_host '", input, "'");
14841
0
  ADA_ASSERT_TRUE(validate());
14842
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14843
0
  return set_host_or_hostname<false>(input);
14844
0
}
14845
14846
0
bool url_aggregator::set_hostname(const std::string_view input) {
14847
0
  ada_log("url_aggregator::set_hostname '", input, "'");
14848
0
  ADA_ASSERT_TRUE(validate());
14849
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14850
0
  return set_host_or_hostname<true>(input);
14851
0
}
14852
14853
0
[[nodiscard]] std::string url_aggregator::get_origin() const {
14854
0
  ada_log("url_aggregator::get_origin");
14855
0
  if (is_special()) {
14856
    // Return a new opaque origin.
14857
0
    if (type == scheme::FILE) {
14858
0
      return "null";
14859
0
    }
14860
14861
0
    return helpers::concat(get_protocol(), "//", get_host());
14862
0
  }
14863
14864
0
  if (get_protocol() == "blob:") {
14865
0
    std::string_view path = get_pathname();
14866
0
    if (!path.empty()) {
14867
0
      auto out = ada::parse<ada::url_aggregator>(path);
14868
0
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14869
        // If pathURL's scheme is not "http" and not "https", then return a
14870
        // new opaque origin.
14871
0
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14872
0
      }
14873
0
    }
14874
0
  }
14875
14876
  // Return a new opaque origin.
14877
0
  return "null";
14878
0
}
14879
14880
[[nodiscard]] std::string_view url_aggregator::get_username() const
14881
0
    ada_lifetime_bound {
14882
0
  ada_log("url_aggregator::get_username");
14883
0
  if (has_non_empty_username()) {
14884
0
    return helpers::substring(buffer, components.protocol_end + 2,
14885
0
                              components.username_end);
14886
0
  }
14887
0
  return "";
14888
0
}
14889
14890
[[nodiscard]] std::string_view url_aggregator::get_password() const
14891
0
    ada_lifetime_bound {
14892
0
  ada_log("url_aggregator::get_password");
14893
0
  if (has_non_empty_password()) {
14894
0
    return helpers::substring(buffer, components.username_end + 1,
14895
0
                              components.host_start);
14896
0
  }
14897
0
  return "";
14898
0
}
14899
14900
[[nodiscard]] std::string_view url_aggregator::get_port() const
14901
0
    ada_lifetime_bound {
14902
0
  ada_log("url_aggregator::get_port");
14903
0
  if (components.port == url_components::omitted) {
14904
0
    return "";
14905
0
  }
14906
0
  return helpers::substring(buffer, components.host_end + 1,
14907
0
                            components.pathname_start);
14908
0
}
14909
14910
[[nodiscard]] std::string_view url_aggregator::get_hash() const
14911
0
    ada_lifetime_bound {
14912
0
  ada_log("url_aggregator::get_hash");
14913
  // If this's URL's fragment is either null or the empty string, then return
14914
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14915
0
  if (components.hash_start == url_components::omitted) {
14916
0
    return "";
14917
0
  }
14918
0
  if (buffer.size() - components.hash_start <= 1) {
14919
0
    return "";
14920
0
  }
14921
0
  return helpers::substring(buffer, components.hash_start);
14922
0
}
14923
14924
[[nodiscard]] std::string_view url_aggregator::get_host() const
14925
0
    ada_lifetime_bound {
14926
0
  ada_log("url_aggregator::get_host");
14927
  // Technically, we should check if there is a hostname, but
14928
  // the code below works even if there isn't.
14929
  // if(!has_hostname()) { return ""; }
14930
0
  size_t start = components.host_start;
14931
0
  if (components.host_end > components.host_start &&
14932
0
      buffer[components.host_start] == '@') {
14933
0
    start++;
14934
0
  }
14935
  // if we have an empty host, then the space between components.host_end and
14936
  // components.pathname_start may be occupied by /.
14937
0
  if (start == components.host_end) {
14938
0
    return {};
14939
0
  }
14940
0
  return helpers::substring(buffer, start, components.pathname_start);
14941
0
}
14942
14943
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
14944
0
    ada_lifetime_bound {
14945
0
  ada_log("url_aggregator::get_hostname");
14946
  // Technically, we should check if there is a hostname, but
14947
  // the code below works even if there isn't.
14948
  // if(!has_hostname()) { return ""; }
14949
0
  size_t start = components.host_start;
14950
  // So host_start is not where the host begins.
14951
0
  if (components.host_end > components.host_start &&
14952
0
      buffer[components.host_start] == '@') {
14953
0
    start++;
14954
0
  }
14955
0
  return helpers::substring(buffer, start, components.host_end);
14956
0
}
14957
14958
[[nodiscard]] std::string_view url_aggregator::get_search() const
14959
0
    ada_lifetime_bound {
14960
0
  ada_log("url_aggregator::get_search");
14961
  // If this's URL's query is either null or the empty string, then return the
14962
  // empty string. Return U+003F (?), followed by this's URL's query.
14963
0
  if (components.search_start == url_components::omitted) {
14964
0
    return "";
14965
0
  }
14966
0
  auto ending_index = uint32_t(buffer.size());
14967
0
  if (components.hash_start != url_components::omitted) {
14968
0
    ending_index = components.hash_start;
14969
0
  }
14970
0
  if (ending_index - components.search_start <= 1) {
14971
0
    return "";
14972
0
  }
14973
0
  return helpers::substring(buffer, components.search_start, ending_index);
14974
0
}
14975
14976
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
14977
0
    ada_lifetime_bound {
14978
0
  ada_log("url_aggregator::get_protocol");
14979
0
  return helpers::substring(buffer, 0, components.protocol_end);
14980
0
}
14981
14982
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14983
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14984
0
          " bytes]");
14985
0
  if (!is_valid) {
14986
0
    return "null";
14987
0
  }
14988
14989
0
  std::string answer;
14990
0
  auto back = std::back_insert_iterator(answer);
14991
0
  answer.append("{\n");
14992
14993
0
  answer.append("\t\"buffer\":\"");
14994
0
  helpers::encode_json(buffer, back);
14995
0
  answer.append("\",\n");
14996
14997
0
  answer.append("\t\"protocol\":\"");
14998
0
  helpers::encode_json(get_protocol(), back);
14999
0
  answer.append("\",\n");
15000
15001
0
  if (has_credentials()) {
15002
0
    answer.append("\t\"username\":\"");
15003
0
    helpers::encode_json(get_username(), back);
15004
0
    answer.append("\",\n");
15005
0
    answer.append("\t\"password\":\"");
15006
0
    helpers::encode_json(get_password(), back);
15007
0
    answer.append("\",\n");
15008
0
  }
15009
15010
0
  answer.append("\t\"host\":\"");
15011
0
  helpers::encode_json(get_host(), back);
15012
0
  answer.append("\",\n");
15013
15014
0
  answer.append("\t\"path\":\"");
15015
0
  helpers::encode_json(get_pathname(), back);
15016
0
  answer.append("\",\n");
15017
0
  answer.append("\t\"opaque path\":");
15018
0
  answer.append((has_opaque_path ? "true" : "false"));
15019
0
  answer.append(",\n");
15020
15021
0
  if (components.search_start != url_components::omitted) {
15022
0
    answer.append("\t\"query\":\"");
15023
0
    helpers::encode_json(get_search(), back);
15024
0
    answer.append("\",\n");
15025
0
  }
15026
0
  if (components.hash_start != url_components::omitted) {
15027
0
    answer.append("\t\"fragment\":\"");
15028
0
    helpers::encode_json(get_hash(), back);
15029
0
    answer.append("\",\n");
15030
0
  }
15031
15032
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15033
0
    if (offset == url_components::omitted) {
15034
0
      return "null";
15035
0
    } else {
15036
0
      return std::to_string(offset);
15037
0
    }
15038
0
  };
15039
15040
0
  answer.append("\t\"protocol_end\":");
15041
0
  answer.append(convert_offset_to_string(components.protocol_end));
15042
0
  answer.append(",\n");
15043
15044
0
  answer.append("\t\"username_end\":");
15045
0
  answer.append(convert_offset_to_string(components.username_end));
15046
0
  answer.append(",\n");
15047
15048
0
  answer.append("\t\"host_start\":");
15049
0
  answer.append(convert_offset_to_string(components.host_start));
15050
0
  answer.append(",\n");
15051
15052
0
  answer.append("\t\"host_end\":");
15053
0
  answer.append(convert_offset_to_string(components.host_end));
15054
0
  answer.append(",\n");
15055
15056
0
  answer.append("\t\"port\":");
15057
0
  answer.append(convert_offset_to_string(components.port));
15058
0
  answer.append(",\n");
15059
15060
0
  answer.append("\t\"pathname_start\":");
15061
0
  answer.append(convert_offset_to_string(components.pathname_start));
15062
0
  answer.append(",\n");
15063
15064
0
  answer.append("\t\"search_start\":");
15065
0
  answer.append(convert_offset_to_string(components.search_start));
15066
0
  answer.append(",\n");
15067
15068
0
  answer.append("\t\"hash_start\":");
15069
0
  answer.append(convert_offset_to_string(components.hash_start));
15070
0
  answer.append("\n}");
15071
15072
0
  return answer;
15073
0
}
15074
15075
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15076
0
  if (components.host_start == components.host_end) {
15077
0
    return false;
15078
0
  }
15079
0
  return checkers::verify_dns_length(get_hostname());
15080
0
}
15081
15082
0
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15083
0
  ada_log("parse_ipv4 ", input, " [", input.size(),
15084
0
          " bytes], overlaps with buffer: ",
15085
0
          helpers::overlaps(input, buffer) ? "yes" : "no");
15086
0
  ADA_ASSERT_TRUE(validate());
15087
0
  const bool trailing_dot = (input.back() == '.');
15088
0
  if (trailing_dot) {
15089
0
    input.remove_suffix(1);
15090
0
  }
15091
0
  size_t digit_count{0};
15092
0
  int pure_decimal_count = 0;  // entries that are decimal
15093
0
  uint64_t ipv4{0};
15094
  // we could unroll for better performance?
15095
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15096
0
    uint32_t
15097
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15098
0
    bool is_hex = checkers::has_hex_prefix(input);
15099
0
    if (is_hex && ((input.length() == 2) ||
15100
0
                   ((input.length() > 2) && (input[2] == '.')))) {
15101
      // special case
15102
0
      segment_result = 0;
15103
0
      input.remove_prefix(2);
15104
0
    } else {
15105
0
      std::from_chars_result r{};
15106
0
      if (is_hex) {
15107
0
        ada_log("parse_ipv4 trying to parse hex number");
15108
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15109
0
                            segment_result, 16);
15110
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
15111
0
                 checkers::is_digit(input[1])) {
15112
0
        ada_log("parse_ipv4 trying to parse octal number");
15113
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15114
0
                            segment_result, 8);
15115
0
      } else {
15116
0
        ada_log("parse_ipv4 trying to parse decimal number");
15117
0
        pure_decimal_count++;
15118
0
        r = std::from_chars(input.data(), input.data() + input.size(),
15119
0
                            segment_result, 10);
15120
0
      }
15121
0
      if (r.ec != std::errc()) {
15122
0
        ada_log("parse_ipv4 parsing failed");
15123
0
        return is_valid = false;
15124
0
      }
15125
0
      ada_log("parse_ipv4 parsed ", segment_result);
15126
0
      input.remove_prefix(r.ptr - input.data());
15127
0
    }
15128
0
    if (input.empty()) {
15129
      // We have the last value.
15130
      // At this stage, ipv4 contains digit_count*8 bits.
15131
      // So we have 32-digit_count*8 bits left.
15132
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15133
0
        return is_valid = false;
15134
0
      }
15135
0
      ipv4 <<= (32 - digit_count * 8);
15136
0
      ipv4 |= segment_result;
15137
0
      goto final;
15138
0
    } else {
15139
      // There is more, so that the value must no be larger than 255
15140
      // and we must have a '.'.
15141
0
      if ((segment_result > 255) || (input[0] != '.')) {
15142
0
        return is_valid = false;
15143
0
      }
15144
0
      ipv4 <<= 8;
15145
0
      ipv4 |= segment_result;
15146
0
      input.remove_prefix(1);  // remove '.'
15147
0
    }
15148
0
  }
15149
0
  if ((digit_count != 4) || (!input.empty())) {
15150
0
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15151
0
    return is_valid = false;
15152
0
  }
15153
0
final:
15154
0
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15155
0
          " host: ", get_host());
15156
15157
  // We could also check r.ptr to see where the parsing ended.
15158
0
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
15159
0
    ada_log(
15160
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
15161
0
        "buffer");
15162
    // The original input was already all decimal and we validated it. So we
15163
    // don't need to do anything.
15164
0
  } else {
15165
0
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
15166
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
15167
    // serializer.
15168
    // TODO: This is likely a bug because it goes back update_base_hostname, not
15169
    // what we want to do.
15170
0
    update_base_hostname(
15171
0
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15172
0
  }
15173
0
  host_type = IPV4;
15174
0
  ADA_ASSERT_TRUE(validate());
15175
0
  return true;
15176
0
}
15177
15178
0
bool url_aggregator::parse_ipv6(std::string_view input) {
15179
  // TODO: Implement in_place optimization: we know that input points
15180
  // in the buffer, so we can just check whether the buffer is already
15181
  // well formatted.
15182
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
15183
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15184
0
  ADA_ASSERT_TRUE(validate());
15185
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15186
0
  if (input.empty()) {
15187
0
    return is_valid = false;
15188
0
  }
15189
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15190
0
  std::array<uint16_t, 8> address{};
15191
15192
  // Let pieceIndex be 0.
15193
0
  int piece_index = 0;
15194
15195
  // Let compress be null.
15196
0
  std::optional<int> compress{};
15197
15198
  // Let pointer be a pointer for input.
15199
0
  std::string_view::iterator pointer = input.begin();
15200
15201
  // If c is U+003A (:), then:
15202
0
  if (input[0] == ':') {
15203
    // If remaining does not start with U+003A (:), validation error, return
15204
    // failure.
15205
0
    if (input.size() == 1 || input[1] != ':') {
15206
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15207
0
      return is_valid = false;
15208
0
    }
15209
15210
    // Increase pointer by 2.
15211
0
    pointer += 2;
15212
15213
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15214
0
    compress = ++piece_index;
15215
0
  }
15216
15217
  // While c is not the EOF code point:
15218
0
  while (pointer != input.end()) {
15219
    // If pieceIndex is 8, validation error, return failure.
15220
0
    if (piece_index == 8) {
15221
0
      ada_log("parse_ipv6 piece_index == 8");
15222
0
      return is_valid = false;
15223
0
    }
15224
15225
    // If c is U+003A (:), then:
15226
0
    if (*pointer == ':') {
15227
      // If compress is non-null, validation error, return failure.
15228
0
      if (compress.has_value()) {
15229
0
        ada_log("parse_ipv6 compress is non-null");
15230
0
        return is_valid = false;
15231
0
      }
15232
15233
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15234
      // then continue.
15235
0
      pointer++;
15236
0
      compress = ++piece_index;
15237
0
      continue;
15238
0
    }
15239
15240
    // Let value and length be 0.
15241
0
    uint16_t value = 0, length = 0;
15242
15243
    // While length is less than 4 and c is an ASCII hex digit,
15244
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15245
    // increase pointer and length by 1.
15246
0
    while (length < 4 && pointer != input.end() &&
15247
0
           unicode::is_ascii_hex_digit(*pointer)) {
15248
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15249
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15250
0
      pointer++;
15251
0
      length++;
15252
0
    }
15253
15254
    // If c is U+002E (.), then:
15255
0
    if (pointer != input.end() && *pointer == '.') {
15256
      // If length is 0, validation error, return failure.
15257
0
      if (length == 0) {
15258
0
        ada_log("parse_ipv6 length is 0");
15259
0
        return is_valid = false;
15260
0
      }
15261
15262
      // Decrease pointer by length.
15263
0
      pointer -= length;
15264
15265
      // If pieceIndex is greater than 6, validation error, return failure.
15266
0
      if (piece_index > 6) {
15267
0
        ada_log("parse_ipv6 piece_index > 6");
15268
0
        return is_valid = false;
15269
0
      }
15270
15271
      // Let numbersSeen be 0.
15272
0
      int numbers_seen = 0;
15273
15274
      // While c is not the EOF code point:
15275
0
      while (pointer != input.end()) {
15276
        // Let ipv4Piece be null.
15277
0
        std::optional<uint16_t> ipv4_piece{};
15278
15279
        // If numbersSeen is greater than 0, then:
15280
0
        if (numbers_seen > 0) {
15281
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15282
          // pointer by 1.
15283
0
          if (*pointer == '.' && numbers_seen < 4) {
15284
0
            pointer++;
15285
0
          } else {
15286
            // Otherwise, validation error, return failure.
15287
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15288
0
            return is_valid = false;
15289
0
          }
15290
0
        }
15291
15292
        // If c is not an ASCII digit, validation error, return failure.
15293
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15294
0
          ada_log(
15295
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15296
0
              "failure");
15297
0
          return is_valid = false;
15298
0
        }
15299
15300
        // While c is an ASCII digit:
15301
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15302
          // Let number be c interpreted as decimal number.
15303
0
          int number = *pointer - '0';
15304
15305
          // If ipv4Piece is null, then set ipv4Piece to number.
15306
0
          if (!ipv4_piece.has_value()) {
15307
0
            ipv4_piece = number;
15308
0
          }
15309
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15310
0
          else if (ipv4_piece == 0) {
15311
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15312
0
            return is_valid = false;
15313
0
          }
15314
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15315
0
          else {
15316
0
            ipv4_piece = *ipv4_piece * 10 + number;
15317
0
          }
15318
15319
          // If ipv4Piece is greater than 255, validation error, return failure.
15320
0
          if (ipv4_piece > 255) {
15321
0
            ada_log("parse_ipv6 ipv4_piece > 255");
15322
0
            return is_valid = false;
15323
0
          }
15324
15325
          // Increase pointer by 1.
15326
0
          pointer++;
15327
0
        }
15328
15329
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15330
        // ipv4Piece.
15331
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15332
0
        address[piece_index] =
15333
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15334
15335
        // Increase numbersSeen by 1.
15336
0
        numbers_seen++;
15337
15338
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15339
0
        if (numbers_seen == 2 || numbers_seen == 4) {
15340
0
          piece_index++;
15341
0
        }
15342
0
      }
15343
15344
      // If numbersSeen is not 4, validation error, return failure.
15345
0
      if (numbers_seen != 4) {
15346
0
        return is_valid = false;
15347
0
      }
15348
15349
      // Break.
15350
0
      break;
15351
0
    }
15352
    // Otherwise, if c is U+003A (:):
15353
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
15354
      // Increase pointer by 1.
15355
0
      pointer++;
15356
15357
      // If c is the EOF code point, validation error, return failure.
15358
0
      if (pointer == input.end()) {
15359
0
        ada_log(
15360
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
15361
0
            "failure");
15362
0
        return is_valid = false;
15363
0
      }
15364
0
    }
15365
    // Otherwise, if c is not the EOF code point, validation error, return
15366
    // failure.
15367
0
    else if (pointer != input.end()) {
15368
0
      ada_log(
15369
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15370
0
          "error, return failure");
15371
0
      return is_valid = false;
15372
0
    }
15373
15374
    // Set address[pieceIndex] to value.
15375
0
    address[piece_index] = value;
15376
15377
    // Increase pieceIndex by 1.
15378
0
    piece_index++;
15379
0
  }
15380
15381
  // If compress is non-null, then:
15382
0
  if (compress.has_value()) {
15383
    // Let swaps be pieceIndex - compress.
15384
0
    int swaps = piece_index - *compress;
15385
15386
    // Set pieceIndex to 7.
15387
0
    piece_index = 7;
15388
15389
    // While pieceIndex is not 0 and swaps is greater than 0,
15390
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15391
    // decrease both pieceIndex and swaps by 1.
15392
0
    while (piece_index != 0 && swaps > 0) {
15393
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15394
0
      piece_index--;
15395
0
      swaps--;
15396
0
    }
15397
0
  }
15398
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15399
  // return failure.
15400
0
  else if (piece_index != 8) {
15401
0
    ada_log(
15402
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15403
0
        "error, return failure");
15404
0
    return is_valid = false;
15405
0
  }
15406
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15407
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15408
  // what we want to do.
15409
0
  update_base_hostname(ada::serializers::ipv6(address));
15410
0
  ada_log("parse_ipv6 ", get_hostname());
15411
0
  ADA_ASSERT_TRUE(validate());
15412
0
  host_type = IPV6;
15413
0
  return true;
15414
0
}
15415
15416
0
bool url_aggregator::parse_opaque_host(std::string_view input) {
15417
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15418
0
  ADA_ASSERT_TRUE(validate());
15419
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15420
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15421
0
    return is_valid = false;
15422
0
  }
15423
15424
  // Return the result of running UTF-8 percent-encode on input using the C0
15425
  // control percent-encode set.
15426
0
  size_t idx = ada::unicode::percent_encode_index(
15427
0
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15428
0
  if (idx == input.size()) {
15429
0
    update_base_hostname(input);
15430
0
  } else {
15431
    // We only create a temporary string if we need to.
15432
0
    update_base_hostname(ada::unicode::percent_encode(
15433
0
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15434
0
  }
15435
0
  ADA_ASSERT_TRUE(validate());
15436
0
  return true;
15437
0
}
15438
15439
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15440
0
  if (!is_valid) {
15441
0
    return "invalid";
15442
0
  }
15443
0
  std::string answer;
15444
0
  answer.append(buffer);
15445
0
  answer.append(" [");
15446
0
  answer.append(std::to_string(buffer.size()));
15447
0
  answer.append(" bytes]");
15448
0
  answer.append("\n");
15449
  // first line
15450
0
  std::string line1;
15451
0
  line1.resize(buffer.size(), ' ');
15452
0
  if (components.hash_start != url_components::omitted) {
15453
0
    line1[components.hash_start] = '|';
15454
0
  }
15455
0
  if (components.search_start != url_components::omitted) {
15456
0
    line1[components.search_start] = '|';
15457
0
  }
15458
0
  if (components.pathname_start != buffer.size()) {
15459
0
    line1[components.pathname_start] = '|';
15460
0
  }
15461
0
  if (components.host_end != buffer.size()) {
15462
0
    line1[components.host_end] = '|';
15463
0
  }
15464
0
  if (components.host_start != buffer.size()) {
15465
0
    line1[components.host_start] = '|';
15466
0
  }
15467
0
  if (components.username_end != buffer.size()) {
15468
0
    line1[components.username_end] = '|';
15469
0
  }
15470
0
  if (components.protocol_end != buffer.size()) {
15471
0
    line1[components.protocol_end] = '|';
15472
0
  }
15473
0
  answer.append(line1);
15474
0
  answer.append("\n");
15475
15476
0
  std::string line2 = line1;
15477
0
  if (components.hash_start != url_components::omitted) {
15478
0
    line2[components.hash_start] = '`';
15479
0
    line1[components.hash_start] = ' ';
15480
15481
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15482
0
      line2[i] = '-';
15483
0
    }
15484
0
    line2.append(" hash_start");
15485
0
    answer.append(line2);
15486
0
    answer.append("\n");
15487
0
  }
15488
15489
0
  std::string line3 = line1;
15490
0
  if (components.search_start != url_components::omitted) {
15491
0
    line3[components.search_start] = '`';
15492
0
    line1[components.search_start] = ' ';
15493
15494
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15495
0
      line3[i] = '-';
15496
0
    }
15497
0
    line3.append(" search_start ");
15498
0
    line3.append(std::to_string(components.search_start));
15499
0
    answer.append(line3);
15500
0
    answer.append("\n");
15501
0
  }
15502
15503
0
  std::string line4 = line1;
15504
0
  if (components.pathname_start != buffer.size()) {
15505
0
    line4[components.pathname_start] = '`';
15506
0
    line1[components.pathname_start] = ' ';
15507
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15508
0
      line4[i] = '-';
15509
0
    }
15510
0
    line4.append(" pathname_start ");
15511
0
    line4.append(std::to_string(components.pathname_start));
15512
0
    answer.append(line4);
15513
0
    answer.append("\n");
15514
0
  }
15515
15516
0
  std::string line5 = line1;
15517
0
  if (components.host_end != buffer.size()) {
15518
0
    line5[components.host_end] = '`';
15519
0
    line1[components.host_end] = ' ';
15520
15521
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15522
0
      line5[i] = '-';
15523
0
    }
15524
0
    line5.append(" host_end ");
15525
0
    line5.append(std::to_string(components.host_end));
15526
0
    answer.append(line5);
15527
0
    answer.append("\n");
15528
0
  }
15529
15530
0
  std::string line6 = line1;
15531
0
  if (components.host_start != buffer.size()) {
15532
0
    line6[components.host_start] = '`';
15533
0
    line1[components.host_start] = ' ';
15534
15535
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15536
0
      line6[i] = '-';
15537
0
    }
15538
0
    line6.append(" host_start ");
15539
0
    line6.append(std::to_string(components.host_start));
15540
0
    answer.append(line6);
15541
0
    answer.append("\n");
15542
0
  }
15543
15544
0
  std::string line7 = line1;
15545
0
  if (components.username_end != buffer.size()) {
15546
0
    line7[components.username_end] = '`';
15547
0
    line1[components.username_end] = ' ';
15548
15549
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15550
0
      line7[i] = '-';
15551
0
    }
15552
0
    line7.append(" username_end ");
15553
0
    line7.append(std::to_string(components.username_end));
15554
0
    answer.append(line7);
15555
0
    answer.append("\n");
15556
0
  }
15557
15558
0
  std::string line8 = line1;
15559
0
  if (components.protocol_end != buffer.size()) {
15560
0
    line8[components.protocol_end] = '`';
15561
0
    line1[components.protocol_end] = ' ';
15562
15563
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15564
0
      line8[i] = '-';
15565
0
    }
15566
0
    line8.append(" protocol_end ");
15567
0
    line8.append(std::to_string(components.protocol_end));
15568
0
    answer.append(line8);
15569
0
    answer.append("\n");
15570
0
  }
15571
15572
0
  if (components.hash_start == url_components::omitted) {
15573
0
    answer.append("note: hash omitted\n");
15574
0
  }
15575
0
  if (components.search_start == url_components::omitted) {
15576
0
    answer.append("note: search omitted\n");
15577
0
  }
15578
0
  if (components.protocol_end > buffer.size()) {
15579
0
    answer.append("warning: protocol_end overflows\n");
15580
0
  }
15581
0
  if (components.username_end > buffer.size()) {
15582
0
    answer.append("warning: username_end overflows\n");
15583
0
  }
15584
0
  if (components.host_start > buffer.size()) {
15585
0
    answer.append("warning: host_start overflows\n");
15586
0
  }
15587
0
  if (components.host_end > buffer.size()) {
15588
0
    answer.append("warning: host_end overflows\n");
15589
0
  }
15590
0
  if (components.pathname_start > buffer.size()) {
15591
0
    answer.append("warning: pathname_start overflows\n");
15592
0
  }
15593
0
  return answer;
15594
0
}
15595
15596
0
void url_aggregator::delete_dash_dot() {
15597
0
  ada_log("url_aggregator::delete_dash_dot");
15598
0
  ADA_ASSERT_TRUE(validate());
15599
0
  ADA_ASSERT_TRUE(has_dash_dot());
15600
0
  buffer.erase(components.host_end, 2);
15601
0
  components.pathname_start -= 2;
15602
0
  if (components.search_start != url_components::omitted) {
15603
0
    components.search_start -= 2;
15604
0
  }
15605
0
  if (components.hash_start != url_components::omitted) {
15606
0
    components.hash_start -= 2;
15607
0
  }
15608
0
  ADA_ASSERT_TRUE(validate());
15609
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15610
0
}
15611
15612
0
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15613
0
  ada_log("url_aggregator::consume_prepared_path ", input);
15614
  /***
15615
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15616
   * unfortunate. This particular function is nearly identical, except that it
15617
   * is a method on url_aggregator. The idea is that the trivial path (which is
15618
   * very common) merely appends to the buffer. This is the same trivial path as
15619
   * with helpers::parse_prepared_path, except that we have the additional check
15620
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15621
   * modify it, and then insert it back into the buffer.
15622
   */
15623
0
  uint8_t accumulator = checkers::path_signature(input);
15624
  // Let us first detect a trivial case.
15625
  // If it is special, we check that we have no dot, no %,  no \ and no
15626
  // character needing percent encoding. Otherwise, we check that we have no %,
15627
  // no dot, and no character needing percent encoding.
15628
0
  constexpr uint8_t need_encoding = 1;
15629
0
  constexpr uint8_t backslash_char = 2;
15630
0
  constexpr uint8_t dot_char = 4;
15631
0
  constexpr uint8_t percent_char = 8;
15632
0
  bool special = type != ada::scheme::NOT_SPECIAL;
15633
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15634
0
                                      checkers::is_windows_drive_letter(input));
15635
0
  bool trivial_path =
15636
0
      (special ? (accumulator == 0)
15637
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15638
0
                  0)) &&
15639
0
      (!may_need_slow_file_handling);
15640
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15641
    // '4' means that we have at least one dot, but nothing that requires
15642
    // percent encoding or decoding. The only part that is not trivial is
15643
    // that we may have single dots and double dots path segments.
15644
    // If we have such segments, then we either have a path that begins
15645
    // with '.' (easy to check), or we have the sequence './'.
15646
    // Note: input cannot be empty, it must at least contain one character ('.')
15647
    // Note: we know that '\' is not present.
15648
0
    if (input[0] != '.') {
15649
0
      size_t slashdot = 0;
15650
0
      bool dot_is_file = true;
15651
0
      for (;;) {
15652
0
        slashdot = input.find("/.", slashdot);
15653
0
        if (slashdot == std::string_view::npos) {  // common case
15654
0
          break;
15655
0
        } else {  // uncommon
15656
          // only three cases matter: /./, /.. or a final /
15657
0
          slashdot += 2;
15658
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15659
0
                           input[slashdot] == '/');
15660
0
        }
15661
0
      }
15662
0
      trivial_path = dot_is_file;
15663
0
    }
15664
0
  }
15665
0
  if (trivial_path && is_at_path()) {
15666
0
    ada_log("parse_path trivial");
15667
0
    buffer += '/';
15668
0
    buffer += input;
15669
0
    return;
15670
0
  }
15671
0
  std::string path = std::string(get_pathname());
15672
  // We are going to need to look a bit at the path, but let us see if we can
15673
  // ignore percent encoding *and* backslashes *and* percent characters.
15674
  // Except for the trivial case, this is likely to capture 99% of paths out
15675
  // there.
15676
0
  bool fast_path =
15677
0
      (special &&
15678
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15679
0
      (type != ada::scheme::type::FILE);
15680
0
  if (fast_path) {
15681
0
    ada_log("parse_prepared_path fast");
15682
    // Here we don't need to worry about \ or percent encoding.
15683
    // We also do not have a file protocol. We might have dots, however,
15684
    // but dots must as appear as '.', and they cannot be encoded because
15685
    // the symbol '%' is not present.
15686
0
    size_t previous_location = 0;  // We start at 0.
15687
0
    do {
15688
0
      size_t new_location = input.find('/', previous_location);
15689
      // std::string_view path_view = input;
15690
      //  We process the last segment separately:
15691
0
      if (new_location == std::string_view::npos) {
15692
0
        std::string_view path_view = input.substr(previous_location);
15693
0
        if (path_view == "..") {  // The path ends with ..
15694
          // e.g., if you receive ".." with an empty path, you go to "/".
15695
0
          if (path.empty()) {
15696
0
            path = '/';
15697
0
            update_base_pathname(path);
15698
0
            return;
15699
0
          }
15700
          // Fast case where we have nothing to do:
15701
0
          if (path.back() == '/') {
15702
0
            update_base_pathname(path);
15703
0
            return;
15704
0
          }
15705
          // If you have the path "/joe/myfriend",
15706
          // then you delete 'myfriend'.
15707
0
          path.resize(path.rfind('/') + 1);
15708
0
          update_base_pathname(path);
15709
0
          return;
15710
0
        }
15711
0
        path += '/';
15712
0
        if (path_view != ".") {
15713
0
          path.append(path_view);
15714
0
        }
15715
0
        update_base_pathname(path);
15716
0
        return;
15717
0
      } else {
15718
        // This is a non-final segment.
15719
0
        std::string_view path_view =
15720
0
            input.substr(previous_location, new_location - previous_location);
15721
0
        previous_location = new_location + 1;
15722
0
        if (path_view == "..") {
15723
0
          size_t last_delimiter = path.rfind('/');
15724
0
          if (last_delimiter != std::string::npos) {
15725
0
            path.erase(last_delimiter);
15726
0
          }
15727
0
        } else if (path_view != ".") {
15728
0
          path += '/';
15729
0
          path.append(path_view);
15730
0
        }
15731
0
      }
15732
0
    } while (true);
15733
0
  } else {
15734
0
    ada_log("parse_path slow");
15735
    // we have reached the general case
15736
0
    bool needs_percent_encoding = (accumulator & 1);
15737
0
    std::string path_buffer_tmp;
15738
0
    do {
15739
0
      size_t location = (special && (accumulator & 2))
15740
0
                            ? input.find_first_of("/\\")
15741
0
                            : input.find('/');
15742
0
      std::string_view path_view = input;
15743
0
      if (location != std::string_view::npos) {
15744
0
        path_view.remove_suffix(path_view.size() - location);
15745
0
        input.remove_prefix(location + 1);
15746
0
      }
15747
      // path_buffer is either path_view or it might point at a percent encoded
15748
      // temporary string.
15749
0
      std::string_view path_buffer =
15750
0
          (needs_percent_encoding &&
15751
0
           ada::unicode::percent_encode<false>(
15752
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15753
0
              ? path_buffer_tmp
15754
0
              : path_view;
15755
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15756
0
        helpers::shorten_path(path, type);
15757
0
        if (location == std::string_view::npos) {
15758
0
          path += '/';
15759
0
        }
15760
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15761
0
                 (location == std::string_view::npos)) {
15762
0
        path += '/';
15763
0
      }
15764
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15765
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15766
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15767
        // Windows drive letter, then replace the second code point in
15768
        // path_buffer with U+003A (:).
15769
0
        if (type == ada::scheme::type::FILE && path.empty() &&
15770
0
            checkers::is_windows_drive_letter(path_buffer)) {
15771
0
          path += '/';
15772
0
          path += path_buffer[0];
15773
0
          path += ':';
15774
0
          path_buffer.remove_prefix(2);
15775
0
          path.append(path_buffer);
15776
0
        } else {
15777
          // Append path_buffer to url's path.
15778
0
          path += '/';
15779
0
          path.append(path_buffer);
15780
0
        }
15781
0
      }
15782
0
      if (location == std::string_view::npos) {
15783
0
        update_base_pathname(path);
15784
0
        return;
15785
0
      }
15786
0
    } while (true);
15787
0
  }
15788
0
}
15789
}  // namespace ada
15790
/* end file src/url_aggregator.cpp */
15791
15792
#if ADA_INCLUDE_URL_PATTERN
15793
/* begin file src/url_pattern.cpp */
15794
#if ADA_INCLUDE_URL_PATTERN
15795
15796
15797
#include <algorithm>
15798
#include <optional>
15799
#include <string>
15800
15801
namespace ada {
15802
15803
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15804
    const url_pattern_init& init, url_pattern_init::process_type type,
15805
    std::optional<std::string_view> protocol,
15806
    std::optional<std::string_view> username,
15807
    std::optional<std::string_view> password,
15808
    std::optional<std::string_view> hostname,
15809
    std::optional<std::string_view> port,
15810
    std::optional<std::string_view> pathname,
15811
    std::optional<std::string_view> search,
15812
0
    std::optional<std::string_view> hash) {
15813
  // Let result be the result of creating a new URLPatternInit.
15814
0
  auto result = url_pattern_init{};
15815
15816
  // If protocol is not null, set result["protocol"] to protocol.
15817
0
  if (protocol.has_value()) result.protocol = *protocol;
15818
15819
  // If username is not null, set result["username"] to username.
15820
0
  if (username.has_value()) result.username = *username;
15821
15822
  // If password is not null, set result["password"] to password.
15823
0
  if (password.has_value()) result.password = *password;
15824
15825
  // If hostname is not null, set result["hostname"] to hostname.
15826
0
  if (hostname.has_value()) result.hostname = *hostname;
15827
15828
  // If port is not null, set result["port"] to port.
15829
0
  if (port.has_value()) result.port = *port;
15830
15831
  // If pathname is not null, set result["pathname"] to pathname.
15832
0
  if (pathname.has_value()) result.pathname = *pathname;
15833
15834
  // If search is not null, set result["search"] to search.
15835
0
  if (search.has_value()) result.search = *search;
15836
15837
  // If hash is not null, set result["hash"] to hash.
15838
0
  if (hash.has_value()) result.hash = *hash;
15839
15840
  // Let baseURL be null.
15841
0
  std::optional<url_aggregator> base_url{};
15842
15843
  // If init["baseURL"] exists:
15844
0
  if (init.base_url.has_value()) {
15845
    // Set baseURL to the result of parsing init["baseURL"].
15846
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15847
    // If baseURL is failure, then throw a TypeError.
15848
0
    if (!parsing_result) {
15849
0
      return tl::unexpected(errors::type_error);
15850
0
    }
15851
0
    base_url = std::move(*parsing_result);
15852
15853
    // If init["protocol"] does not exist, then set result["protocol"] to the
15854
    // result of processing a base URL string given baseURL's scheme and type.
15855
0
    if (!init.protocol.has_value()) {
15856
0
      ADA_ASSERT_TRUE(base_url.has_value());
15857
0
      std::string_view base_url_protocol = base_url->get_protocol();
15858
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15859
0
      result.protocol =
15860
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15861
0
    }
15862
15863
    // If type is not "pattern" and init contains none of "protocol",
15864
    // "hostname", "port" and "username", then set result["username"] to the
15865
    // result of processing a base URL string given baseURL's username and type.
15866
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15867
0
        !init.port && !init.username) {
15868
0
      result.username = url_pattern_helpers::process_base_url_string(
15869
0
          base_url->get_username(), type);
15870
0
    }
15871
15872
    // TODO: Optimization opportunity: Merge this with the previous check.
15873
    // If type is not "pattern" and init contains none of "protocol",
15874
    // "hostname", "port", "username" and "password", then set
15875
    // result["password"] to the result of processing a base URL string given
15876
    // baseURL's password and type.
15877
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15878
0
        !init.port && !init.username && !init.password) {
15879
0
      result.password = url_pattern_helpers::process_base_url_string(
15880
0
          base_url->get_password(), type);
15881
0
    }
15882
15883
    // If init contains neither "protocol" nor "hostname", then:
15884
0
    if (!init.protocol && !init.hostname) {
15885
      // Let baseHost be baseURL's host.
15886
      // If baseHost is null, then set baseHost to the empty string.
15887
0
      auto base_host = base_url->get_hostname();
15888
      // Set result["hostname"] to the result of processing a base URL string
15889
      // given baseHost and type.
15890
0
      result.hostname =
15891
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15892
0
    }
15893
15894
    // If init contains none of "protocol", "hostname", and "port", then:
15895
0
    if (!init.protocol && !init.hostname && !init.port) {
15896
      // If baseURL's port is null, then set result["port"] to the empty string.
15897
      // Otherwise, set result["port"] to baseURL's port, serialized.
15898
0
      result.port = base_url->get_port();
15899
0
    }
15900
15901
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15902
    // then set result["pathname"] to the result of processing a base URL string
15903
    // given the result of URL path serializing baseURL and type.
15904
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15905
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15906
0
          base_url->get_pathname(), type);
15907
0
    }
15908
15909
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15910
    // "search", then:
15911
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15912
0
        !init.search) {
15913
      // Let baseQuery be baseURL's query.
15914
      // Set result["search"] to the result of processing a base URL string
15915
      // given baseQuery and type.
15916
0
      result.search = url_pattern_helpers::process_base_url_string(
15917
0
          base_url->get_search(), type);
15918
0
    }
15919
15920
    // If init contains none of "protocol", "hostname", "port", "pathname",
15921
    // "search", and "hash", then:
15922
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15923
0
        !init.search && !init.hash) {
15924
      // Let baseFragment be baseURL's fragment.
15925
      // Set result["hash"] to the result of processing a base URL string given
15926
      // baseFragment and type.
15927
0
      result.hash = url_pattern_helpers::process_base_url_string(
15928
0
          base_url->get_hash(), type);
15929
0
    }
15930
0
  }
15931
15932
  // If init["protocol"] exists, then set result["protocol"] to the result of
15933
  // process protocol for init given init["protocol"] and type.
15934
0
  if (init.protocol) {
15935
0
    auto process_result = process_protocol(*init.protocol, type);
15936
0
    if (!process_result) {
15937
0
      return tl::unexpected(process_result.error());
15938
0
    }
15939
0
    result.protocol = std::move(*process_result);
15940
0
  }
15941
15942
  // If init["username"] exists, then set result["username"] to the result of
15943
  // process username for init given init["username"] and type.
15944
0
  if (init.username.has_value()) {
15945
0
    auto process_result = process_username(*init.username, type);
15946
0
    if (!process_result) {
15947
0
      return tl::unexpected(process_result.error());
15948
0
    }
15949
0
    result.username = std::move(*process_result);
15950
0
  }
15951
15952
  // If init["password"] exists, then set result["password"] to the result of
15953
  // process password for init given init["password"] and type.
15954
0
  if (init.password.has_value()) {
15955
0
    auto process_result = process_password(*init.password, type);
15956
0
    if (!process_result) {
15957
0
      return tl::unexpected(process_result.error());
15958
0
    }
15959
0
    result.password = std::move(*process_result);
15960
0
  }
15961
15962
  // If init["hostname"] exists, then set result["hostname"] to the result of
15963
  // process hostname for init given init["hostname"] and type.
15964
0
  if (init.hostname.has_value()) {
15965
0
    auto process_result = process_hostname(*init.hostname, type);
15966
0
    if (!process_result) {
15967
0
      return tl::unexpected(process_result.error());
15968
0
    }
15969
0
    result.hostname = std::move(*process_result);
15970
0
  }
15971
15972
  // If init["port"] exists, then set result["port"] to the result of process
15973
  // port for init given init["port"], result["protocol"], and type.
15974
0
  if (init.port) {
15975
0
    auto process_result =
15976
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15977
0
    if (!process_result) {
15978
0
      return tl::unexpected(process_result.error());
15979
0
    }
15980
0
    result.port = std::move(*process_result);
15981
0
  }
15982
15983
  // If init["pathname"] exists:
15984
0
  if (init.pathname.has_value()) {
15985
    // Set result["pathname"] to init["pathname"].
15986
0
    result.pathname = init.pathname;
15987
15988
    // If the following are all true:
15989
    // - baseURL is not null;
15990
    // - baseURL has an opaque path; and
15991
    // - the result of running is an absolute pathname given result["pathname"]
15992
    // and type is false,
15993
0
    if (base_url && !base_url->has_opaque_path &&
15994
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15995
      // Let baseURLPath be the result of running process a base URL string
15996
      // given the result of URL path serializing baseURL and type.
15997
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15998
      // exist.
15999
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
16000
0
          base_url->get_pathname(), type);
16001
16002
      // Let slash index be the index of the last U+002F (/) code point found in
16003
      // baseURLPath, interpreted as a sequence of code points, or null if there
16004
      // are no instances of the code point.
16005
0
      auto slash_index = base_url_path.find_last_of('/');
16006
16007
      // If slash index is not null:
16008
0
      if (slash_index != std::string::npos) {
16009
        // Let new pathname be the code point substring from 0 to slash index +
16010
        // 1 within baseURLPath.
16011
0
        base_url_path.resize(slash_index + 1);
16012
        // Append result["pathname"] to the end of new pathname.
16013
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
16014
0
        base_url_path.append(std::move(*result.pathname));
16015
        // Set result["pathname"] to new pathname.
16016
0
        result.pathname = std::move(base_url_path);
16017
0
      }
16018
0
    }
16019
16020
    // Set result["pathname"] to the result of process pathname for init given
16021
    // result["pathname"], result["protocol"], and type.
16022
0
    auto pathname_processing_result =
16023
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
16024
0
    if (!pathname_processing_result) {
16025
0
      return tl::unexpected(pathname_processing_result.error());
16026
0
    }
16027
0
    result.pathname = std::move(*pathname_processing_result);
16028
0
  }
16029
16030
  // If init["search"] exists then set result["search"] to the result of process
16031
  // search for init given init["search"] and type.
16032
0
  if (init.search) {
16033
0
    auto process_result = process_search(*init.search, type);
16034
0
    if (!process_result) {
16035
0
      return tl::unexpected(process_result.error());
16036
0
    }
16037
0
    result.search = std::move(*process_result);
16038
0
  }
16039
16040
  // If init["hash"] exists then set result["hash"] to the result of process
16041
  // hash for init given init["hash"] and type.
16042
0
  if (init.hash) {
16043
0
    auto process_result = process_hash(*init.hash, type);
16044
0
    if (!process_result) {
16045
0
      return tl::unexpected(process_result.error());
16046
0
    }
16047
0
    result.hash = std::move(*process_result);
16048
0
  }
16049
  // Return result.
16050
0
  return result;
16051
0
}
16052
16053
tl::expected<std::string, errors> url_pattern_init::process_protocol(
16054
0
    std::string_view value, process_type type) {
16055
0
  ada_log("process_protocol=", value, " [", type, "]");
16056
  // Let strippedValue be the given value with a single trailing U+003A (:)
16057
  // removed, if any.
16058
0
  if (value.ends_with(":")) {
16059
0
    value.remove_suffix(1);
16060
0
  }
16061
  // If type is "pattern" then return strippedValue.
16062
0
  if (type == process_type::pattern) {
16063
0
    return std::string(value);
16064
0
  }
16065
  // Return the result of running canonicalize a protocol given strippedValue.
16066
0
  return url_pattern_helpers::canonicalize_protocol(value);
16067
0
}
16068
16069
tl::expected<std::string, errors> url_pattern_init::process_username(
16070
0
    std::string_view value, process_type type) {
16071
  // If type is "pattern" then return value.
16072
0
  if (type == process_type::pattern) {
16073
0
    return std::string(value);
16074
0
  }
16075
  // Return the result of running canonicalize a username given value.
16076
0
  return url_pattern_helpers::canonicalize_username(value);
16077
0
}
16078
16079
tl::expected<std::string, errors> url_pattern_init::process_password(
16080
0
    std::string_view value, process_type type) {
16081
  // If type is "pattern" then return value.
16082
0
  if (type == process_type::pattern) {
16083
0
    return std::string(value);
16084
0
  }
16085
  // Return the result of running canonicalize a password given value.
16086
0
  return url_pattern_helpers::canonicalize_password(value);
16087
0
}
16088
16089
tl::expected<std::string, errors> url_pattern_init::process_hostname(
16090
0
    std::string_view value, process_type type) {
16091
0
  ada_log("process_hostname value=", value, " type=", type);
16092
  // If type is "pattern" then return value.
16093
0
  if (type == process_type::pattern) {
16094
0
    return std::string(value);
16095
0
  }
16096
  // Return the result of running canonicalize a hostname given value.
16097
0
  return url_pattern_helpers::canonicalize_hostname(value);
16098
0
}
16099
16100
tl::expected<std::string, errors> url_pattern_init::process_port(
16101
0
    std::string_view port, std::string_view protocol, process_type type) {
16102
  // If type is "pattern" then return portValue.
16103
0
  if (type == process_type::pattern) {
16104
0
    return std::string(port);
16105
0
  }
16106
  // Return the result of running canonicalize a port given portValue and
16107
  // protocolValue.
16108
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
16109
0
}
16110
16111
tl::expected<std::string, errors> url_pattern_init::process_pathname(
16112
0
    std::string_view value, std::string_view protocol, process_type type) {
16113
  // If type is "pattern" then return pathnameValue.
16114
0
  if (type == process_type::pattern) {
16115
0
    return std::string(value);
16116
0
  }
16117
16118
  // If protocolValue is a special scheme or the empty string, then return the
16119
  // result of running canonicalize a pathname given pathnameValue.
16120
0
  if (protocol.empty() || scheme::is_special(protocol)) {
16121
0
    return url_pattern_helpers::canonicalize_pathname(value);
16122
0
  }
16123
16124
  // Return the result of running canonicalize an opaque pathname given
16125
  // pathnameValue.
16126
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
16127
0
}
16128
16129
tl::expected<std::string, errors> url_pattern_init::process_search(
16130
0
    std::string_view value, process_type type) {
16131
  // Let strippedValue be the given value with a single leading U+003F (?)
16132
  // removed, if any.
16133
0
  if (value.starts_with("?")) {
16134
0
    value.remove_prefix(1);
16135
0
  }
16136
  // We cannot assert that the value is no longer starting with a single
16137
  // question mark because technically it can start. The question is whether or
16138
  // not we should remove the first question mark. Ref:
16139
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
16140
16141
  // If type is "pattern" then return strippedValue.
16142
0
  if (type == process_type::pattern) {
16143
0
    return std::string(value);
16144
0
  }
16145
  // Return the result of running canonicalize a search given strippedValue.
16146
0
  return url_pattern_helpers::canonicalize_search(value);
16147
0
}
16148
16149
tl::expected<std::string, errors> url_pattern_init::process_hash(
16150
0
    std::string_view value, process_type type) {
16151
  // Let strippedValue be the given value with a single leading U+0023 (#)
16152
  // removed, if any.
16153
0
  if (value.starts_with("#")) {
16154
0
    value.remove_prefix(1);
16155
0
  }
16156
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16157
  // If type is "pattern" then return strippedValue.
16158
0
  if (type == process_type::pattern) {
16159
0
    return std::string(value);
16160
0
  }
16161
  // Return the result of running canonicalize a hash given strippedValue.
16162
0
  return url_pattern_helpers::canonicalize_hash(value);
16163
0
}
16164
16165
}  // namespace ada
16166
16167
#endif  // ADA_INCLUDE_URL_PATTERN
16168
/* end file src/url_pattern.cpp */
16169
/* begin file src/url_pattern_helpers.cpp */
16170
#if ADA_INCLUDE_URL_PATTERN
16171
16172
#include <algorithm>
16173
#include <array>
16174
#include <charconv>
16175
#include <optional>
16176
#include <ranges>
16177
#include <string>
16178
16179
16180
namespace ada::url_pattern_helpers {
16181
16182
std::tuple<std::string, std::vector<std::string>>
16183
generate_regular_expression_and_name_list(
16184
    const std::vector<url_pattern_part>& part_list,
16185
0
    url_pattern_compile_component_options options) {
16186
  // Let result be "^"
16187
0
  std::string result = "^";
16188
  // Reserve capacity to reduce reallocations
16189
0
  result.reserve(part_list.size() * 16);
16190
16191
  // Let name list be a new list
16192
0
  std::vector<std::string> name_list{};
16193
0
  name_list.reserve(part_list.size());
16194
16195
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16196
0
  std::string segment_wildcard_regexp;
16197
16198
  // For each part of part list:
16199
0
  for (const url_pattern_part& part : part_list) {
16200
    // If part's type is "fixed-text":
16201
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16202
      // If part's modifier is "none"
16203
0
      if (part.modifier == url_pattern_part_modifier::none) {
16204
0
        result.append(escape_regexp_string(part.value));
16205
0
      } else {
16206
        // (?:<fixed text>)<modifier>
16207
0
        result.append("(?:");
16208
0
        result.append(escape_regexp_string(part.value));
16209
0
        result.push_back(')');
16210
0
        result.append(convert_modifier_to_string(part.modifier));
16211
0
      }
16212
0
      continue;
16213
0
    }
16214
16215
    // Assert: part's name is not the empty string
16216
0
    ADA_ASSERT_TRUE(!part.name.empty());
16217
0
    name_list.push_back(part.name);
16218
16219
    // Use string_view to avoid copies where possible
16220
0
    std::string_view regexp_value = part.value;
16221
16222
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16223
      // Lazy generate segment wildcard regexp
16224
0
      if (segment_wildcard_regexp.empty()) {
16225
0
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16226
0
      }
16227
0
      regexp_value = segment_wildcard_regexp;
16228
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16229
0
      regexp_value = ".*";
16230
0
    }
16231
16232
    // If part's prefix is the empty string and part's suffix is the empty
16233
    // string
16234
0
    if (part.prefix.empty() && part.suffix.empty()) {
16235
      // If part's modifier is "none" or "optional"
16236
0
      if (part.modifier == url_pattern_part_modifier::none ||
16237
0
          part.modifier == url_pattern_part_modifier::optional) {
16238
        // (<regexp value>)<modifier>
16239
0
        result.push_back('(');
16240
0
        result.append(regexp_value);
16241
0
        result.push_back(')');
16242
0
        result.append(convert_modifier_to_string(part.modifier));
16243
0
      } else {
16244
        // ((?:<regexp value>)<modifier>)
16245
0
        result.append("((?:");
16246
0
        result.append(regexp_value);
16247
0
        result.push_back(')');
16248
0
        result.append(convert_modifier_to_string(part.modifier));
16249
0
        result.push_back(')');
16250
0
      }
16251
0
      continue;
16252
0
    }
16253
16254
    // If part's modifier is "none" or "optional"
16255
0
    if (part.modifier == url_pattern_part_modifier::none ||
16256
0
        part.modifier == url_pattern_part_modifier::optional) {
16257
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16258
0
      result.append("(?:");
16259
0
      result.append(escape_regexp_string(part.prefix));
16260
0
      result.push_back('(');
16261
0
      result.append(regexp_value);
16262
0
      result.push_back(')');
16263
0
      result.append(escape_regexp_string(part.suffix));
16264
0
      result.push_back(')');
16265
0
      result.append(convert_modifier_to_string(part.modifier));
16266
0
      continue;
16267
0
    }
16268
16269
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16270
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16271
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
16272
16273
    // Assert: part's prefix is not the empty string or part's suffix is not the
16274
    // empty string
16275
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16276
16277
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16278
    // value>))*)<suffix>)?
16279
    // Append "(?:" to the end of result.
16280
0
    result.append("(?:");
16281
    // Append the result of running escape a regexp string given part's prefix
16282
    // to the end of result.
16283
0
    result.append(escape_regexp_string(part.prefix));
16284
    // Append "((?:" to the end of result.
16285
0
    result.append("((?:");
16286
    // Append regexp value to the end of result.
16287
0
    result.append(regexp_value);
16288
    // Append ")(?:" to the end of result.
16289
0
    result.append(")(?:");
16290
    // Append the result of running escape a regexp string given part's suffix
16291
    // to the end of result.
16292
0
    result.append(escape_regexp_string(part.suffix));
16293
    // Append the result of running escape a regexp string given part's prefix
16294
    // to the end of result.
16295
0
    result.append(escape_regexp_string(part.prefix));
16296
    // Append "(?:" to the end of result.
16297
0
    result.append("(?:");
16298
    // Append regexp value to the end of result.
16299
0
    result.append(regexp_value);
16300
    // Append "))*)" to the end of result.
16301
0
    result.append("))*)");
16302
    // Append the result of running escape a regexp string given part's suffix
16303
    // to the end of result.
16304
0
    result.append(escape_regexp_string(part.suffix));
16305
    // Append ")" to the end of result.
16306
0
    result.append(")");
16307
16308
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16309
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16310
0
      result += "?";
16311
0
    }
16312
0
  }
16313
16314
  // Append "$" to the end of result
16315
0
  result += "$";
16316
16317
  // Return (result, name list)
16318
0
  return {std::move(result), std::move(name_list)};
16319
0
}
16320
16321
0
bool is_ipv6_address(std::string_view input) noexcept {
16322
  // If input's code point length is less than 2, then return false.
16323
0
  if (input.size() < 2) return false;
16324
16325
  // Let input code points be input interpreted as a list of code points.
16326
  // If input code points[0] is U+005B ([), then return true.
16327
0
  if (input.front() == '[') return true;
16328
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16329
  // ([), then return true.
16330
0
  if (input.starts_with("{[")) return true;
16331
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16332
  // ([), then return true.
16333
0
  return input.starts_with("\\[");
16334
0
}
16335
16336
std::string_view convert_modifier_to_string(
16337
0
    url_pattern_part_modifier modifier) {
16338
0
  switch (modifier) {
16339
      // If modifier is "zero-or-more", then return "*".
16340
0
    case url_pattern_part_modifier::zero_or_more:
16341
0
      return "*";
16342
    // If modifier is "optional", then return "?".
16343
0
    case url_pattern_part_modifier::optional:
16344
0
      return "?";
16345
    // If modifier is "one-or-more", then return "+".
16346
0
    case url_pattern_part_modifier::one_or_more:
16347
0
      return "+";
16348
    // Return the empty string.
16349
0
    default:
16350
0
      return "";
16351
0
  }
16352
0
}
16353
16354
std::string generate_segment_wildcard_regexp(
16355
0
    url_pattern_compile_component_options options) {
16356
  // Let result be "[^".
16357
0
  std::string result = "[^";
16358
  // Append the result of running escape a regexp string given options's
16359
  // delimiter code point to the end of result.
16360
0
  result.append(escape_regexp_string(options.get_delimiter()));
16361
  // Append "]+?" to the end of result.
16362
0
  result.append("]+?");
16363
  // Return result.
16364
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16365
0
  return result;
16366
0
}
16367
16368
namespace {
16369
// Unified lookup table for URL pattern character classification
16370
// Bit flags for different character types
16371
constexpr uint8_t CHAR_SCHEME = 1;  // valid in scheme (a-z, A-Z, 0-9, +, -, .)
16372
constexpr uint8_t CHAR_UPPER = 2;   // uppercase letter (needs lowercasing)
16373
constexpr uint8_t CHAR_SIMPLE_HOSTNAME = 4;  // simple hostname (a-z, 0-9, -, .)
16374
constexpr uint8_t CHAR_SIMPLE_PATHNAME =
16375
    8;  // simple pathname (a-z, A-Z, 0-9, /, -, _, ~)
16376
16377
constexpr std::array<uint8_t, 256> char_class_table = []() consteval {
16378
  std::array<uint8_t, 256> table{};
16379
  for (int c = 'a'; c <= 'z'; c++)
16380
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16381
  for (int c = 'A'; c <= 'Z'; c++)
16382
    table[c] = CHAR_SCHEME | CHAR_UPPER | CHAR_SIMPLE_PATHNAME;
16383
  for (int c = '0'; c <= '9'; c++)
16384
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16385
  table['+'] = CHAR_SCHEME;
16386
  table['-'] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16387
  table['.'] =
16388
      CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME;  // not pathname (needs normalization)
16389
  table['/'] = CHAR_SIMPLE_PATHNAME;
16390
  table['_'] = CHAR_SIMPLE_PATHNAME;
16391
  table['~'] = CHAR_SIMPLE_PATHNAME;
16392
  return table;
16393
}();
16394
}  // namespace
16395
16396
tl::expected<std::string, errors> canonicalize_protocol(
16397
0
    std::string_view input) {
16398
0
  ada_log("canonicalize_protocol called with input=", input);
16399
0
  if (input.empty()) [[unlikely]] {
16400
0
    return "";
16401
0
  }
16402
16403
0
  if (input.ends_with(":")) {
16404
0
    input.remove_suffix(1);
16405
0
  }
16406
16407
  // Fast path: special schemes are already canonical
16408
0
  if (scheme::is_special(input)) {
16409
0
    return std::string(input);
16410
0
  }
16411
16412
  // Fast path: validate scheme chars and check for uppercase
16413
  // First char must be alpha (not +, -, ., or digit)
16414
0
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16415
0
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16416
0
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16417
0
    return tl::unexpected(errors::type_error);
16418
0
  }
16419
16420
0
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16421
0
  for (size_t i = 1; i < input.size(); i++) {
16422
0
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16423
0
    if (!(flags & CHAR_SCHEME)) {
16424
0
      return tl::unexpected(errors::type_error);
16425
0
    }
16426
0
    needs_lowercase |= flags & CHAR_UPPER;
16427
0
  }
16428
16429
0
  if (needs_lowercase == 0) {
16430
0
    return std::string(input);
16431
0
  }
16432
16433
0
  std::string result(input);
16434
0
  unicode::to_lower_ascii(result.data(), result.size());
16435
0
  return result;
16436
0
}
16437
16438
tl::expected<std::string, errors> canonicalize_username(
16439
0
    std::string_view input) {
16440
  // If value is the empty string, return value.
16441
0
  if (input.empty()) [[unlikely]] {
16442
0
    return "";
16443
0
  }
16444
  // Percent-encode the input using the userinfo percent-encode set.
16445
0
  size_t idx = ada::unicode::percent_encode_index(
16446
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16447
0
  if (idx == input.size()) {
16448
    // No encoding needed, return input as-is
16449
0
    return std::string(input);
16450
0
  }
16451
  // Percent-encode from the first character that needs encoding
16452
0
  return ada::unicode::percent_encode(
16453
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16454
0
}
16455
16456
tl::expected<std::string, errors> canonicalize_password(
16457
0
    std::string_view input) {
16458
  // If value is the empty string, return value.
16459
0
  if (input.empty()) [[unlikely]] {
16460
0
    return "";
16461
0
  }
16462
  // Percent-encode the input using the userinfo percent-encode set.
16463
0
  size_t idx = ada::unicode::percent_encode_index(
16464
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
16465
0
  if (idx == input.size()) {
16466
    // No encoding needed, return input as-is
16467
0
    return std::string(input);
16468
0
  }
16469
  // Percent-encode from the first character that needs encoding
16470
0
  return ada::unicode::percent_encode(
16471
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16472
0
}
16473
16474
tl::expected<std::string, errors> canonicalize_hostname(
16475
0
    std::string_view input) {
16476
0
  ada_log("canonicalize_hostname input=", input);
16477
0
  if (input.empty()) [[unlikely]] {
16478
0
    return "";
16479
0
  }
16480
16481
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA
16482
0
  bool needs_processing = false;
16483
0
  for (char c : input) {
16484
0
    needs_processing |=
16485
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
16486
0
  }
16487
0
  if (!needs_processing) {
16488
0
    return std::string(input);
16489
0
  }
16490
16491
  // Let dummyURL be a new URL record.
16492
  // Let parseResult be the result of running the basic URL parser given value
16493
  // with dummyURL as url and hostname state as state override.
16494
16495
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16496
  // hostname will not be converted using IDNA.
16497
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16498
0
  ADA_ASSERT_TRUE(url);
16499
  // if (!isValidHostnameInput(hostname)) return kj::none;
16500
0
  if (!url->set_hostname(input)) {
16501
    // If parseResult is failure, then throw a TypeError.
16502
0
    return tl::unexpected(errors::type_error);
16503
0
  }
16504
  // Return dummyURL's host, serialized, or empty string if it is null.
16505
0
  return std::string(url->get_hostname());
16506
0
}
16507
16508
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16509
0
    std::string_view input) {
16510
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16511
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16512
0
  if (std::ranges::any_of(input, [](char c) {
16513
0
        return c != '[' && c != ']' && c != ':' &&
16514
0
               !unicode::is_ascii_hex_digit(c);
16515
0
      })) {
16516
0
    return tl::unexpected(errors::type_error);
16517
0
  }
16518
  // Append the result of running ASCII lowercase given code point to the end of
16519
  // result.
16520
0
  auto hostname = std::string(input);
16521
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16522
0
  return hostname;
16523
0
}
16524
16525
tl::expected<std::string, errors> canonicalize_port(
16526
0
    std::string_view port_value) {
16527
  // If portValue is the empty string, return portValue.
16528
0
  if (port_value.empty()) [[unlikely]] {
16529
0
    return "";
16530
0
  }
16531
16532
  // Remove ASCII tab or newline characters
16533
0
  std::string trimmed(port_value);
16534
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16535
16536
0
  if (trimmed.empty()) {
16537
0
    return "";
16538
0
  }
16539
16540
  // Input should start with a digit character
16541
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16542
0
    return tl::unexpected(errors::type_error);
16543
0
  }
16544
16545
  // Find the first non-digit character
16546
0
  auto first_non_digit =
16547
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16548
0
  std::string_view digits_to_parse =
16549
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16550
16551
  // Here we have that a range of ASCII digit characters identified
16552
  // by digits_to_parse. It is none empty.
16553
  // We want to determine whether it is a valid port number (0-65535).
16554
  // Clearly, if the length is greater than 5, it is invalid.
16555
  // If the length is 5, we need to compare lexicographically to "65535".
16556
  // Otherwise it is valid.
16557
0
  if (digits_to_parse.size() == 5) {
16558
0
    if (digits_to_parse > "65535") {
16559
0
      return tl::unexpected(errors::type_error);
16560
0
    }
16561
0
  } else if (digits_to_parse.size() > 5) {
16562
0
    return tl::unexpected(errors::type_error);
16563
0
  }
16564
0
  if (digits_to_parse[0] == '0' && digits_to_parse.size() > 1) {
16565
    // Leading zeros are not allowed for multi-digit ports
16566
0
    return tl::unexpected(errors::type_error);
16567
0
  }
16568
  // It is valid! Most times, we do not need to parse it into an integer.
16569
0
  return std::string(digits_to_parse);
16570
0
}
16571
16572
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16573
0
    std::string_view port_value, std::string_view protocol) {
16574
  // If portValue is the empty string, return portValue.
16575
0
  if (port_value.empty()) [[unlikely]] {
16576
0
    return "";
16577
0
  }
16578
16579
  // Handle empty or trailing colon in protocol
16580
0
  if (protocol.empty()) {
16581
0
    protocol = "fake";
16582
0
  } else if (protocol.ends_with(":")) {
16583
0
    protocol.remove_suffix(1);
16584
0
  }
16585
16586
  // Remove ASCII tab or newline characters
16587
0
  std::string trimmed(port_value);
16588
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16589
16590
0
  if (trimmed.empty()) {
16591
0
    return "";
16592
0
  }
16593
16594
  // Input should start with a digit character
16595
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16596
0
    return tl::unexpected(errors::type_error);
16597
0
  }
16598
16599
  // Find the first non-digit character
16600
0
  auto first_non_digit =
16601
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16602
0
  std::string_view digits_to_parse =
16603
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16604
16605
  // Parse the port number
16606
0
  uint16_t parsed_port{};
16607
0
  auto result = std::from_chars(digits_to_parse.data(),
16608
0
                                digits_to_parse.data() + digits_to_parse.size(),
16609
0
                                parsed_port);
16610
16611
0
  if (result.ec == std::errc::result_out_of_range) {
16612
0
    return tl::unexpected(errors::type_error);
16613
0
  }
16614
16615
0
  if (result.ec == std::errc()) {
16616
    // Check if this is the default port for the scheme
16617
0
    uint16_t default_port = scheme::get_special_port(protocol);
16618
16619
    // If it's the default port for a special scheme, return empty string
16620
0
    if (default_port != 0 && default_port == parsed_port) {
16621
0
      return "";
16622
0
    }
16623
16624
    // Successfully parsed, return as string
16625
0
    return std::to_string(parsed_port);
16626
0
  }
16627
16628
0
  return tl::unexpected(errors::type_error);
16629
0
}
16630
16631
tl::expected<std::string, errors> canonicalize_pathname(
16632
0
    std::string_view input) {
16633
0
  if (input.empty()) [[unlikely]] {
16634
0
    return "";
16635
0
  }
16636
16637
  // Fast path: simple pathnames (no . which needs normalization) can be
16638
  // returned as-is
16639
0
  bool needs_processing = false;
16640
0
  for (char c : input) {
16641
0
    needs_processing |=
16642
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
16643
0
  }
16644
0
  if (!needs_processing) {
16645
0
    return std::string(input);
16646
0
  }
16647
16648
  // Let leading slash be true if the first code point in value is U+002F (/)
16649
  // and otherwise false.
16650
0
  const bool leading_slash = input.starts_with("/");
16651
  // Let modified value be "/-" if leading slash is false and otherwise the
16652
  // empty string.
16653
0
  const auto modified_value = leading_slash ? "" : "/-";
16654
0
  const auto full_url =
16655
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16656
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16657
0
    const auto pathname = url->get_pathname();
16658
    // If leading slash is false, then set result to the code point substring
16659
    // from 2 to the end of the string within result.
16660
0
    return leading_slash ? std::string(pathname)
16661
0
                         : std::string(pathname.substr(2));
16662
0
  }
16663
  // If parseResult is failure, then throw a TypeError.
16664
0
  return tl::unexpected(errors::type_error);
16665
0
}
16666
16667
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16668
0
    std::string_view input) {
16669
  // If value is the empty string, return value.
16670
0
  if (input.empty()) [[unlikely]] {
16671
0
    return "";
16672
0
  }
16673
  // Let dummyURL be a new URL record.
16674
  // Set dummyURL's path to the empty string.
16675
  // Let parseResult be the result of running URL parsing given value with
16676
  // dummyURL as url and opaque path state as state override.
16677
0
  if (auto url =
16678
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16679
    // Return the result of URL path serializing dummyURL.
16680
0
    return std::string(url->get_pathname());
16681
0
  }
16682
  // If parseResult is failure, then throw a TypeError.
16683
0
  return tl::unexpected(errors::type_error);
16684
0
}
16685
16686
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16687
  // If value is the empty string, return value.
16688
0
  if (input.empty()) [[unlikely]] {
16689
0
    return "";
16690
0
  }
16691
  // Remove leading '?' if present
16692
0
  std::string new_value;
16693
0
  new_value = input[0] == '?' ? input.substr(1) : input;
16694
  // Remove ASCII tab or newline characters
16695
0
  helpers::remove_ascii_tab_or_newline(new_value);
16696
16697
0
  if (new_value.empty()) {
16698
0
    return "";
16699
0
  }
16700
16701
  // Percent-encode using QUERY_PERCENT_ENCODE (for non-special URLs)
16702
  // Note: "fake://dummy.test" is not a special URL, so we use
16703
  // QUERY_PERCENT_ENCODE
16704
0
  size_t idx = ada::unicode::percent_encode_index(
16705
0
      new_value, character_sets::QUERY_PERCENT_ENCODE);
16706
0
  if (idx == new_value.size()) {
16707
    // No encoding needed
16708
0
    return new_value;
16709
0
  }
16710
  // Percent-encode from the first character that needs encoding
16711
0
  return ada::unicode::percent_encode(
16712
0
      new_value, character_sets::QUERY_PERCENT_ENCODE, idx);
16713
0
}
16714
16715
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16716
  // If value is the empty string, return value.
16717
0
  if (input.empty()) [[unlikely]] {
16718
0
    return "";
16719
0
  }
16720
  // Remove leading '#' if present
16721
0
  std::string new_value;
16722
0
  new_value = input[0] == '#' ? input.substr(1) : input;
16723
  // Remove ASCII tab or newline characters
16724
0
  helpers::remove_ascii_tab_or_newline(new_value);
16725
16726
0
  if (new_value.empty()) {
16727
0
    return "";
16728
0
  }
16729
16730
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
16731
0
  size_t idx = ada::unicode::percent_encode_index(
16732
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
16733
0
  if (idx == new_value.size()) {
16734
    // No encoding needed
16735
0
    return new_value;
16736
0
  }
16737
  // Percent-encode from the first character that needs encoding
16738
0
  return ada::unicode::percent_encode(
16739
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
16740
0
}
16741
16742
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16743
0
                                                  token_policy policy) {
16744
0
  ada_log("tokenize input: ", input);
16745
  // Let tokenizer be a new tokenizer.
16746
  // Set tokenizer's input to input.
16747
  // Set tokenizer's policy to policy.
16748
0
  auto tokenizer = Tokenizer(input, policy);
16749
  // While tokenizer's index is less than tokenizer's input's code point length:
16750
0
  while (tokenizer.index < tokenizer.input.size()) {
16751
    // Run seek and get the next code point given tokenizer and tokenizer's
16752
    // index.
16753
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16754
16755
    // If tokenizer's code point is U+002A (*):
16756
0
    if (tokenizer.code_point == '*') {
16757
      // Run add a token with default position and length given tokenizer and
16758
      // "asterisk".
16759
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16760
0
      ada_log("add ASTERISK token");
16761
      // Continue.
16762
0
      continue;
16763
0
    }
16764
16765
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16766
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16767
      // Run add a token with default position and length given tokenizer and
16768
      // "other-modifier".
16769
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16770
      // Continue.
16771
0
      continue;
16772
0
    }
16773
16774
    // If tokenizer's code point is U+005C (\):
16775
0
    if (tokenizer.code_point == '\\') {
16776
      // If tokenizer's index is equal to tokenizer's input's code point length
16777
      // - 1:
16778
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16779
        // Run process a tokenizing error given tokenizer, tokenizer's next
16780
        // index, and tokenizer's index.
16781
0
        if (auto error = tokenizer.process_tokenizing_error(
16782
0
                tokenizer.next_index, tokenizer.index)) {
16783
0
          ada_log("process_tokenizing_error failed");
16784
0
          return tl::unexpected(*error);
16785
0
        }
16786
0
        continue;
16787
0
      }
16788
16789
      // Let escaped index be tokenizer's next index.
16790
0
      auto escaped_index = tokenizer.next_index;
16791
      // Run get the next code point given tokenizer.
16792
0
      tokenizer.get_next_code_point();
16793
      // Run add a token with default length given tokenizer, "escaped-char",
16794
      // tokenizer's next index, and escaped index.
16795
0
      tokenizer.add_token_with_default_length(
16796
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16797
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16798
0
              " with escaped index ", escaped_index);
16799
      // Continue.
16800
0
      continue;
16801
0
    }
16802
16803
    // If tokenizer's code point is U+007B ({):
16804
0
    if (tokenizer.code_point == '{') {
16805
      // Run add a token with default position and length given tokenizer and
16806
      // "open".
16807
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16808
0
      ada_log("add OPEN token");
16809
0
      continue;
16810
0
    }
16811
16812
    // If tokenizer's code point is U+007D (}):
16813
0
    if (tokenizer.code_point == '}') {
16814
      // Run add a token with default position and length given tokenizer and
16815
      // "close".
16816
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16817
0
      ada_log("add CLOSE token");
16818
0
      continue;
16819
0
    }
16820
16821
    // If tokenizer's code point is U+003A (:):
16822
0
    if (tokenizer.code_point == ':') {
16823
      // Let name position be tokenizer's next index.
16824
0
      auto name_position = tokenizer.next_index;
16825
      // Let name start be name position.
16826
0
      auto name_start = name_position;
16827
      // While name position is less than tokenizer's input's code point length:
16828
0
      while (name_position < tokenizer.input.size()) {
16829
        // Run seek and get the next code point given tokenizer and name
16830
        // position.
16831
0
        tokenizer.seek_and_get_next_code_point(name_position);
16832
        // Let first code point be true if name position equals name start and
16833
        // false otherwise.
16834
0
        bool first_code_point = name_position == name_start;
16835
        // Let valid code point be the result of running is a valid name code
16836
        // point given tokenizer's code point and first code point.
16837
0
        auto valid_code_point =
16838
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16839
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16840
0
                " first_code_point=", first_code_point,
16841
0
                " valid_code_point=", valid_code_point);
16842
        // If valid code point is false break.
16843
0
        if (!valid_code_point) break;
16844
        // Set name position to tokenizer's next index.
16845
0
        name_position = tokenizer.next_index;
16846
0
      }
16847
16848
      // If name position is less than or equal to name start:
16849
0
      if (name_position <= name_start) {
16850
        // Run process a tokenizing error given tokenizer, name start, and
16851
        // tokenizer's index.
16852
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16853
0
                                                            tokenizer.index)) {
16854
0
          ada_log("process_tokenizing_error failed");
16855
0
          return tl::unexpected(*error);
16856
0
        }
16857
        // Continue
16858
0
        continue;
16859
0
      }
16860
16861
      // Run add a token with default length given tokenizer, "name", name
16862
      // position, and name start.
16863
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16864
0
                                              name_start);
16865
0
      continue;
16866
0
    }
16867
16868
    // If tokenizer's code point is U+0028 (():
16869
0
    if (tokenizer.code_point == '(') {
16870
      // Let depth be 1.
16871
0
      size_t depth = 1;
16872
      // Let regexp position be tokenizer's next index.
16873
0
      auto regexp_position = tokenizer.next_index;
16874
      // Let regexp start be regexp position.
16875
0
      auto regexp_start = regexp_position;
16876
      // Let error be false.
16877
0
      bool error = false;
16878
16879
      // While regexp position is less than tokenizer's input's code point
16880
      // length:
16881
0
      while (regexp_position < tokenizer.input.size()) {
16882
        // Run seek and get the next code point given tokenizer and regexp
16883
        // position.
16884
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16885
16886
        // TODO: Optimization opportunity: The next 2 if statements can be
16887
        // merged. If the result of running is ASCII given tokenizer's code
16888
        // point is false:
16889
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16890
          // Run process a tokenizing error given tokenizer, regexp start, and
16891
          // tokenizer's index.
16892
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16893
0
                  regexp_start, tokenizer.index)) {
16894
0
            return tl::unexpected(*process_error);
16895
0
          }
16896
          // Set error to true.
16897
0
          error = true;
16898
0
          break;
16899
0
        }
16900
16901
        // If regexp position equals regexp start and tokenizer's code point is
16902
        // U+003F (?):
16903
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16904
          // Run process a tokenizing error given tokenizer, regexp start, and
16905
          // tokenizer's index.
16906
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16907
0
                  regexp_start, tokenizer.index)) {
16908
0
            return tl::unexpected(*process_error);
16909
0
          }
16910
          // Set error to true;
16911
0
          error = true;
16912
0
          break;
16913
0
        }
16914
16915
        // If tokenizer's code point is U+005C (\):
16916
0
        if (tokenizer.code_point == '\\') {
16917
          // If regexp position equals tokenizer's input's code point length - 1
16918
0
          if (regexp_position == tokenizer.input.size() - 1) {
16919
            // Run process a tokenizing error given tokenizer, regexp start, and
16920
            // tokenizer's index.
16921
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16922
0
                    regexp_start, tokenizer.index)) {
16923
0
              return tl::unexpected(*process_error);
16924
0
            }
16925
            // Set error to true.
16926
0
            error = true;
16927
0
            break;
16928
0
          }
16929
          // Run get the next code point given tokenizer.
16930
0
          tokenizer.get_next_code_point();
16931
          // If the result of running is ASCII given tokenizer's code point is
16932
          // false:
16933
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16934
            // Run process a tokenizing error given tokenizer, regexp start, and
16935
            // tokenizer's index.
16936
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16937
0
                    regexp_start, tokenizer.index);
16938
0
                process_error.has_value()) {
16939
0
              return tl::unexpected(*process_error);
16940
0
            }
16941
            // Set error to true.
16942
0
            error = true;
16943
0
            break;
16944
0
          }
16945
          // Set regexp position to tokenizer's next index.
16946
0
          regexp_position = tokenizer.next_index;
16947
0
          continue;
16948
0
        }
16949
16950
        // If tokenizer's code point is U+0029 ()):
16951
0
        if (tokenizer.code_point == ')') {
16952
          // Decrement depth by 1.
16953
0
          depth--;
16954
          // If depth is 0:
16955
0
          if (depth == 0) {
16956
            // Set regexp position to tokenizer's next index.
16957
0
            regexp_position = tokenizer.next_index;
16958
            // Break.
16959
0
            break;
16960
0
          }
16961
0
        } else if (tokenizer.code_point == '(') {
16962
          // Otherwise if tokenizer's code point is U+0028 (():
16963
          // Increment depth by 1.
16964
0
          depth++;
16965
          // If regexp position equals tokenizer's input's code point length -
16966
          // 1:
16967
0
          if (regexp_position == tokenizer.input.size() - 1) {
16968
            // Run process a tokenizing error given tokenizer, regexp start, and
16969
            // tokenizer's index.
16970
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16971
0
                    regexp_start, tokenizer.index)) {
16972
0
              return tl::unexpected(*process_error);
16973
0
            }
16974
            // Set error to true.
16975
0
            error = true;
16976
0
            break;
16977
0
          }
16978
          // Let temporary position be tokenizer's next index.
16979
0
          auto temporary_position = tokenizer.next_index;
16980
          // Run get the next code point given tokenizer.
16981
0
          tokenizer.get_next_code_point();
16982
          // If tokenizer's code point is not U+003F (?):
16983
0
          if (tokenizer.code_point != '?') {
16984
            // Run process a tokenizing error given tokenizer, regexp start, and
16985
            // tokenizer's index.
16986
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16987
0
                    regexp_start, tokenizer.index)) {
16988
0
              return tl::unexpected(*process_error);
16989
0
            }
16990
            // Set error to true.
16991
0
            error = true;
16992
0
            break;
16993
0
          }
16994
          // Set tokenizer's next index to temporary position.
16995
0
          tokenizer.next_index = temporary_position;
16996
0
        }
16997
        // Set regexp position to tokenizer's next index.
16998
0
        regexp_position = tokenizer.next_index;
16999
0
      }
17000
17001
      // If error is true continue.
17002
0
      if (error) continue;
17003
      // If depth is not zero:
17004
0
      if (depth != 0) {
17005
        // Run process a tokenizing error given tokenizer, regexp start, and
17006
        // tokenizer's index.
17007
0
        if (auto process_error = tokenizer.process_tokenizing_error(
17008
0
                regexp_start, tokenizer.index)) {
17009
0
          return tl::unexpected(*process_error);
17010
0
        }
17011
0
        continue;
17012
0
      }
17013
      // Let regexp length be regexp position - regexp start - 1.
17014
0
      auto regexp_length = regexp_position - regexp_start - 1;
17015
      // If regexp length is zero:
17016
0
      if (regexp_length == 0) {
17017
        // Run process a tokenizing error given tokenizer, regexp start, and
17018
        // tokenizer's index.
17019
0
        if (auto process_error = tokenizer.process_tokenizing_error(
17020
0
                regexp_start, tokenizer.index)) {
17021
0
          ada_log("process_tokenizing_error failed");
17022
0
          return tl::unexpected(*process_error);
17023
0
        }
17024
0
        continue;
17025
0
      }
17026
      // Run add a token given tokenizer, "regexp", regexp position, regexp
17027
      // start, and regexp length.
17028
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
17029
0
                          regexp_length);
17030
0
      continue;
17031
0
    }
17032
    // Run add a token with default position and length given tokenizer and
17033
    // "char".
17034
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
17035
0
  }
17036
  // Run add a token with default length given tokenizer, "end", tokenizer's
17037
  // index, and tokenizer's index.
17038
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
17039
0
                                          tokenizer.index);
17040
17041
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
17042
  // Return tokenizer's token list.
17043
0
  return tokenizer.token_list;
17044
0
}
17045
17046
namespace {
17047
constexpr std::array<uint8_t, 256> escape_pattern_table = []() consteval {
17048
  std::array<uint8_t, 256> out{};
17049
  for (auto& c : {'+', '*', '?', ':', '{', '}', '(', ')', '\\'}) {
17050
    out[c] = 1;
17051
  }
17052
  return out;
17053
}();
17054
17055
0
constexpr bool should_escape_pattern_char(char c) {
17056
0
  return escape_pattern_table[static_cast<uint8_t>(c)];
17057
0
}
17058
}  // namespace
17059
17060
0
std::string escape_pattern_string(std::string_view input) {
17061
0
  ada_log("escape_pattern_string called with input=", input);
17062
0
  if (input.empty()) [[unlikely]] {
17063
0
    return "";
17064
0
  }
17065
  // Assert: input is an ASCII string.
17066
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17067
  // Let result be the empty string.
17068
0
  std::string result{};
17069
  // Reserve extra space for potential escapes
17070
0
  result.reserve(input.size() * 2);
17071
17072
  // While index is less than input's length:
17073
0
  for (const char c : input) {
17074
0
    if (should_escape_pattern_char(c)) {
17075
      // Append U+005C (\) to the end of result.
17076
0
      result.push_back('\\');
17077
0
    }
17078
    // Append c to the end of result.
17079
0
    result.push_back(c);
17080
0
  }
17081
  // Return result.
17082
0
  return result;
17083
0
}
17084
17085
namespace {
17086
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
17087
  std::array<uint8_t, 256> out{};
17088
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
17089
                  '|', '/', '\\'}) {
17090
    out[c] = 1;
17091
  }
17092
  return out;
17093
}();
17094
17095
0
constexpr bool should_escape_regexp_char(char c) {
17096
0
  return escape_regexp_table[(uint8_t)c];
17097
0
}
17098
}  // namespace
17099
17100
0
std::string escape_regexp_string(std::string_view input) {
17101
  // Assert: input is an ASCII string.
17102
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17103
  // Let result be the empty string.
17104
0
  std::string result{};
17105
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17106
0
  result.reserve(input.size() * 2);
17107
0
  for (const char c : input) {
17108
0
    if (should_escape_regexp_char(c)) {
17109
      // Avoid temporary string allocation - directly append characters
17110
0
      result.push_back('\\');
17111
0
      result.push_back(c);
17112
0
    } else {
17113
0
      result.push_back(c);
17114
0
    }
17115
0
  }
17116
0
  return result;
17117
0
}
17118
17119
std::string process_base_url_string(std::string_view input,
17120
0
                                    url_pattern_init::process_type type) {
17121
  // If type is not "pattern" return input.
17122
0
  if (type != url_pattern_init::process_type::pattern) {
17123
0
    return std::string(input);
17124
0
  }
17125
  // Return the result of escaping a pattern string given input.
17126
0
  return escape_pattern_string(input);
17127
0
}
17128
17129
constexpr bool is_absolute_pathname(
17130
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
17131
  // If input is the empty string, then return false.
17132
0
  if (input.empty()) [[unlikely]] {
17133
0
    return false;
17134
0
  }
17135
  // If input[0] is U+002F (/), then return true.
17136
0
  if (input.starts_with("/")) return true;
17137
  // If type is "url", then return false.
17138
0
  if (type == url_pattern_init::process_type::url) return false;
17139
  // If input's code point length is less than 2, then return false.
17140
0
  if (input.size() < 2) return false;
17141
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
17142
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
17143
  // Return false.
17144
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
17145
0
}
17146
17147
std::string generate_pattern_string(
17148
    std::vector<url_pattern_part>& part_list,
17149
0
    url_pattern_compile_component_options& options) {
17150
  // Let result be the empty string.
17151
0
  std::string result{};
17152
  // Let index list be the result of getting the indices for part list.
17153
  // For each index of index list:
17154
0
  for (size_t index = 0; index < part_list.size(); index++) {
17155
    // Let part be part list[index].
17156
    // Use reference to avoid copy
17157
0
    const auto& part = part_list[index];
17158
    // Let previous part be part list[index - 1] if index is greater than 0,
17159
    // otherwise let it be null.
17160
    // Use pointer to avoid copy
17161
0
    const url_pattern_part* previous_part =
17162
0
        index == 0 ? nullptr : &part_list[index - 1];
17163
    // Let next part be part list[index + 1] if index is less than index list's
17164
    // size - 1, otherwise let it be null.
17165
0
    const url_pattern_part* next_part =
17166
0
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17167
    // If part's type is "fixed-text" then:
17168
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17169
      // If part's modifier is "none" then:
17170
0
      if (part.modifier == url_pattern_part_modifier::none) {
17171
        // Append the result of running escape a pattern string given part's
17172
        // value to the end of result.
17173
0
        result.append(escape_pattern_string(part.value));
17174
0
        continue;
17175
0
      }
17176
      // Append "{" to the end of result.
17177
0
      result += "{";
17178
      // Append the result of running escape a pattern string given part's value
17179
      // to the end of result.
17180
0
      result.append(escape_pattern_string(part.value));
17181
      // Append "}" to the end of result.
17182
0
      result += "}";
17183
      // Append the result of running convert a modifier to a string given
17184
      // part's modifier to the end of result.
17185
0
      result.append(convert_modifier_to_string(part.modifier));
17186
0
      continue;
17187
0
    }
17188
    // Let custom name be true if part's name[0] is not an ASCII digit;
17189
    // otherwise false.
17190
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
17191
    // Let needs grouping be true if at least one of the following are true,
17192
    // otherwise let it be false:
17193
    // - part's suffix is not the empty string.
17194
    // - part's prefix is not the empty string and is not options's prefix code
17195
    // point.
17196
0
    bool needs_grouping =
17197
0
        !part.suffix.empty() ||
17198
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
17199
17200
    // If all of the following are true:
17201
    // - needs grouping is false; and
17202
    // - custom name is true; and
17203
    // - part's type is "segment-wildcard"; and
17204
    // - part's modifier is "none"; and
17205
    // - next part is not null; and
17206
    // - next part's prefix is the empty string; and
17207
    // - next part's suffix is the empty string
17208
0
    if (!needs_grouping && custom_name &&
17209
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17210
0
        part.modifier == url_pattern_part_modifier::none && next_part &&
17211
0
        next_part->prefix.empty() && next_part->suffix.empty()) {
17212
      // If next part's type is "fixed-text":
17213
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
17214
        // Set needs grouping to true if the result of running is a valid name
17215
        // code point given next part's value's first code point and the boolean
17216
        // false is true.
17217
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17218
0
          needs_grouping = true;
17219
0
        }
17220
0
      } else {
17221
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17222
0
        needs_grouping = !next_part->name.empty() &&
17223
0
                         unicode::is_ascii_digit(next_part->name[0]);
17224
0
      }
17225
0
    }
17226
17227
    // If all of the following are true:
17228
    // - needs grouping is false; and
17229
    // - part's prefix is the empty string; and
17230
    // - previous part is not null; and
17231
    // - previous part's type is "fixed-text"; and
17232
    // - previous part's value's last code point is options's prefix code point.
17233
    // then set needs grouping to true.
17234
0
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17235
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17236
0
        !options.get_prefix().empty() &&
17237
0
        previous_part->value.at(previous_part->value.size() - 1) ==
17238
0
            options.get_prefix()[0]) {
17239
0
      needs_grouping = true;
17240
0
    }
17241
17242
    // Assert: part's name is not the empty string or null.
17243
0
    ADA_ASSERT_TRUE(!part.name.empty());
17244
17245
    // If needs grouping is true, then append "{" to the end of result.
17246
0
    if (needs_grouping) {
17247
0
      result.append("{");
17248
0
    }
17249
17250
    // Append the result of running escape a pattern string given part's prefix
17251
    // to the end of result.
17252
0
    result.append(escape_pattern_string(part.prefix));
17253
17254
    // If custom name is true:
17255
0
    if (custom_name) {
17256
      // Append ":" to the end of result.
17257
0
      result.append(":");
17258
      // Append part's name to the end of result.
17259
0
      result.append(part.name);
17260
0
    }
17261
17262
    // If part's type is "regexp" then:
17263
0
    if (part.type == url_pattern_part_type::REGEXP) {
17264
      // Append "(" to the end of result.
17265
0
      result.append("(");
17266
      // Append part's value to the end of result.
17267
0
      result.append(part.value);
17268
      // Append ")" to the end of result.
17269
0
      result.append(")");
17270
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17271
0
               !custom_name) {
17272
      // Otherwise if part's type is "segment-wildcard" and custom name is
17273
      // false: Append "(" to the end of result.
17274
0
      result.append("(");
17275
      // Append the result of running generate a segment wildcard regexp given
17276
      // options to the end of result.
17277
0
      result.append(generate_segment_wildcard_regexp(options));
17278
      // Append ")" to the end of result.
17279
0
      result.append(")");
17280
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
17281
      // Otherwise if part's type is "full-wildcard":
17282
      // If custom name is false and one of the following is true:
17283
      // - previous part is null; or
17284
      // - previous part's type is "fixed-text"; or
17285
      // - previous part's modifier is not "none"; or
17286
      // - needs grouping is true; or
17287
      // - part's prefix is not the empty string
17288
      // - then append "*" to the end of result.
17289
0
      if (!custom_name &&
17290
0
          (!previous_part ||
17291
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17292
0
           previous_part->modifier != url_pattern_part_modifier::none ||
17293
0
           needs_grouping || !part.prefix.empty())) {
17294
0
        result.append("*");
17295
0
      } else {
17296
        // Append "(" to the end of result.
17297
        // Append full wildcard regexp value to the end of result.
17298
        // Append ")" to the end of result.
17299
0
        result.append("(.*)");
17300
0
      }
17301
0
    }
17302
17303
    // If all of the following are true:
17304
    // - part's type is "segment-wildcard"; and
17305
    // - custom name is true; and
17306
    // - part's suffix is not the empty string; and
17307
    // - The result of running is a valid name code point given part's suffix's
17308
    // first code point and the boolean false is true then append U+005C (\) to
17309
    // the end of result.
17310
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17311
0
        !part.suffix.empty() &&
17312
0
        idna::valid_name_code_point(part.suffix[0], false)) {
17313
0
      result.append("\\");
17314
0
    }
17315
17316
    // Append the result of running escape a pattern string given part's suffix
17317
    // to the end of result.
17318
0
    result.append(escape_pattern_string(part.suffix));
17319
    // If needs grouping is true, then append "}" to the end of result.
17320
0
    if (needs_grouping) result.append("}");
17321
    // Append the result of running convert a modifier to a string given part's
17322
    // modifier to the end of result.
17323
0
    result.append(convert_modifier_to_string(part.modifier));
17324
0
  }
17325
  // Return result.
17326
0
  return result;
17327
0
}
17328
}  // namespace ada::url_pattern_helpers
17329
17330
#endif  // ADA_INCLUDE_URL_PATTERN
17331
/* end file src/url_pattern_helpers.cpp */
17332
/* begin file src/url_pattern_regex.cpp */
17333
#if ADA_INCLUDE_URL_PATTERN
17334
17335
17336
namespace ada::url_pattern_regex {
17337
17338
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17339
std::optional<std::regex> std_regex_provider::create_instance(
17340
    std::string_view pattern, bool ignore_case) {
17341
  // Let flags be an empty string.
17342
  // If options's ignore case is true then set flags to "vi".
17343
  // Otherwise set flags to "v"
17344
  auto flags = ignore_case
17345
                   ? std::regex::icase | std::regex_constants::ECMAScript
17346
                   : std::regex_constants::ECMAScript;
17347
  try {
17348
    return std::regex(pattern.data(), pattern.size(), flags);
17349
  } catch (const std::regex_error& e) {
17350
    (void)e;
17351
    ada_log("std_regex_provider::create_instance failed:", e.what());
17352
    return std::nullopt;
17353
  }
17354
}
17355
17356
std::optional<std::vector<std::optional<std::string>>>
17357
std_regex_provider::regex_search(std::string_view input,
17358
                                 const std::regex& pattern) {
17359
  // Use iterator-based regex_search to avoid string allocation
17360
  std::match_results<std::string_view::const_iterator> match_result;
17361
  if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17362
                         std::regex_constants::match_any)) {
17363
    return std::nullopt;
17364
  }
17365
  std::vector<std::optional<std::string>> matches;
17366
  // If input is empty, let's assume the result will be empty as well.
17367
  if (input.empty() || match_result.empty()) {
17368
    return matches;
17369
  }
17370
  matches.reserve(match_result.size());
17371
  for (size_t i = 1; i < match_result.size(); ++i) {
17372
    if (auto entry = match_result[i]; entry.matched) {
17373
      matches.emplace_back(entry.str());
17374
    }
17375
  }
17376
  return matches;
17377
}
17378
17379
bool std_regex_provider::regex_match(std::string_view input,
17380
                                     const std::regex& pattern) {
17381
  return std::regex_match(input.begin(), input.end(), pattern);
17382
}
17383
17384
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17385
17386
}  // namespace ada::url_pattern_regex
17387
17388
#endif  // ADA_INCLUDE_URL_PATTERN
17389
/* end file src/url_pattern_regex.cpp */
17390
#endif  // ADA_INCLUDE_URL_PATTERN
17391
17392
/* begin file src/ada_c.cpp */
17393
// NOLINTBEGIN(bugprone-exception-escape,
17394
// bugprone-suspicious-stringview-data-usage)
17395
17396
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17397
0
  return *(ada::result<ada::url_aggregator>*)result;
17398
0
}
17399
17400
extern "C" {
17401
typedef void* ada_url;
17402
typedef void* ada_url_search_params;
17403
typedef void* ada_strings;
17404
typedef void* ada_url_search_params_keys_iter;
17405
typedef void* ada_url_search_params_values_iter;
17406
typedef void* ada_url_search_params_entries_iter;
17407
17408
struct ada_string {
17409
  const char* data;
17410
  size_t length;
17411
};
17412
17413
struct ada_owned_string {
17414
  const char* data;
17415
  size_t length;
17416
};
17417
17418
struct ada_string_pair {
17419
  ada_string key;
17420
  ada_string value;
17421
};
17422
17423
0
ada_string ada_string_create(const char* data, size_t length) {
17424
0
  ada_string out{};
17425
0
  out.data = data;
17426
0
  out.length = length;
17427
0
  return out;
17428
0
}
17429
17430
struct ada_url_components {
17431
  /*
17432
   * By using 32-bit integers, we implicitly assume that the URL string
17433
   * cannot exceed 4 GB.
17434
   *
17435
   * https://user:pass@example.com:1234/foo/bar?baz#quux
17436
   *       |     |    |          | ^^^^|       |   |
17437
   *       |     |    |          | |   |       |   `----- hash_start
17438
   *       |     |    |          | |   |       `--------- search_start
17439
   *       |     |    |          | |   `----------------- pathname_start
17440
   *       |     |    |          | `--------------------- port
17441
   *       |     |    |          `----------------------- host_end
17442
   *       |     |    `---------------------------------- host_start
17443
   *       |     `--------------------------------------- username_end
17444
   *       `--------------------------------------------- protocol_end
17445
   */
17446
  uint32_t protocol_end;
17447
  /**
17448
   * Username end is not `omitted` by default (-1) to make username and password
17449
   * getters less costly to implement.
17450
   */
17451
  uint32_t username_end;
17452
  uint32_t host_start;
17453
  uint32_t host_end;
17454
  uint32_t port;
17455
  uint32_t pathname_start;
17456
  uint32_t search_start;
17457
  uint32_t hash_start;
17458
};
17459
17460
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17461
0
  return new ada::result<ada::url_aggregator>(
17462
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17463
0
}
17464
17465
ada_url ada_parse_with_base(const char* input, size_t input_length,
17466
0
                            const char* base, size_t base_length) noexcept {
17467
0
  auto base_out =
17468
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17469
17470
0
  if (!base_out) {
17471
0
    return new ada::result<ada::url_aggregator>(base_out);
17472
0
  }
17473
17474
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17475
0
      std::string_view(input, input_length), &base_out.value()));
17476
0
}
17477
17478
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17479
0
  return ada::can_parse(std::string_view(input, length));
17480
0
}
17481
17482
bool ada_can_parse_with_base(const char* input, size_t input_length,
17483
0
                             const char* base, size_t base_length) noexcept {
17484
0
  std::string_view base_view(base, base_length);
17485
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17486
0
}
17487
17488
0
void ada_free(ada_url result) noexcept {
17489
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17490
0
  delete r;
17491
0
}
17492
17493
0
ada_url ada_copy(ada_url input) noexcept {
17494
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17495
0
  return new ada::result<ada::url_aggregator>(r);
17496
0
}
17497
17498
0
bool ada_is_valid(ada_url result) noexcept {
17499
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17500
0
  return r.has_value();
17501
0
}
17502
17503
// caller must free the result with ada_free_owned_string
17504
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17505
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17506
0
  ada_owned_string owned{};
17507
0
  if (!r) {
17508
0
    owned.data = nullptr;
17509
0
    owned.length = 0;
17510
0
    return owned;
17511
0
  }
17512
0
  std::string out = r->get_origin();
17513
0
  owned.length = out.size();
17514
0
  owned.data = new char[owned.length];
17515
0
  memcpy((void*)owned.data, out.data(), owned.length);
17516
0
  return owned;
17517
0
}
17518
17519
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17520
0
  delete[] owned.data;
17521
0
}
17522
17523
0
ada_string ada_get_href(ada_url result) noexcept {
17524
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17525
0
  if (!r) {
17526
0
    return ada_string_create(nullptr, 0);
17527
0
  }
17528
0
  std::string_view out = r->get_href();
17529
0
  return ada_string_create(out.data(), out.length());
17530
0
}
17531
17532
0
ada_string ada_get_username(ada_url result) noexcept {
17533
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17534
0
  if (!r) {
17535
0
    return ada_string_create(nullptr, 0);
17536
0
  }
17537
0
  std::string_view out = r->get_username();
17538
0
  return ada_string_create(out.data(), out.length());
17539
0
}
17540
17541
0
ada_string ada_get_password(ada_url result) noexcept {
17542
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17543
0
  if (!r) {
17544
0
    return ada_string_create(nullptr, 0);
17545
0
  }
17546
0
  std::string_view out = r->get_password();
17547
0
  return ada_string_create(out.data(), out.length());
17548
0
}
17549
17550
0
ada_string ada_get_port(ada_url result) noexcept {
17551
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17552
0
  if (!r) {
17553
0
    return ada_string_create(nullptr, 0);
17554
0
  }
17555
0
  std::string_view out = r->get_port();
17556
0
  return ada_string_create(out.data(), out.length());
17557
0
}
17558
17559
0
ada_string ada_get_hash(ada_url result) noexcept {
17560
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17561
0
  if (!r) {
17562
0
    return ada_string_create(nullptr, 0);
17563
0
  }
17564
0
  std::string_view out = r->get_hash();
17565
0
  return ada_string_create(out.data(), out.length());
17566
0
}
17567
17568
0
ada_string ada_get_host(ada_url result) noexcept {
17569
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17570
0
  if (!r) {
17571
0
    return ada_string_create(nullptr, 0);
17572
0
  }
17573
0
  std::string_view out = r->get_host();
17574
0
  return ada_string_create(out.data(), out.length());
17575
0
}
17576
17577
0
ada_string ada_get_hostname(ada_url result) noexcept {
17578
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17579
0
  if (!r) {
17580
0
    return ada_string_create(nullptr, 0);
17581
0
  }
17582
0
  std::string_view out = r->get_hostname();
17583
0
  return ada_string_create(out.data(), out.length());
17584
0
}
17585
17586
0
ada_string ada_get_pathname(ada_url result) noexcept {
17587
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17588
0
  if (!r) {
17589
0
    return ada_string_create(nullptr, 0);
17590
0
  }
17591
0
  std::string_view out = r->get_pathname();
17592
0
  return ada_string_create(out.data(), out.length());
17593
0
}
17594
17595
0
ada_string ada_get_search(ada_url result) noexcept {
17596
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17597
0
  if (!r) {
17598
0
    return ada_string_create(nullptr, 0);
17599
0
  }
17600
0
  std::string_view out = r->get_search();
17601
0
  return ada_string_create(out.data(), out.length());
17602
0
}
17603
17604
0
ada_string ada_get_protocol(ada_url result) noexcept {
17605
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17606
0
  if (!r) {
17607
0
    return ada_string_create(nullptr, 0);
17608
0
  }
17609
0
  std::string_view out = r->get_protocol();
17610
0
  return ada_string_create(out.data(), out.length());
17611
0
}
17612
17613
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17614
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17615
0
  if (!r) {
17616
0
    return 0;
17617
0
  }
17618
0
  return r->host_type;
17619
0
}
17620
17621
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17622
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17623
0
  if (!r) {
17624
0
    return 0;
17625
0
  }
17626
0
  return r->type;
17627
0
}
17628
17629
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17630
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17631
0
  if (!r) {
17632
0
    return false;
17633
0
  }
17634
0
  return r->set_href(std::string_view(input, length));
17635
0
}
17636
17637
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17638
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17639
0
  if (!r) {
17640
0
    return false;
17641
0
  }
17642
0
  return r->set_host(std::string_view(input, length));
17643
0
}
17644
17645
bool ada_set_hostname(ada_url result, const char* input,
17646
0
                      size_t length) noexcept {
17647
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17648
0
  if (!r) {
17649
0
    return false;
17650
0
  }
17651
0
  return r->set_hostname(std::string_view(input, length));
17652
0
}
17653
17654
bool ada_set_protocol(ada_url result, const char* input,
17655
0
                      size_t length) noexcept {
17656
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17657
0
  if (!r) {
17658
0
    return false;
17659
0
  }
17660
0
  return r->set_protocol(std::string_view(input, length));
17661
0
}
17662
17663
bool ada_set_username(ada_url result, const char* input,
17664
0
                      size_t length) noexcept {
17665
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17666
0
  if (!r) {
17667
0
    return false;
17668
0
  }
17669
0
  return r->set_username(std::string_view(input, length));
17670
0
}
17671
17672
bool ada_set_password(ada_url result, const char* input,
17673
0
                      size_t length) noexcept {
17674
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17675
0
  if (!r) {
17676
0
    return false;
17677
0
  }
17678
0
  return r->set_password(std::string_view(input, length));
17679
0
}
17680
17681
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17682
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17683
0
  if (!r) {
17684
0
    return false;
17685
0
  }
17686
0
  return r->set_port(std::string_view(input, length));
17687
0
}
17688
17689
bool ada_set_pathname(ada_url result, const char* input,
17690
0
                      size_t length) noexcept {
17691
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17692
0
  if (!r) {
17693
0
    return false;
17694
0
  }
17695
0
  return r->set_pathname(std::string_view(input, length));
17696
0
}
17697
17698
/**
17699
 * Update the search/query of the URL.
17700
 *
17701
 * If a URL has `?` as the search value, passing empty string to this function
17702
 * does not remove the attribute. If you need to remove it, please use
17703
 * `ada_clear_search` method.
17704
 */
17705
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17706
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17707
0
  if (r) {
17708
0
    r->set_search(std::string_view(input, length));
17709
0
  }
17710
0
}
17711
17712
/**
17713
 * Update the hash/fragment of the URL.
17714
 *
17715
 * If a URL has `#` as the hash value, passing empty string to this function
17716
 * does not remove the attribute. If you need to remove it, please use
17717
 * `ada_clear_hash` method.
17718
 */
17719
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17720
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17721
0
  if (r) {
17722
0
    r->set_hash(std::string_view(input, length));
17723
0
  }
17724
0
}
17725
17726
0
void ada_clear_port(ada_url result) noexcept {
17727
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17728
0
  if (r) {
17729
0
    r->clear_port();
17730
0
  }
17731
0
}
17732
17733
/**
17734
 * Removes the hash of the URL.
17735
 *
17736
 * Despite `ada_set_hash` method, this function allows the complete
17737
 * removal of the hash attribute, even if it has a value of `#`.
17738
 */
17739
0
void ada_clear_hash(ada_url result) noexcept {
17740
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17741
0
  if (r) {
17742
0
    r->clear_hash();
17743
0
  }
17744
0
}
17745
17746
/**
17747
 * Removes the search of the URL.
17748
 *
17749
 * Despite `ada_set_search` method, this function allows the complete
17750
 * removal of the search attribute, even if it has a value of `?`.
17751
 */
17752
0
void ada_clear_search(ada_url result) noexcept {
17753
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17754
0
  if (r) {
17755
0
    r->clear_search();
17756
0
  }
17757
0
}
17758
17759
0
bool ada_has_credentials(ada_url result) noexcept {
17760
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17761
0
  if (!r) {
17762
0
    return false;
17763
0
  }
17764
0
  return r->has_credentials();
17765
0
}
17766
17767
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17768
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17769
0
  if (!r) {
17770
0
    return false;
17771
0
  }
17772
0
  return r->has_empty_hostname();
17773
0
}
17774
17775
0
bool ada_has_hostname(ada_url result) noexcept {
17776
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17777
0
  if (!r) {
17778
0
    return false;
17779
0
  }
17780
0
  return r->has_hostname();
17781
0
}
17782
17783
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17784
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17785
0
  if (!r) {
17786
0
    return false;
17787
0
  }
17788
0
  return r->has_non_empty_username();
17789
0
}
17790
17791
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17792
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17793
0
  if (!r) {
17794
0
    return false;
17795
0
  }
17796
0
  return r->has_non_empty_password();
17797
0
}
17798
17799
0
bool ada_has_port(ada_url result) noexcept {
17800
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17801
0
  if (!r) {
17802
0
    return false;
17803
0
  }
17804
0
  return r->has_port();
17805
0
}
17806
17807
0
bool ada_has_password(ada_url result) noexcept {
17808
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17809
0
  if (!r) {
17810
0
    return false;
17811
0
  }
17812
0
  return r->has_password();
17813
0
}
17814
17815
0
bool ada_has_hash(ada_url result) noexcept {
17816
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17817
0
  if (!r) {
17818
0
    return false;
17819
0
  }
17820
0
  return r->has_hash();
17821
0
}
17822
17823
0
bool ada_has_search(ada_url result) noexcept {
17824
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17825
0
  if (!r) {
17826
0
    return false;
17827
0
  }
17828
0
  return r->has_search();
17829
0
}
17830
17831
// returns a pointer to the internal url_aggregator::url_components
17832
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17833
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17834
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17835
0
  if (!r) {
17836
0
    return nullptr;
17837
0
  }
17838
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17839
0
}
17840
17841
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17842
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17843
0
  ada_owned_string owned{};
17844
0
  owned.length = out.length();
17845
0
  owned.data = new char[owned.length];
17846
0
  memcpy((void*)owned.data, out.data(), owned.length);
17847
0
  return owned;
17848
0
}
17849
17850
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17851
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17852
0
  ada_owned_string owned{};
17853
0
  owned.length = out.size();
17854
0
  owned.data = new char[owned.length];
17855
0
  memcpy((void*)owned.data, out.data(), owned.length);
17856
0
  return owned;
17857
0
}
17858
17859
ada_url_search_params ada_parse_search_params(const char* input,
17860
0
                                              size_t length) {
17861
0
  return new ada::result<ada::url_search_params>(
17862
0
      ada::url_search_params(std::string_view(input, length)));
17863
0
}
17864
17865
0
void ada_free_search_params(ada_url_search_params result) {
17866
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17867
0
  delete r;
17868
0
}
17869
17870
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17871
0
  ada::result<ada::url_search_params>& r =
17872
0
      *(ada::result<ada::url_search_params>*)result;
17873
0
  if (!r) return ada_owned_string{nullptr, 0};
17874
0
  std::string out = r->to_string();
17875
0
  ada_owned_string owned{};
17876
0
  owned.length = out.size();
17877
0
  owned.data = new char[owned.length];
17878
0
  memcpy((void*)owned.data, out.data(), owned.length);
17879
0
  return owned;
17880
0
}
17881
17882
0
size_t ada_search_params_size(ada_url_search_params result) {
17883
0
  ada::result<ada::url_search_params>& r =
17884
0
      *(ada::result<ada::url_search_params>*)result;
17885
0
  if (!r) {
17886
0
    return 0;
17887
0
  }
17888
0
  return r->size();
17889
0
}
17890
17891
0
void ada_search_params_sort(ada_url_search_params result) {
17892
0
  ada::result<ada::url_search_params>& r =
17893
0
      *(ada::result<ada::url_search_params>*)result;
17894
0
  if (r) {
17895
0
    r->sort();
17896
0
  }
17897
0
}
17898
17899
void ada_search_params_reset(ada_url_search_params result, const char* input,
17900
0
                             size_t length) {
17901
0
  ada::result<ada::url_search_params>& r =
17902
0
      *(ada::result<ada::url_search_params>*)result;
17903
0
  if (r) {
17904
0
    r->reset(std::string_view(input, length));
17905
0
  }
17906
0
}
17907
17908
void ada_search_params_append(ada_url_search_params result, const char* key,
17909
                              size_t key_length, const char* value,
17910
0
                              size_t value_length) {
17911
0
  ada::result<ada::url_search_params>& r =
17912
0
      *(ada::result<ada::url_search_params>*)result;
17913
0
  if (r) {
17914
0
    r->append(std::string_view(key, key_length),
17915
0
              std::string_view(value, value_length));
17916
0
  }
17917
0
}
17918
17919
void ada_search_params_set(ada_url_search_params result, const char* key,
17920
                           size_t key_length, const char* value,
17921
0
                           size_t value_length) {
17922
0
  ada::result<ada::url_search_params>& r =
17923
0
      *(ada::result<ada::url_search_params>*)result;
17924
0
  if (r) {
17925
0
    r->set(std::string_view(key, key_length),
17926
0
           std::string_view(value, value_length));
17927
0
  }
17928
0
}
17929
17930
void ada_search_params_remove(ada_url_search_params result, const char* key,
17931
0
                              size_t key_length) {
17932
0
  ada::result<ada::url_search_params>& r =
17933
0
      *(ada::result<ada::url_search_params>*)result;
17934
0
  if (r) {
17935
0
    r->remove(std::string_view(key, key_length));
17936
0
  }
17937
0
}
17938
17939
void ada_search_params_remove_value(ada_url_search_params result,
17940
                                    const char* key, size_t key_length,
17941
0
                                    const char* value, size_t value_length) {
17942
0
  ada::result<ada::url_search_params>& r =
17943
0
      *(ada::result<ada::url_search_params>*)result;
17944
0
  if (r) {
17945
0
    r->remove(std::string_view(key, key_length),
17946
0
              std::string_view(value, value_length));
17947
0
  }
17948
0
}
17949
17950
bool ada_search_params_has(ada_url_search_params result, const char* key,
17951
0
                           size_t key_length) {
17952
0
  ada::result<ada::url_search_params>& r =
17953
0
      *(ada::result<ada::url_search_params>*)result;
17954
0
  if (!r) {
17955
0
    return false;
17956
0
  }
17957
0
  return r->has(std::string_view(key, key_length));
17958
0
}
17959
17960
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17961
                                 size_t key_length, const char* value,
17962
0
                                 size_t value_length) {
17963
0
  ada::result<ada::url_search_params>& r =
17964
0
      *(ada::result<ada::url_search_params>*)result;
17965
0
  if (!r) {
17966
0
    return false;
17967
0
  }
17968
0
  return r->has(std::string_view(key, key_length),
17969
0
                std::string_view(value, value_length));
17970
0
}
17971
17972
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17973
0
                                 size_t key_length) {
17974
0
  ada::result<ada::url_search_params>& r =
17975
0
      *(ada::result<ada::url_search_params>*)result;
17976
0
  if (!r) {
17977
0
    return ada_string_create(nullptr, 0);
17978
0
  }
17979
0
  auto found = r->get(std::string_view(key, key_length));
17980
0
  if (!found.has_value()) {
17981
0
    return ada_string_create(nullptr, 0);
17982
0
  }
17983
0
  return ada_string_create(found->data(), found->length());
17984
0
}
17985
17986
ada_strings ada_search_params_get_all(ada_url_search_params result,
17987
0
                                      const char* key, size_t key_length) {
17988
0
  ada::result<ada::url_search_params>& r =
17989
0
      *(ada::result<ada::url_search_params>*)result;
17990
0
  if (!r) {
17991
0
    return new ada::result<std::vector<std::string>>(
17992
0
        std::vector<std::string>());
17993
0
  }
17994
0
  return new ada::result<std::vector<std::string>>(
17995
0
      r->get_all(std::string_view(key, key_length)));
17996
0
}
17997
17998
ada_url_search_params_keys_iter ada_search_params_get_keys(
17999
0
    ada_url_search_params result) {
18000
0
  ada::result<ada::url_search_params>& r =
18001
0
      *(ada::result<ada::url_search_params>*)result;
18002
0
  if (!r) {
18003
0
    return new ada::result<ada::url_search_params_keys_iter>(
18004
0
        ada::url_search_params_keys_iter());
18005
0
  }
18006
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
18007
0
}
18008
18009
ada_url_search_params_values_iter ada_search_params_get_values(
18010
0
    ada_url_search_params result) {
18011
0
  ada::result<ada::url_search_params>& r =
18012
0
      *(ada::result<ada::url_search_params>*)result;
18013
0
  if (!r) {
18014
0
    return new ada::result<ada::url_search_params_values_iter>(
18015
0
        ada::url_search_params_values_iter());
18016
0
  }
18017
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
18018
0
}
18019
18020
ada_url_search_params_entries_iter ada_search_params_get_entries(
18021
0
    ada_url_search_params result) {
18022
0
  ada::result<ada::url_search_params>& r =
18023
0
      *(ada::result<ada::url_search_params>*)result;
18024
0
  if (!r) {
18025
0
    return new ada::result<ada::url_search_params_entries_iter>(
18026
0
        ada::url_search_params_entries_iter());
18027
0
  }
18028
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
18029
0
}
18030
18031
0
void ada_free_strings(ada_strings result) {
18032
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18033
0
  delete r;
18034
0
}
18035
18036
0
size_t ada_strings_size(ada_strings result) {
18037
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18038
0
  if (!r) {
18039
0
    return 0;
18040
0
  }
18041
0
  return (*r)->size();
18042
0
}
18043
18044
0
ada_string ada_strings_get(ada_strings result, size_t index) {
18045
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
18046
0
  if (!r) {
18047
0
    return ada_string_create(nullptr, 0);
18048
0
  }
18049
0
  std::string_view view = (*r)->at(index);
18050
0
  return ada_string_create(view.data(), view.length());
18051
0
}
18052
18053
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
18054
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18055
0
  delete r;
18056
0
}
18057
18058
ada_string ada_search_params_keys_iter_next(
18059
0
    ada_url_search_params_keys_iter result) {
18060
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18061
0
  if (!r) {
18062
0
    return ada_string_create(nullptr, 0);
18063
0
  }
18064
0
  auto next = (*r)->next();
18065
0
  if (!next.has_value()) {
18066
0
    return ada_string_create(nullptr, 0);
18067
0
  }
18068
0
  return ada_string_create(next->data(), next->length());
18069
0
}
18070
18071
bool ada_search_params_keys_iter_has_next(
18072
0
    ada_url_search_params_keys_iter result) {
18073
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18074
0
  if (!r) {
18075
0
    return false;
18076
0
  }
18077
0
  return (*r)->has_next();
18078
0
}
18079
18080
void ada_free_search_params_values_iter(
18081
0
    ada_url_search_params_values_iter result) {
18082
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18083
0
  delete r;
18084
0
}
18085
18086
ada_string ada_search_params_values_iter_next(
18087
0
    ada_url_search_params_values_iter result) {
18088
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18089
0
  if (!r) {
18090
0
    return ada_string_create(nullptr, 0);
18091
0
  }
18092
0
  auto next = (*r)->next();
18093
0
  if (!next.has_value()) {
18094
0
    return ada_string_create(nullptr, 0);
18095
0
  }
18096
0
  return ada_string_create(next->data(), next->length());
18097
0
}
18098
18099
bool ada_search_params_values_iter_has_next(
18100
0
    ada_url_search_params_values_iter result) {
18101
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18102
0
  if (!r) {
18103
0
    return false;
18104
0
  }
18105
0
  return (*r)->has_next();
18106
0
}
18107
18108
void ada_free_search_params_entries_iter(
18109
0
    ada_url_search_params_entries_iter result) {
18110
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18111
0
  delete r;
18112
0
}
18113
18114
ada_string_pair ada_search_params_entries_iter_next(
18115
0
    ada_url_search_params_entries_iter result) {
18116
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18117
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18118
0
  auto next = (*r)->next();
18119
0
  if (!next.has_value()) {
18120
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18121
0
  }
18122
0
  return ada_string_pair{
18123
0
      ada_string_create(next->first.data(), next->first.length()),
18124
0
      ada_string_create(next->second.data(), next->second.length())};
18125
0
}
18126
18127
bool ada_search_params_entries_iter_has_next(
18128
0
    ada_url_search_params_entries_iter result) {
18129
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18130
0
  if (!r) {
18131
0
    return false;
18132
0
  }
18133
0
  return (*r)->has_next();
18134
0
}
18135
18136
typedef struct {
18137
  int major;
18138
  int minor;
18139
  int revision;
18140
} ada_version_components;
18141
18142
0
const char* ada_get_version() { return ADA_VERSION; }
18143
18144
0
ada_version_components ada_get_version_components() {
18145
0
  return ada_version_components{
18146
0
      .major = ada::ADA_VERSION_MAJOR,
18147
0
      .minor = ada::ADA_VERSION_MINOR,
18148
0
      .revision = ada::ADA_VERSION_REVISION,
18149
0
  };
18150
0
}
18151
18152
}  // extern "C"
18153
// NOLINTEND(bugprone-exception-escape,
18154
// bugprone-suspicious-stringview-data-usage)
18155
/* end file src/ada_c.cpp */
18156
/* end file src/ada.cpp */