Coverage Report

Created: 2025-10-13 06:17

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 2025-10-10 09:09:47 -0400. 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
/* auto-generated on 2025-06-26 23:04:30 -0300. Do not edit! */
140
/* begin file src/idna.cpp */
141
/* begin file src/unicode_transcoding.cpp */
142
143
#include <algorithm>
144
#include <cstdint>
145
#include <cstring>
146
147
namespace ada::idna {
148
149
0
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
150
0
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
151
0
  size_t pos = 0;
152
0
  const char32_t* start{utf32_output};
153
0
  while (pos < len) {
154
    // try to convert the next block of 16 ASCII bytes
155
0
    if (pos + 16 <= len) {  // if it is safe to read 16 more
156
                            // bytes, check that they are ascii
157
0
      uint64_t v1;
158
0
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
159
0
      uint64_t v2;
160
0
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
161
0
      uint64_t v{v1 | v2};
162
0
      if ((v & 0x8080808080808080) == 0) {
163
0
        size_t final_pos = pos + 16;
164
0
        while (pos < final_pos) {
165
0
          *utf32_output++ = char32_t(buf[pos]);
166
0
          pos++;
167
0
        }
168
0
        continue;
169
0
      }
170
0
    }
171
0
    uint8_t leading_byte = data[pos];  // leading byte
172
0
    if (leading_byte < 0b10000000) {
173
      // converting one ASCII byte !!!
174
0
      *utf32_output++ = char32_t(leading_byte);
175
0
      pos++;
176
0
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
177
      // We have a two-byte UTF-8
178
0
      if (pos + 1 >= len) {
179
0
        return 0;
180
0
      }  // minimal bound checking
181
0
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
182
0
        return 0;
183
0
      }
184
      // range check
185
0
      uint32_t code_point =
186
0
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
187
0
      if (code_point < 0x80 || 0x7ff < code_point) {
188
0
        return 0;
189
0
      }
190
0
      *utf32_output++ = char32_t(code_point);
191
0
      pos += 2;
192
0
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
193
      // We have a three-byte UTF-8
194
0
      if (pos + 2 >= len) {
195
0
        return 0;
196
0
      }  // minimal bound checking
197
198
0
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
199
0
        return 0;
200
0
      }
201
0
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
202
0
        return 0;
203
0
      }
204
      // range check
205
0
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
206
0
                            (data[pos + 1] & 0b00111111) << 6 |
207
0
                            (data[pos + 2] & 0b00111111);
208
0
      if (code_point < 0x800 || 0xffff < code_point ||
209
0
          (0xd7ff < code_point && code_point < 0xe000)) {
210
0
        return 0;
211
0
      }
212
0
      *utf32_output++ = char32_t(code_point);
213
0
      pos += 3;
214
0
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
215
      // we have a 4-byte UTF-8 word.
216
0
      if (pos + 3 >= len) {
217
0
        return 0;
218
0
      }  // minimal bound checking
219
0
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
220
0
        return 0;
221
0
      }
222
0
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
223
0
        return 0;
224
0
      }
225
0
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
226
0
        return 0;
227
0
      }
228
229
      // range check
230
0
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
231
0
                            (data[pos + 1] & 0b00111111) << 12 |
232
0
                            (data[pos + 2] & 0b00111111) << 6 |
233
0
                            (data[pos + 3] & 0b00111111);
234
0
      if (code_point <= 0xffff || 0x10ffff < code_point) {
235
0
        return 0;
236
0
      }
237
0
      *utf32_output++ = char32_t(code_point);
238
0
      pos += 4;
239
0
    } else {
240
0
      return 0;
241
0
    }
242
0
  }
243
0
  return utf32_output - start;
244
0
}
245
246
0
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
247
  // We are not BOM aware.
248
0
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
249
0
  size_t counter{0};
250
0
  for (size_t i = 0; i != len; ++i) {
251
0
    ++counter;                                      // ASCII
252
0
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
253
0
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
254
0
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
255
0
  }
256
0
  return counter;
257
0
}
258
259
0
size_t utf32_length_from_utf8(const char* buf, size_t len) {
260
0
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
261
0
  return std::count_if(p, std::next(p, len), [](int8_t c) {
262
    // -65 is 0b10111111, anything larger in two-complement's
263
    // should start a new code point.
264
0
    return c > -65;
265
0
  });
266
0
}
267
268
0
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
269
0
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
270
0
  size_t pos = 0;
271
0
  const char* start{utf8_output};
272
0
  while (pos < len) {
273
    // try to convert the next block of 2 ASCII characters
274
0
    if (pos + 2 <= len) {  // if it is safe to read 8 more
275
                           // bytes, check that they are ascii
276
0
      uint64_t v;
277
0
      std::memcpy(&v, data + pos, sizeof(uint64_t));
278
0
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
279
0
        *utf8_output++ = char(buf[pos]);
280
0
        *utf8_output++ = char(buf[pos + 1]);
281
0
        pos += 2;
282
0
        continue;
283
0
      }
284
0
    }
285
0
    uint32_t word = data[pos];
286
0
    if ((word & 0xFFFFFF80) == 0) {
287
      // will generate one UTF-8 bytes
288
0
      *utf8_output++ = char(word);
289
0
      pos++;
290
0
    } else if ((word & 0xFFFFF800) == 0) {
291
      // will generate two UTF-8 bytes
292
      // we have 0b110XXXXX 0b10XXXXXX
293
0
      *utf8_output++ = char((word >> 6) | 0b11000000);
294
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
295
0
      pos++;
296
0
    } else if ((word & 0xFFFF0000) == 0) {
297
      // will generate three UTF-8 bytes
298
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
299
0
      if (word >= 0xD800 && word <= 0xDFFF) {
300
0
        return 0;
301
0
      }
302
0
      *utf8_output++ = char((word >> 12) | 0b11100000);
303
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
304
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
305
0
      pos++;
306
0
    } else {
307
      // will generate four UTF-8 bytes
308
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
309
      // 0b10XXXXXX
310
0
      if (word > 0x10FFFF) {
311
0
        return 0;
312
0
      }
313
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
314
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
315
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
316
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
317
0
      pos++;
318
0
    }
319
0
  }
320
0
  return utf8_output - start;
321
0
}
322
}  // namespace ada::idna
323
/* end file src/unicode_transcoding.cpp */
324
/* begin file src/mapping.cpp */
325
326
#include <algorithm>
327
#include <array>
328
#include <string>
329
330
/* begin file src/mapping_tables.cpp */
331
// IDNA  16.0.0
332
333
// clang-format off
334
#ifndef ADA_IDNA_TABLES_H
335
#define ADA_IDNA_TABLES_H
336
#include <cstdint>
337
338
namespace ada::idna {
339
340
const uint32_t mappings[5236] =
341
{
342
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
343
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
344
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
345
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
346
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
347
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
348
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
349
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
350
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
351
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
352
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
353
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
354
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
355
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
356
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
357
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
358
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
359
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
360
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
361
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
362
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
363
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
364
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
365
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
366
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
367
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
368
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
369
  1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243,
370
  1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271,
371
  1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
372
  1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327,
373
  1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390,
374
  1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404,
375
  1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652,
376
  1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364,
377
  2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492,
378
  2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876,
379
  2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916,
380
  4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018,
381
  3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001,
382
  4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525,
383
  11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537,
384
  11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549,
385
  11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104,
386
  5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310,
387
  4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325,
388
  4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339,
389
  4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604,
390
  7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671,
391
  625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689,
392
  7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717,
393
  7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745,
394
  7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773,
395
  7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801,
396
  7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829,
397
  97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861,
398
  7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889,
399
  7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917,
400
  7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940,
401
  7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972,
402
  7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002,
403
  8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038,
404
  8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953,
405
  7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974,
406
  953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953,
407
  8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32,
408
  787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32,
409
  787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788,
410
  769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969,
411
  953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245,
412
  8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55,
413
  56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99,
414
  47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491,
415
  102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51,
416
  50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260,
417
  54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105,
418
  105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120,
419
  120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750,
420
  8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49,
421
  55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40,
422
  53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49,
423
  49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49,
424
  54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97,
425
  41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41,
426
  40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40,
427
  110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116,
428
  41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41,
429
  58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318,
430
  11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330,
431
  11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342,
432
  11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354,
433
  11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379,
434
  11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409,
435
  11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433,
436
  11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457,
437
  11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481,
438
  11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968,
439
  20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866,
440
  20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340,
441
  21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823,
442
  22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049,
443
  24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515,
444
  25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352,
445
  26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700,
446
  28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916,
447
  29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446,
448
  30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566,
449
  32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267,
450
  33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915,
451
  35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275,
452
  36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272,
453
  38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913,
454
  39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730,
455
  39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701,
456
  40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316,
457
  21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354,
458
  4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359,
459
  4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450,
460
  4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464,
461
  4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569,
462
  4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398,
463
  4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488,
464
  4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969,
465
  22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358,
466
  41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367,
467
  41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40,
468
  45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500,
469
  41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40,
470
  54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968,
471
  41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40,
472
  19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779,
473
  41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40,
474
  26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001,
475
  41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40,
476
  30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241,
477
  41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50,
478
  52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280,
479
  44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889,
480
  27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48,
481
  52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51,
482
  26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48,
483
  26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116,
484
  100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471,
485
  12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494,
486
  12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518,
487
  12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644,
488
  12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450,
489
  12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457,
490
  12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531,
491
  12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459,
492
  12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462,
493
  12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525,
494
  12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461,
495
  12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476,
496
  12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490,
497
  12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512,
498
  12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540,
499
  12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452,
500
  12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524,
501
  12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499,
502
  12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483,
503
  12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506,
504
  12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540,
505
  12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507,
506
  12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452,
507
  12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510,
508
  12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522,
509
  12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489,
510
  12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521,
511
  12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488,
512
  12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857,
513
  54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50,
514
  28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857,
515
  49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51,
516
  28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112,
517
  99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644,
518
  22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97,
519
  107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110,
520
  102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104,
521
  122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109,
522
  109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109,
523
  51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97,
524
  109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100,
525
  8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956,
526
  118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107,
527
  969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110,
528
  107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111,
529
  108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725,
530
  109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085,
531
  56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085,
532
  49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57,
533
  26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085,
534
  50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48,
535
  26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575,
536
  42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599,
537
  42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641,
538
  42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799,
539
  42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825,
540
  42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849,
541
  42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881,
542
  42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913,
543
  42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941,
544
  42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42961, 42967, 42969,
545
  42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030,
546
  5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044,
547
  5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058,
548
  5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072,
549
  5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086,
550
  5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100,
551
  5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856,
552
  25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853,
553
  37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172,
554
  25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796,
555
  27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160,
556
  33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744,
557
  23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260,
558
  32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271,
559
  30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498,
560
  27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391,
561
  35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654,
562
  26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244,
563
  32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565,
564
  25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428,
565
  38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615,
566
  26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316,
567
  29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459,
568
  24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178,
569
  32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023,
570
  40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050,
571
  20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952,
572
  22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322,
573
  35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813,
574
  21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974,
575
  25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865,
576
  31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626,
577
  32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627,
578
  38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191,
579
  21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425,
580
  24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454,
581
  28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427,
582
  30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137,
583
  35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923,
584
  39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832, 163539, 40771,
585
  40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396,
586
  1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501,
587
  1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463,
588
  1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468,
589
  1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468,
590
  1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468,
591
  1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659,
592
  1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678,
593
  1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747,
594
  1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608,
595
  1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574,
596
  1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576,
597
  1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578,
598
  1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581,
599
  1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587,
600
  1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591,
601
  1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601,
602
  1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602,
603
  1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603,
604
  1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604,
605
  1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606,
606
  1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607,
607
  1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585,
608
  1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617,
609
  32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585,
610
  1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586,
611
  1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586,
612
  1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607,
613
  1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600,
614
  1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594,
615
  1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580,
616
  1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588,
617
  1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575,
618
  1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578,
619
  1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609,
620
  1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605,
621
  1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588,
622
  1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605,
623
  1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605,
624
  1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601,
625
  1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610,
626
  1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581,
627
  1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607,
628
  1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605,
629
  1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582,
630
  1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578,
631
  1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609,
632
  1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580,
633
  1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602,
634
  1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581,
635
  1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580,
636
  1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606,
637
  1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603,
638
  1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604,
639
  1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609,
640
  32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605,
641
  1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289,
642
  12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298, 12299,
643
  12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32,
644
  1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573,
645
  1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539,
646
  12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632,
647
  9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609, 66610,
648
  66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621, 66622,
649
  66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633, 66634,
650
  66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781, 66782,
651
  66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793, 66794,
652
  66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806,
653
  66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972, 66973,
654
  66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985, 66986,
655
  66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998, 66999,
656
  67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600, 606,
657
  681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630,
658
  630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448,
659
  449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807,
660
  68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819,
661
  68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
662
  68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843,
663
  68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980,
664
  68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992,
665
  68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878,
666
  71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890,
667
  71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902,
668
  71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802,
669
  93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814,
670
  93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128,
671
  119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152,
672
  119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141,
673
  119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226,
674
  119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222, 125223,
675
  125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233,
676
  125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243,
677
  125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647,
678
  48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44,
679
  12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119, 99,
680
  109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132,
681
  26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436,
682
  25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942,
683
  37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433,
684
  12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213,
685
  12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411,
686
  20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839,
687
  132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589,
688
  21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987,
689
  21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859,
690
  21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541,
691
  22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938,
692
  23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491, 23512,
693
  23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875, 138726,
694
  23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651,
695
  14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122,
696
  24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775,
697
  24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424,
698
  142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705,
699
  25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076,
700
  20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618,
701
  26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355,
702
  15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170,
703
  27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956,
704
  28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729,
705
  28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395,
706
  29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605,
707
  16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679,
708
  30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494,
709
  30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211,
710
  16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935,
711
  154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325,
712
  17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963,
713
  32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607,
714
  157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457,
715
  33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738,
716
  33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148,
717
  159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440,
718
  34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031,
719
  35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011,
720
  36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330,
721
  165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909,
722
  166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474,
723
  19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209,
724
  39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704,
725
  172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568,
726
727
};
728
const uint32_t table[8150][2] =
729
{
730
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
731
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
732
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
733
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
734
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
735
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
736
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
737
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
738
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
739
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
740
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
741
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
742
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
743
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
744
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
745
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
746
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
747
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
748
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
749
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
750
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
751
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
752
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
753
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
754
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
755
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
756
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
757
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
758
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
759
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
760
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
761
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
762
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
763
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
764
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
765
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
766
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
767
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
768
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
769
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
770
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
771
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
772
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
773
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
774
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
775
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
776
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
777
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
778
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
779
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
780
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
781
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
782
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
783
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
784
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
785
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
786
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
787
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
788
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
789
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
790
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
791
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
792
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
793
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
794
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
795
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
796
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
797
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
798
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
799
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
800
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
801
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
802
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
803
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
804
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
805
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
806
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
807
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
808
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
809
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
810
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
811
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
812
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
813
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
814
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
815
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
816
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
817
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
818
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
819
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
820
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
821
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
822
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
823
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
824
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
825
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
826
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
827
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
828
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
829
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
830
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
831
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
832
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
833
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
834
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
835
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
836
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
837
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
838
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
839
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
840
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
841
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
842
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
843
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
844
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
845
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
846
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
847
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
848
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
849
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
850
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
851
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
852
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
853
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
854
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
855
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
856
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
857
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
858
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
859
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
860
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
861
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
862
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
863
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
864
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
865
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
866
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
867
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
868
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
869
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
870
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
871
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
872
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
873
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
874
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
875
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
876
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
877
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
878
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
879
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
880
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
881
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
882
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
883
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
884
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
885
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
886
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
887
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
888
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
889
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
890
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
891
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
892
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
893
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
894
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
895
  {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531},
896
  {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043},
897
  {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555},
898
  {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067},
899
  {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579},
900
  {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091},
901
  {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603},
902
  {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115},
903
  {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627},
904
  {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139},
905
  {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651},
906
  {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163},
907
  {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675},
908
  {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187},
909
  {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699},
910
  {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211},
911
  {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723},
912
  {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235},
913
  {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747},
914
  {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259},
915
  {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771},
916
  {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283},
917
  {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795},
918
  {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307},
919
  {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819},
920
  {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331},
921
  {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843},
922
  {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2},
923
  {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123},
924
  {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147},
925
  {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171},
926
  {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195},
927
  {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219},
928
  {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243},
929
  {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267},
930
  {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291},
931
  {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315},
932
  {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1},
933
  {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1},
934
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
935
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
936
  {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323},
937
  {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2},
938
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
939
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
940
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
941
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
942
  {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
943
  {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859},
944
  {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907},
945
  {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1},
946
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
947
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
948
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
949
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
950
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
951
  {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2},
952
  {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1},
953
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
954
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
955
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
956
  {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003},
957
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
958
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
959
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
960
  {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539},
961
  {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2},
962
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
963
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
964
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
965
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
966
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
967
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
968
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
969
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
970
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
971
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
972
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
973
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
974
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
975
  {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1},
976
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
977
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
978
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
979
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
980
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
981
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
982
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
983
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
984
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
985
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
986
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
987
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
988
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
989
  {3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
990
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
991
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
992
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
993
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
994
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
995
  {3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
996
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
997
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
998
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
999
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
1000
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
1001
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
1002
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
1003
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
1004
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
1005
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
1006
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
1007
  {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1},
1008
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1009
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1010
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1011
  {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1},
1012
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1013
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611},
1014
  {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1},
1015
  {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1},
1016
  {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1},
1017
  {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1},
1018
  {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1},
1019
  {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1},
1020
  {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267},
1021
  {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1},
1022
  {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1},
1023
  {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1},
1024
  {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1},
1025
  {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1},
1026
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1027
  {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171},
1028
  {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195},
1029
  {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219},
1030
  {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243},
1031
  {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267},
1032
  {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291},
1033
  {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315},
1034
  {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339},
1035
  {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363},
1036
  {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131},
1037
  {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1},
1038
  {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1},
1039
  {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1},
1040
  {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1},
1041
  {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1},
1042
  {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1},
1043
  {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1},
1044
  {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1},
1045
  {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1},
1046
  {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1},
1047
  {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1},
1048
  {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411},
1049
  {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2},
1050
  {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2},
1051
  {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2},
1052
  {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2},
1053
  {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2},
1054
  {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0},
1055
  {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2},
1056
  {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0},
1057
  {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2},
1058
  {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2},
1059
  {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2},
1060
  {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2},
1061
  {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2},
1062
  {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2},
1063
  {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2},
1064
  {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2},
1065
  {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2},
1066
  {6816, 1}, {6830, 2}, {6832, 1}, {6863, 2},
1067
  {6912, 1}, {6989, 2}, {6990, 1}, {7156, 2},
1068
  {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1069
  {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1070
  {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1071
  {7304, 16946435}, {7305, 16946691}, {7306, 1}, {7307, 2},
1072
  {7312, 16946947}, {7313, 16947203}, {7314, 16947459}, {7315, 16947715},
1073
  {7316, 16947971}, {7317, 16948227}, {7318, 16948483}, {7319, 16948739},
1074
  {7320, 16948995}, {7321, 16949251}, {7322, 16949507}, {7323, 16949763},
1075
  {7324, 16944643}, {7325, 16950019}, {7326, 16950275}, {7327, 16950531},
1076
  {7328, 16950787}, {7329, 16951043}, {7330, 16951299}, {7331, 16951555},
1077
  {7332, 16951811}, {7333, 16952067}, {7334, 16952323}, {7335, 16952579},
1078
  {7336, 16952835}, {7337, 16953091}, {7338, 16953347}, {7339, 16953603},
1079
  {7340, 16953859}, {7341, 16954115}, {7342, 16954371}, {7343, 16954627},
1080
  {7344, 16954883}, {7345, 16955139}, {7346, 16955395}, {7347, 16955651},
1081
  {7348, 16955907}, {7349, 16956163}, {7350, 16956419}, {7351, 16956675},
1082
  {7352, 16956931}, {7353, 16957187}, {7354, 16957443}, {7355, 2},
1083
  {7357, 16957699}, {7358, 16957955}, {7359, 16958211}, {7360, 1},
1084
  {7368, 2}, {7376, 1}, {7419, 2}, {7424, 1},
1085
  {7468, 16777219}, {7469, 16791043}, {7470, 16777475}, {7471, 1},
1086
  {7472, 16777987}, {7473, 16778243}, {7474, 16816131}, {7475, 16778755},
1087
  {7476, 16779011}, {7477, 16779267}, {7478, 16779523}, {7479, 16779779},
1088
  {7480, 16780035}, {7481, 16780291}, {7482, 16780547}, {7483, 1},
1089
  {7484, 16780803}, {7485, 16835843}, {7486, 16781059}, {7487, 16781571},
1090
  {7488, 16782083}, {7489, 16782339}, {7490, 16782851}, {7491, 16777219},
1091
  {7492, 16958467}, {7493, 16958723}, {7494, 16958979}, {7495, 16777475},
1092
  {7496, 16777987}, {7497, 16778243}, {7498, 16816387}, {7499, 16816643},
1093
  {7500, 16959235}, {7501, 16778755}, {7502, 1}, {7503, 16779779},
1094
  {7504, 16780291}, {7505, 16807171}, {7506, 16780803}, {7507, 16814851},
1095
  {7508, 16959491}, {7509, 16959747}, {7510, 16781059}, {7511, 16782083},
1096
  {7512, 16782339}, {7513, 16960003}, {7514, 16818435}, {7515, 16782595},
1097
  {7516, 16960259}, {7517, 16851971}, {7518, 16852227}, {7519, 16852483},
1098
  {7520, 16856323}, {7521, 16856579}, {7522, 16779267}, {7523, 16781571},
1099
  {7524, 16782339}, {7525, 16782595}, {7526, 16851971}, {7527, 16852227},
1100
  {7528, 16855299}, {7529, 16856323}, {7530, 16856579}, {7531, 1},
1101
  {7544, 16869891}, {7545, 1}, {7579, 16960515}, {7580, 16777731},
1102
  {7581, 16960771}, {7582, 16793603}, {7583, 16959235}, {7584, 16778499},
1103
  {7585, 16961027}, {7586, 16961283}, {7587, 16961539}, {7588, 16817923},
1104
  {7589, 16817667}, {7590, 16961795}, {7591, 16962051}, {7592, 16962307},
1105
  {7593, 16962563}, {7594, 16962819}, {7595, 16963075}, {7596, 16963331},
1106
  {7597, 16963587}, {7598, 16818691}, {7599, 16963843}, {7600, 16964099},
1107
  {7601, 16818947}, {7602, 16964355}, {7603, 16964611}, {7604, 16820483},
1108
  {7605, 16964867}, {7606, 16839683}, {7607, 16821507}, {7608, 16965123},
1109
  {7609, 16821763}, {7610, 16839939}, {7611, 16783619}, {7612, 16965379},
1110
  {7613, 16965635}, {7614, 16822531}, {7615, 16853507}, {7616, 1},
1111
  {7680, 16965891}, {7681, 1}, {7682, 16966147}, {7683, 1},
1112
  {7684, 16966403}, {7685, 1}, {7686, 16966659}, {7687, 1},
1113
  {7688, 16966915}, {7689, 1}, {7690, 16967171}, {7691, 1},
1114
  {7692, 16967427}, {7693, 1}, {7694, 16967683}, {7695, 1},
1115
  {7696, 16967939}, {7697, 1}, {7698, 16968195}, {7699, 1},
1116
  {7700, 16968451}, {7701, 1}, {7702, 16968707}, {7703, 1},
1117
  {7704, 16968963}, {7705, 1}, {7706, 16969219}, {7707, 1},
1118
  {7708, 16969475}, {7709, 1}, {7710, 16969731}, {7711, 1},
1119
  {7712, 16969987}, {7713, 1}, {7714, 16970243}, {7715, 1},
1120
  {7716, 16970499}, {7717, 1}, {7718, 16970755}, {7719, 1},
1121
  {7720, 16971011}, {7721, 1}, {7722, 16971267}, {7723, 1},
1122
  {7724, 16971523}, {7725, 1}, {7726, 16971779}, {7727, 1},
1123
  {7728, 16972035}, {7729, 1}, {7730, 16972291}, {7731, 1},
1124
  {7732, 16972547}, {7733, 1}, {7734, 16972803}, {7735, 1},
1125
  {7736, 16973059}, {7737, 1}, {7738, 16973315}, {7739, 1},
1126
  {7740, 16973571}, {7741, 1}, {7742, 16973827}, {7743, 1},
1127
  {7744, 16974083}, {7745, 1}, {7746, 16974339}, {7747, 1},
1128
  {7748, 16974595}, {7749, 1}, {7750, 16974851}, {7751, 1},
1129
  {7752, 16975107}, {7753, 1}, {7754, 16975363}, {7755, 1},
1130
  {7756, 16975619}, {7757, 1}, {7758, 16975875}, {7759, 1},
1131
  {7760, 16976131}, {7761, 1}, {7762, 16976387}, {7763, 1},
1132
  {7764, 16976643}, {7765, 1}, {7766, 16976899}, {7767, 1},
1133
  {7768, 16977155}, {7769, 1}, {7770, 16977411}, {7771, 1},
1134
  {7772, 16977667}, {7773, 1}, {7774, 16977923}, {7775, 1},
1135
  {7776, 16978179}, {7777, 1}, {7778, 16978435}, {7779, 1},
1136
  {7780, 16978691}, {7781, 1}, {7782, 16978947}, {7783, 1},
1137
  {7784, 16979203}, {7785, 1}, {7786, 16979459}, {7787, 1},
1138
  {7788, 16979715}, {7789, 1}, {7790, 16979971}, {7791, 1},
1139
  {7792, 16980227}, {7793, 1}, {7794, 16980483}, {7795, 1},
1140
  {7796, 16980739}, {7797, 1}, {7798, 16980995}, {7799, 1},
1141
  {7800, 16981251}, {7801, 1}, {7802, 16981507}, {7803, 1},
1142
  {7804, 16981763}, {7805, 1}, {7806, 16982019}, {7807, 1},
1143
  {7808, 16982275}, {7809, 1}, {7810, 16982531}, {7811, 1},
1144
  {7812, 16982787}, {7813, 1}, {7814, 16983043}, {7815, 1},
1145
  {7816, 16983299}, {7817, 1}, {7818, 16983555}, {7819, 1},
1146
  {7820, 16983811}, {7821, 1}, {7822, 16984067}, {7823, 1},
1147
  {7824, 16984323}, {7825, 1}, {7826, 16984579}, {7827, 1},
1148
  {7828, 16984835}, {7829, 1}, {7834, 33762307}, {7835, 16978179},
1149
  {7836, 1}, {7838, 16985603}, {7839, 1}, {7840, 16985859},
1150
  {7841, 1}, {7842, 16986115}, {7843, 1}, {7844, 16986371},
1151
  {7845, 1}, {7846, 16986627}, {7847, 1}, {7848, 16986883},
1152
  {7849, 1}, {7850, 16987139}, {7851, 1}, {7852, 16987395},
1153
  {7853, 1}, {7854, 16987651}, {7855, 1}, {7856, 16987907},
1154
  {7857, 1}, {7858, 16988163}, {7859, 1}, {7860, 16988419},
1155
  {7861, 1}, {7862, 16988675}, {7863, 1}, {7864, 16988931},
1156
  {7865, 1}, {7866, 16989187}, {7867, 1}, {7868, 16989443},
1157
  {7869, 1}, {7870, 16989699}, {7871, 1}, {7872, 16989955},
1158
  {7873, 1}, {7874, 16990211}, {7875, 1}, {7876, 16990467},
1159
  {7877, 1}, {7878, 16990723}, {7879, 1}, {7880, 16990979},
1160
  {7881, 1}, {7882, 16991235}, {7883, 1}, {7884, 16991491},
1161
  {7885, 1}, {7886, 16991747}, {7887, 1}, {7888, 16992003},
1162
  {7889, 1}, {7890, 16992259}, {7891, 1}, {7892, 16992515},
1163
  {7893, 1}, {7894, 16992771}, {7895, 1}, {7896, 16993027},
1164
  {7897, 1}, {7898, 16993283}, {7899, 1}, {7900, 16993539},
1165
  {7901, 1}, {7902, 16993795}, {7903, 1}, {7904, 16994051},
1166
  {7905, 1}, {7906, 16994307}, {7907, 1}, {7908, 16994563},
1167
  {7909, 1}, {7910, 16994819}, {7911, 1}, {7912, 16995075},
1168
  {7913, 1}, {7914, 16995331}, {7915, 1}, {7916, 16995587},
1169
  {7917, 1}, {7918, 16995843}, {7919, 1}, {7920, 16996099},
1170
  {7921, 1}, {7922, 16996355}, {7923, 1}, {7924, 16996611},
1171
  {7925, 1}, {7926, 16996867}, {7927, 1}, {7928, 16997123},
1172
  {7929, 1}, {7930, 16997379}, {7931, 1}, {7932, 16997635},
1173
  {7933, 1}, {7934, 16997891}, {7935, 1}, {7944, 16998147},
1174
  {7945, 16998403}, {7946, 16998659}, {7947, 16998915}, {7948, 16999171},
1175
  {7949, 16999427}, {7950, 16999683}, {7951, 16999939}, {7952, 1},
1176
  {7958, 2}, {7960, 17000195}, {7961, 17000451}, {7962, 17000707},
1177
  {7963, 17000963}, {7964, 17001219}, {7965, 17001475}, {7966, 2},
1178
  {7968, 1}, {7976, 17001731}, {7977, 17001987}, {7978, 17002243},
1179
  {7979, 17002499}, {7980, 17002755}, {7981, 17003011}, {7982, 17003267},
1180
  {7983, 17003523}, {7984, 1}, {7992, 17003779}, {7993, 17004035},
1181
  {7994, 17004291}, {7995, 17004547}, {7996, 17004803}, {7997, 17005059},
1182
  {7998, 17005315}, {7999, 17005571}, {8000, 1}, {8006, 2},
1183
  {8008, 17005827}, {8009, 17006083}, {8010, 17006339}, {8011, 17006595},
1184
  {8012, 17006851}, {8013, 17007107}, {8014, 2}, {8016, 1},
1185
  {8024, 2}, {8025, 17007363}, {8026, 2}, {8027, 17007619},
1186
  {8028, 2}, {8029, 17007875}, {8030, 2}, {8031, 17008131},
1187
  {8032, 1}, {8040, 17008387}, {8041, 17008643}, {8042, 17008899},
1188
  {8043, 17009155}, {8044, 17009411}, {8045, 17009667}, {8046, 17009923},
1189
  {8047, 17010179}, {8048, 1}, {8049, 16849923}, {8050, 1},
1190
  {8051, 16850179}, {8052, 1}, {8053, 16850435}, {8054, 1},
1191
  {8055, 16850691}, {8056, 1}, {8057, 16850947}, {8058, 1},
1192
  {8059, 16851203}, {8060, 1}, {8061, 16851459}, {8062, 2},
1193
  {8064, 33787651}, {8065, 33788163}, {8066, 33788675}, {8067, 33789187},
1194
  {8068, 33789699}, {8069, 33790211}, {8070, 33790723}, {8071, 33791235},
1195
  {8072, 33787651}, {8073, 33788163}, {8074, 33788675}, {8075, 33789187},
1196
  {8076, 33789699}, {8077, 33790211}, {8078, 33790723}, {8079, 33791235},
1197
  {8080, 33791747}, {8081, 33792259}, {8082, 33792771}, {8083, 33793283},
1198
  {8084, 33793795}, {8085, 33794307}, {8086, 33794819}, {8087, 33795331},
1199
  {8088, 33791747}, {8089, 33792259}, {8090, 33792771}, {8091, 33793283},
1200
  {8092, 33793795}, {8093, 33794307}, {8094, 33794819}, {8095, 33795331},
1201
  {8096, 33795843}, {8097, 33796355}, {8098, 33796867}, {8099, 33797379},
1202
  {8100, 33797891}, {8101, 33798403}, {8102, 33798915}, {8103, 33799427},
1203
  {8104, 33795843}, {8105, 33796355}, {8106, 33796867}, {8107, 33797379},
1204
  {8108, 33797891}, {8109, 33798403}, {8110, 33798915}, {8111, 33799427},
1205
  {8112, 1}, {8114, 33799939}, {8115, 33800451}, {8116, 33800963},
1206
  {8117, 2}, {8118, 1}, {8119, 33801475}, {8120, 17024771},
1207
  {8121, 17025027}, {8122, 17022723}, {8123, 16849923}, {8124, 33800451},
1208
  {8125, 33802499}, {8126, 16846851}, {8127, 33802499}, {8128, 33803011},
1209
  {8129, 50580739}, {8130, 33804291}, {8131, 33804803}, {8132, 33805315},
1210
  {8133, 2}, {8134, 1}, {8135, 33805827}, {8136, 17029123},
1211
  {8137, 16850179}, {8138, 17027075}, {8139, 16850435}, {8140, 33804803},
1212
  {8141, 50583811}, {8142, 50584579}, {8143, 50585347}, {8144, 1},
1213
  {8147, 17031683}, {8148, 2}, {8150, 1}, {8152, 17031939},
1214
  {8153, 17032195}, {8154, 17032451}, {8155, 16850691}, {8156, 2},
1215
  {8157, 50587139}, {8158, 50587907}, {8159, 50588675}, {8160, 1},
1216
  {8163, 17035011}, {8164, 1}, {8168, 17035267}, {8169, 17035523},
1217
  {8170, 17035779}, {8171, 16851203}, {8172, 17036035}, {8173, 50590723},
1218
  {8174, 50403587}, {8175, 17037059}, {8176, 2}, {8178, 33814531},
1219
  {8179, 33815043}, {8180, 33815555}, {8181, 2}, {8182, 1},
1220
  {8183, 33816067}, {8184, 17039363}, {8185, 16850947}, {8186, 17037315},
1221
  {8187, 16851459}, {8188, 33815043}, {8189, 33562883}, {8190, 33809923},
1222
  {8191, 2}, {8192, 16783875}, {8203, 0}, {8204, 1},
1223
  {8206, 2}, {8208, 1}, {8209, 17039619}, {8210, 1},
1224
  {8215, 33817091}, {8216, 1}, {8228, 2}, {8231, 1},
1225
  {8232, 2}, {8239, 16783875}, {8240, 1}, {8243, 33817603},
1226
  {8244, 50595331}, {8245, 1}, {8246, 33818883}, {8247, 50596611},
1227
  {8248, 1}, {8252, 33820163}, {8253, 1}, {8254, 33820675},
1228
  {8255, 1}, {8263, 33821187}, {8264, 33821699}, {8265, 33822211},
1229
  {8266, 1}, {8279, 67372035}, {8280, 1}, {8287, 16783875},
1230
  {8288, 0}, {8293, 2}, {8298, 0}, {8304, 17045507},
1231
  {8305, 16779267}, {8306, 2}, {8308, 16787715}, {8309, 17045763},
1232
  {8310, 17046019}, {8311, 17046275}, {8312, 17046531}, {8313, 17046787},
1233
  {8314, 17047043}, {8315, 17047299}, {8316, 17047555}, {8317, 17047811},
1234
  {8318, 17048067}, {8319, 16780547}, {8320, 17045507}, {8321, 16786947},
1235
  {8322, 16785155}, {8323, 16785411}, {8324, 16787715}, {8325, 17045763},
1236
  {8326, 17046019}, {8327, 17046275}, {8328, 17046531}, {8329, 17046787},
1237
  {8330, 17047043}, {8331, 17047299}, {8332, 17047555}, {8333, 17047811},
1238
  {8334, 17048067}, {8335, 2}, {8336, 16777219}, {8337, 16778243},
1239
  {8338, 16780803}, {8339, 16783107}, {8340, 16816387}, {8341, 16779011},
1240
  {8342, 16779779}, {8343, 16780035}, {8344, 16780291}, {8345, 16780547},
1241
  {8346, 16781059}, {8347, 16781827}, {8348, 16782083}, {8349, 2},
1242
  {8352, 1}, {8360, 33558787}, {8361, 1}, {8385, 2},
1243
  {8400, 1}, {8433, 2}, {8448, 50602755}, {8449, 50603523},
1244
  {8450, 16777731}, {8451, 33827075}, {8452, 1}, {8453, 50604803},
1245
  {8454, 50605571}, {8455, 16816643}, {8456, 1}, {8457, 33829123},
1246
  {8458, 16778755}, {8459, 16779011}, {8463, 16802051}, {8464, 16779267},
1247
  {8466, 16780035}, {8468, 1}, {8469, 16780547}, {8470, 33557763},
1248
  {8471, 1}, {8473, 16781059}, {8474, 16781315}, {8475, 16781571},
1249
  {8478, 1}, {8480, 33829635}, {8481, 50607363}, {8482, 33830915},
1250
  {8483, 1}, {8484, 16783619}, {8485, 1}, {8486, 16857091},
1251
  {8487, 1}, {8488, 16783619}, {8489, 1}, {8490, 16779779},
1252
  {8491, 16790787}, {8492, 16777475}, {8493, 16777731}, {8494, 1},
1253
  {8495, 16778243}, {8497, 16778499}, {8498, 17054211}, {8499, 16780291},
1254
  {8500, 16780803}, {8501, 17054467}, {8502, 17054723}, {8503, 17054979},
1255
  {8504, 17055235}, {8505, 16779267}, {8506, 1}, {8507, 50609923},
1256
  {8508, 16855043}, {8509, 16852227}, {8511, 16855043}, {8512, 17056259},
1257
  {8513, 1}, {8517, 16777987}, {8519, 16778243}, {8520, 16779267},
1258
  {8521, 16779523}, {8522, 1}, {8528, 50610947}, {8529, 50611715},
1259
  {8530, 67389699}, {8531, 50613507}, {8532, 50614275}, {8533, 50615043},
1260
  {8534, 50615811}, {8535, 50616579}, {8536, 50617347}, {8537, 50618115},
1261
  {8538, 50618883}, {8539, 50619651}, {8540, 50620419}, {8541, 50621187},
1262
  {8542, 50621955}, {8543, 33564419}, {8544, 16779267}, {8545, 33845507},
1263
  {8546, 50623235}, {8547, 33846787}, {8548, 16782595}, {8549, 33847299},
1264
  {8550, 50625027}, {8551, 67403011}, {8552, 33849603}, {8553, 16783107},
1265
  {8554, 33850115}, {8555, 50627843}, {8556, 16780035}, {8557, 16777731},
1266
  {8558, 16777987}, {8559, 16780291}, {8560, 16779267}, {8561, 33845507},
1267
  {8562, 50622723}, {8563, 33846787}, {8564, 16782595}, {8565, 33847299},
1268
  {8566, 50625027}, {8567, 67403011}, {8568, 33849603}, {8569, 16783107},
1269
  {8570, 33850115}, {8571, 50627843}, {8572, 16780035}, {8573, 16777731},
1270
  {8574, 16777987}, {8575, 16780291}, {8576, 1}, {8579, 17074179},
1271
  {8580, 1}, {8585, 50628867}, {8586, 1}, {8588, 2},
1272
  {8592, 1}, {8748, 33852419}, {8749, 50630147}, {8750, 1},
1273
  {8751, 33853699}, {8752, 50631427}, {8753, 1}, {9001, 17077763},
1274
  {9002, 17078019}, {9003, 1}, {9258, 2}, {9280, 1},
1275
  {9291, 2}, {9312, 16786947}, {9313, 16785155}, {9314, 16785411},
1276
  {9315, 16787715}, {9316, 17045763}, {9317, 17046019}, {9318, 17046275},
1277
  {9319, 17046531}, {9320, 17046787}, {9321, 33835779}, {9322, 33564163},
1278
  {9323, 33855491}, {9324, 33856003}, {9325, 33856515}, {9326, 33857027},
1279
  {9327, 33857539}, {9328, 33858051}, {9329, 33858563}, {9330, 33859075},
1280
  {9331, 33859587}, {9332, 50637315}, {9333, 50638083}, {9334, 50638851},
1281
  {9335, 50639619}, {9336, 50640387}, {9337, 50641155}, {9338, 50641923},
1282
  {9339, 50642691}, {9340, 50643459}, {9341, 67421443}, {9342, 67422467},
1283
  {9343, 67423491}, {9344, 67424515}, {9345, 67425539}, {9346, 67426563},
1284
  {9347, 67427587}, {9348, 67428611}, {9349, 67429635}, {9350, 67430659},
1285
  {9351, 67431683}, {9352, 2}, {9372, 50655491}, {9373, 50656259},
1286
  {9374, 50657027}, {9375, 50657795}, {9376, 50658563}, {9377, 50659331},
1287
  {9378, 50660099}, {9379, 50660867}, {9380, 50661635}, {9381, 50662403},
1288
  {9382, 50663171}, {9383, 50663939}, {9384, 50664707}, {9385, 50665475},
1289
  {9386, 50666243}, {9387, 50667011}, {9388, 50667779}, {9389, 50668547},
1290
  {9390, 50669315}, {9391, 50670083}, {9392, 50670851}, {9393, 50671619},
1291
  {9394, 50672387}, {9395, 50673155}, {9396, 50673923}, {9397, 50674691},
1292
  {9398, 16777219}, {9399, 16777475}, {9400, 16777731}, {9401, 16777987},
1293
  {9402, 16778243}, {9403, 16778499}, {9404, 16778755}, {9405, 16779011},
1294
  {9406, 16779267}, {9407, 16779523}, {9408, 16779779}, {9409, 16780035},
1295
  {9410, 16780291}, {9411, 16780547}, {9412, 16780803}, {9413, 16781059},
1296
  {9414, 16781315}, {9415, 16781571}, {9416, 16781827}, {9417, 16782083},
1297
  {9418, 16782339}, {9419, 16782595}, {9420, 16782851}, {9421, 16783107},
1298
  {9422, 16783363}, {9423, 16783619}, {9424, 16777219}, {9425, 16777475},
1299
  {9426, 16777731}, {9427, 16777987}, {9428, 16778243}, {9429, 16778499},
1300
  {9430, 16778755}, {9431, 16779011}, {9432, 16779267}, {9433, 16779523},
1301
  {9434, 16779779}, {9435, 16780035}, {9436, 16780291}, {9437, 16780547},
1302
  {9438, 16780803}, {9439, 16781059}, {9440, 16781315}, {9441, 16781571},
1303
  {9442, 16781827}, {9443, 16782083}, {9444, 16782339}, {9445, 16782595},
1304
  {9446, 16782851}, {9447, 16783107}, {9448, 16783363}, {9449, 16783619},
1305
  {9450, 17045507}, {9451, 1}, {10764, 67406851}, {10765, 1},
1306
  {10868, 50675459}, {10869, 33899011}, {10870, 50675971}, {10871, 1},
1307
  {10972, 33899523}, {10973, 1}, {11124, 2}, {11126, 1},
1308
  {11158, 2}, {11159, 1}, {11264, 17122819}, {11265, 17123075},
1309
  {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099},
1310
  {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123},
1311
  {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147},
1312
  {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171},
1313
  {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195},
1314
  {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219},
1315
  {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243},
1316
  {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267},
1317
  {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291},
1318
  {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315},
1319
  {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339},
1320
  {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107},
1321
  {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875},
1322
  {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387},
1323
  {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723},
1324
  {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1},
1325
  {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1},
1326
  {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667},
1327
  {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1},
1328
  {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1},
1329
  {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1},
1330
  {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1},
1331
  {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1},
1332
  {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1},
1333
  {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1},
1334
  {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1},
1335
  {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1},
1336
  {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1},
1337
  {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1},
1338
  {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1},
1339
  {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1},
1340
  {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1},
1341
  {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1},
1342
  {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1},
1343
  {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1},
1344
  {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1},
1345
  {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1},
1346
  {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1},
1347
  {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1},
1348
  {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1},
1349
  {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1},
1350
  {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1},
1351
  {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1},
1352
  {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1},
1353
  {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1},
1354
  {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1},
1355
  {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491},
1356
  {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2},
1357
  {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2},
1358
  {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2},
1359
  {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2},
1360
  {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2},
1361
  {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2},
1362
  {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003},
1363
  {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771},
1364
  {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795},
1365
  {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819},
1366
  {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843},
1367
  {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867},
1368
  {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891},
1369
  {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915},
1370
  {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939},
1371
  {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963},
1372
  {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987},
1373
  {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011},
1374
  {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035},
1375
  {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059},
1376
  {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083},
1377
  {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107},
1378
  {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131},
1379
  {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155},
1380
  {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179},
1381
  {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203},
1382
  {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227},
1383
  {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251},
1384
  {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275},
1385
  {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299},
1386
  {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323},
1387
  {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347},
1388
  {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371},
1389
  {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395},
1390
  {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419},
1391
  {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443},
1392
  {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467},
1393
  {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491},
1394
  {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515},
1395
  {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539},
1396
  {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563},
1397
  {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587},
1398
  {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611},
1399
  {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635},
1400
  {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659},
1401
  {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683},
1402
  {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707},
1403
  {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731},
1404
  {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755},
1405
  {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779},
1406
  {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803},
1407
  {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827},
1408
  {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851},
1409
  {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875},
1410
  {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899},
1411
  {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923},
1412
  {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947},
1413
  {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971},
1414
  {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995},
1415
  {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019},
1416
  {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2},
1417
  {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1},
1418
  {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555},
1419
  {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1},
1420
  {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795},
1421
  {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819},
1422
  {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115},
1423
  {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139},
1424
  {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163},
1425
  {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187},
1426
  {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211},
1427
  {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235},
1428
  {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259},
1429
  {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283},
1430
  {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307},
1431
  {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331},
1432
  {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355},
1433
  {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379},
1434
  {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403},
1435
  {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171},
1436
  {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195},
1437
  {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219},
1438
  {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243},
1439
  {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267},
1440
  {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291},
1441
  {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315},
1442
  {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339},
1443
  {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363},
1444
  {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387},
1445
  {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411},
1446
  {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259},
1447
  {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435},
1448
  {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283},
1449
  {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227},
1450
  {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1},
1451
  {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219},
1452
  {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291},
1453
  {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363},
1454
  {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435},
1455
  {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507},
1456
  {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579},
1457
  {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651},
1458
  {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2},
1459
  {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539},
1460
  {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611},
1461
  {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683},
1462
  {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755},
1463
  {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827},
1464
  {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899},
1465
  {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971},
1466
  {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043},
1467
  {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115},
1468
  {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963},
1469
  {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203},
1470
  {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739},
1471
  {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787},
1472
  {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811},
1473
  {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651},
1474
  {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235},
1475
  {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771},
1476
  {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491},
1477
  {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563},
1478
  {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635},
1479
  {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707},
1480
  {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643},
1481
  {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923},
1482
  {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667},
1483
  {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947},
1484
  {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755},
1485
  {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883},
1486
  {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955},
1487
  {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155},
1488
  {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923},
1489
  {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691},
1490
  {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947},
1491
  {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971},
1492
  {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099},
1493
  {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211},
1494
  {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931},
1495
  {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771},
1496
  {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819},
1497
  {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867},
1498
  {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915},
1499
  {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435},
1500
  {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035},
1501
  {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611},
1502
  {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635},
1503
  {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403},
1504
  {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427},
1505
  {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451},
1506
  {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219},
1507
  {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243},
1508
  {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267},
1509
  {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291},
1510
  {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315},
1511
  {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339},
1512
  {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363},
1513
  {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827},
1514
  {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195},
1515
  {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035},
1516
  {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619},
1517
  {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651},
1518
  {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923},
1519
  {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803},
1520
  {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211},
1521
  {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307},
1522
  {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907},
1523
  {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915},
1524
  {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187},
1525
  {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259},
1526
  {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611},
1527
  {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507},
1528
  {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835},
1529
  {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651},
1530
  {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979},
1531
  {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995},
1532
  {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379},
1533
  {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491},
1534
  {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955},
1535
  {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611},
1536
  {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659},
1537
  {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923},
1538
  {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995},
1539
  {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067},
1540
  {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139},
1541
  {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995},
1542
  {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299},
1543
  {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859},
1544
  {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907},
1545
  {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955},
1546
  {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003},
1547
  {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819},
1548
  {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867},
1549
  {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387},
1550
  {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219},
1551
  {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755},
1552
  {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803},
1553
  {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067},
1554
  {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371},
1555
  {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931},
1556
  {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435},
1557
  {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627},
1558
  {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675},
1559
  {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211},
1560
  {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259},
1561
  {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2},
1562
  {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739},
1563
  {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355},
1564
  {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803},
1565
  {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131},
1566
  {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179},
1567
  {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011},
1568
  {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763},
1569
  {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107},
1570
  {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155},
1571
  {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675},
1572
  {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747},
1573
  {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819},
1574
  {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891},
1575
  {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963},
1576
  {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035},
1577
  {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1},
1578
  {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139},
1579
  {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651},
1580
  {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163},
1581
  {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419},
1582
  {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931},
1583
  {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443},
1584
  {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955},
1585
  {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467},
1586
  {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979},
1587
  {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491},
1588
  {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003},
1589
  {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515},
1590
  {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027},
1591
  {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539},
1592
  {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051},
1593
  {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563},
1594
  {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075},
1595
  {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587},
1596
  {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099},
1597
  {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1},
1598
  {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1},
1599
  {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1},
1600
  {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1},
1601
  {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1},
1602
  {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1},
1603
  {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1},
1604
  {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1},
1605
  {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1},
1606
  {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1},
1607
  {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1},
1608
  {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1},
1609
  {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1},
1610
  {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1},
1611
  {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1},
1612
  {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1},
1613
  {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1},
1614
  {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1},
1615
  {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1},
1616
  {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1},
1617
  {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1},
1618
  {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1},
1619
  {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107},
1620
  {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619},
1621
  {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131},
1622
  {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387},
1623
  {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899},
1624
  {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411},
1625
  {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923},
1626
  {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435},
1627
  {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947},
1628
  {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475},
1629
  {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795},
1630
  {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307},
1631
  {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739},
1632
  {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251},
1633
  {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763},
1634
  {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275},
1635
  {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787},
1636
  {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1},
1637
  {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 2},
1638
  {42960, 17528067}, {42961, 1}, {42962, 2}, {42963, 1},
1639
  {42964, 2}, {42965, 1}, {42966, 17528323}, {42967, 1},
1640
  {42968, 17528579}, {42969, 1}, {42970, 17528835}, {42971, 1},
1641
  {42972, 17529091}, {42973, 2}, {42994, 16777731}, {42995, 16778499},
1642
  {42996, 16781315}, {42997, 17529347}, {42998, 1}, {43000, 16802051},
1643
  {43001, 16808195}, {43002, 1}, {43053, 2}, {43056, 1},
1644
  {43066, 2}, {43072, 1}, {43128, 2}, {43136, 1},
1645
  {43206, 2}, {43214, 1}, {43226, 2}, {43232, 1},
1646
  {43348, 2}, {43359, 1}, {43389, 2}, {43392, 1},
1647
  {43470, 2}, {43471, 1}, {43482, 2}, {43486, 1},
1648
  {43519, 2}, {43520, 1}, {43575, 2}, {43584, 1},
1649
  {43598, 2}, {43600, 1}, {43610, 2}, {43612, 1},
1650
  {43715, 2}, {43739, 1}, {43767, 2}, {43777, 1},
1651
  {43783, 2}, {43785, 1}, {43791, 2}, {43793, 1},
1652
  {43799, 2}, {43808, 1}, {43815, 2}, {43816, 1},
1653
  {43823, 2}, {43824, 1}, {43868, 17508867}, {43869, 17529603},
1654
  {43870, 17135363}, {43871, 17529859}, {43872, 1}, {43881, 17530115},
1655
  {43882, 1}, {43884, 2}, {43888, 17530371}, {43889, 17530627},
1656
  {43890, 17530883}, {43891, 17531139}, {43892, 17531395}, {43893, 17531651},
1657
  {43894, 17531907}, {43895, 17532163}, {43896, 17532419}, {43897, 17532675},
1658
  {43898, 17532931}, {43899, 17533187}, {43900, 17533443}, {43901, 17533699},
1659
  {43902, 17533955}, {43903, 17534211}, {43904, 17534467}, {43905, 17534723},
1660
  {43906, 17534979}, {43907, 17535235}, {43908, 17535491}, {43909, 17535747},
1661
  {43910, 17536003}, {43911, 17536259}, {43912, 17536515}, {43913, 17536771},
1662
  {43914, 17537027}, {43915, 17537283}, {43916, 17537539}, {43917, 17537795},
1663
  {43918, 17538051}, {43919, 17538307}, {43920, 17538563}, {43921, 17538819},
1664
  {43922, 17539075}, {43923, 17539331}, {43924, 17539587}, {43925, 17539843},
1665
  {43926, 17540099}, {43927, 17540355}, {43928, 17540611}, {43929, 17540867},
1666
  {43930, 17541123}, {43931, 17541379}, {43932, 17541635}, {43933, 17541891},
1667
  {43934, 17542147}, {43935, 17542403}, {43936, 17542659}, {43937, 17542915},
1668
  {43938, 17543171}, {43939, 17543427}, {43940, 17543683}, {43941, 17543939},
1669
  {43942, 17544195}, {43943, 17544451}, {43944, 17544707}, {43945, 17544963},
1670
  {43946, 17545219}, {43947, 17545475}, {43948, 17545731}, {43949, 17545987},
1671
  {43950, 17546243}, {43951, 17546499}, {43952, 17546755}, {43953, 17547011},
1672
  {43954, 17547267}, {43955, 17547523}, {43956, 17547779}, {43957, 17548035},
1673
  {43958, 17548291}, {43959, 17548547}, {43960, 17548803}, {43961, 17549059},
1674
  {43962, 17549315}, {43963, 17549571}, {43964, 17549827}, {43965, 17550083},
1675
  {43966, 17550339}, {43967, 17550595}, {43968, 1}, {44014, 2},
1676
  {44016, 1}, {44026, 2}, {44032, 1}, {55204, 2},
1677
  {55216, 1}, {55239, 2}, {55243, 1}, {55292, 2},
1678
  {63744, 17550851}, {63745, 17551107}, {63746, 17192707}, {63747, 17551363},
1679
  {63748, 17551619}, {63749, 17551875}, {63750, 17552131}, {63751, 17206531},
1680
  {63753, 17552387}, {63754, 17194755}, {63755, 17552643}, {63756, 17552899},
1681
  {63757, 17553155}, {63758, 17553411}, {63759, 17553667}, {63760, 17553923},
1682
  {63761, 17554179}, {63762, 17554435}, {63763, 17554691}, {63764, 17554947},
1683
  {63765, 17555203}, {63766, 17555459}, {63767, 17555715}, {63768, 17555971},
1684
  {63769, 17556227}, {63770, 17556483}, {63771, 17556739}, {63772, 17556995},
1685
  {63773, 17557251}, {63774, 17557507}, {63775, 17557763}, {63776, 17558019},
1686
  {63777, 17558275}, {63778, 17558531}, {63779, 17558787}, {63780, 17559043},
1687
  {63781, 17559299}, {63782, 17559555}, {63783, 17559811}, {63784, 17560067},
1688
  {63785, 17560323}, {63786, 17560579}, {63787, 17560835}, {63788, 17561091},
1689
  {63789, 17561347}, {63790, 17561603}, {63791, 17561859}, {63792, 17562115},
1690
  {63793, 17562371}, {63794, 17562627}, {63795, 17562883}, {63796, 17184003},
1691
  {63797, 17563139}, {63798, 17563395}, {63799, 17563651}, {63800, 17563907},
1692
  {63801, 17564163}, {63802, 17564419}, {63803, 17564675}, {63804, 17564931},
1693
  {63805, 17565187}, {63806, 17565443}, {63807, 17565699}, {63808, 17202691},
1694
  {63809, 17565955}, {63810, 17566211}, {63811, 17566467}, {63812, 17566723},
1695
  {63813, 17566979}, {63814, 17567235}, {63815, 17567491}, {63816, 17567747},
1696
  {63817, 17568003}, {63818, 17568259}, {63819, 17568515}, {63820, 17568771},
1697
  {63821, 17569027}, {63822, 17569283}, {63823, 17569539}, {63824, 17569795},
1698
  {63825, 17570051}, {63826, 17570307}, {63827, 17570563}, {63828, 17570819},
1699
  {63829, 17571075}, {63830, 17571331}, {63831, 17571587}, {63832, 17571843},
1700
  {63833, 17572099}, {63834, 17572355}, {63835, 17572611}, {63836, 17554947},
1701
  {63837, 17572867}, {63838, 17573123}, {63839, 17573379}, {63840, 17573635},
1702
  {63841, 17573891}, {63842, 17574147}, {63843, 17574403}, {63844, 17574659},
1703
  {63845, 17574915}, {63846, 17575171}, {63847, 17575427}, {63848, 17575683},
1704
  {63849, 17575939}, {63850, 17576195}, {63851, 17576451}, {63852, 17576707},
1705
  {63853, 17576963}, {63854, 17577219}, {63855, 17577475}, {63856, 17577731},
1706
  {63857, 17193219}, {63858, 17577987}, {63859, 17578243}, {63860, 17578499},
1707
  {63861, 17578755}, {63862, 17579011}, {63863, 17579267}, {63864, 17579523},
1708
  {63865, 17579779}, {63866, 17580035}, {63867, 17580291}, {63868, 17580547},
1709
  {63869, 17580803}, {63870, 17581059}, {63871, 17581315}, {63872, 17581571},
1710
  {63873, 17161731}, {63874, 17581827}, {63875, 17582083}, {63876, 17582339},
1711
  {63877, 17582595}, {63878, 17582851}, {63879, 17583107}, {63880, 17583363},
1712
  {63881, 17583619}, {63882, 17156867}, {63883, 17583875}, {63884, 17584131},
1713
  {63885, 17584387}, {63886, 17584643}, {63887, 17584899}, {63888, 17585155},
1714
  {63889, 17585411}, {63890, 17585667}, {63891, 17585923}, {63892, 17586179},
1715
  {63893, 17586435}, {63894, 17586691}, {63895, 17586947}, {63896, 17587203},
1716
  {63897, 17587459}, {63898, 17587715}, {63899, 17587971}, {63900, 17588227},
1717
  {63901, 17588483}, {63902, 17588739}, {63903, 17588995}, {63904, 17589251},
1718
  {63905, 17577475}, {63906, 17589507}, {63907, 17589763}, {63908, 17590019},
1719
  {63909, 17590275}, {63910, 17590531}, {63911, 17590787}, {63912, 17327619},
1720
  {63913, 17591043}, {63914, 17573379}, {63915, 17591299}, {63916, 17591555},
1721
  {63917, 17591811}, {63918, 17592067}, {63919, 17592323}, {63920, 17592579},
1722
  {63921, 17592835}, {63922, 17593091}, {63923, 17593347}, {63924, 17593603},
1723
  {63925, 17593859}, {63926, 17594115}, {63927, 17594371}, {63928, 17594627},
1724
  {63929, 17594883}, {63930, 17595139}, {63931, 17595395}, {63932, 17595651},
1725
  {63933, 17595907}, {63934, 17596163}, {63935, 17554947}, {63936, 17596419},
1726
  {63937, 17596675}, {63938, 17596931}, {63939, 17597187}, {63940, 17206275},
1727
  {63941, 17597443}, {63942, 17597699}, {63943, 17597955}, {63944, 17598211},
1728
  {63945, 17598467}, {63946, 17598723}, {63947, 17598979}, {63948, 17599235},
1729
  {63949, 17599491}, {63950, 17599747}, {63951, 17600003}, {63952, 17600259},
1730
  {63953, 17264899}, {63954, 17600515}, {63955, 17600771}, {63956, 17601027},
1731
  {63957, 17601283}, {63958, 17601539}, {63959, 17601795}, {63960, 17602051},
1732
  {63961, 17602307}, {63962, 17602563}, {63963, 17573891}, {63964, 17602819},
1733
  {63965, 17603075}, {63966, 17603331}, {63967, 17603587}, {63968, 17603843},
1734
  {63969, 17604099}, {63970, 17604355}, {63971, 17604611}, {63972, 17604867},
1735
  {63973, 17605123}, {63974, 17605379}, {63975, 17605635}, {63976, 17605891},
1736
  {63977, 17194499}, {63978, 17606147}, {63979, 17606403}, {63980, 17606659},
1737
  {63981, 17606915}, {63982, 17607171}, {63983, 17607427}, {63984, 17607683},
1738
  {63985, 17607939}, {63986, 17608195}, {63987, 17608451}, {63988, 17608707},
1739
  {63989, 17608963}, {63990, 17609219}, {63991, 17181955}, {63992, 17609475},
1740
  {63993, 17609731}, {63994, 17609987}, {63995, 17610243}, {63996, 17610499},
1741
  {63997, 17610755}, {63998, 17611011}, {63999, 17611267}, {64000, 17611523},
1742
  {64001, 17611779}, {64002, 17612035}, {64003, 17612291}, {64004, 17612547},
1743
  {64005, 17612803}, {64006, 17613059}, {64007, 17613315}, {64008, 17188867},
1744
  {64009, 17613571}, {64010, 17189635}, {64011, 17613827}, {64012, 17614083},
1745
  {64013, 17614339}, {64014, 1}, {64016, 17614595}, {64017, 1},
1746
  {64018, 17614851}, {64019, 1}, {64021, 17615107}, {64022, 17615363},
1747
  {64023, 17615619}, {64024, 17615875}, {64025, 17616131}, {64026, 17616387},
1748
  {64027, 17616643}, {64028, 17616899}, {64029, 17617155}, {64030, 17183747},
1749
  {64031, 1}, {64032, 17617411}, {64033, 1}, {64034, 17617667},
1750
  {64035, 1}, {64037, 17617923}, {64038, 17618179}, {64039, 1},
1751
  {64042, 17618435}, {64043, 17618691}, {64044, 17618947}, {64045, 17619203},
1752
  {64046, 17619459}, {64047, 17619715}, {64048, 17619971}, {64049, 17620227},
1753
  {64050, 17620483}, {64051, 17620739}, {64052, 17620995}, {64053, 17621251},
1754
  {64054, 17621507}, {64055, 17621763}, {64056, 17622019}, {64057, 17622275},
1755
  {64058, 17622531}, {64059, 17622787}, {64060, 17163523}, {64061, 17623043},
1756
  {64062, 17623299}, {64063, 17623555}, {64064, 17623811}, {64065, 17624067},
1757
  {64066, 17624323}, {64067, 17624579}, {64068, 17624835}, {64069, 17625091},
1758
  {64070, 17625347}, {64071, 17625603}, {64072, 17625859}, {64073, 17626115},
1759
  {64074, 17626371}, {64075, 17626627}, {64076, 17275651}, {64077, 17626883},
1760
  {64078, 17627139}, {64079, 17627395}, {64080, 17627651}, {64081, 17278723},
1761
  {64082, 17627907}, {64083, 17628163}, {64084, 17628419}, {64085, 17628675},
1762
  {64086, 17628931}, {64087, 17586691}, {64088, 17629187}, {64089, 17629443},
1763
  {64090, 17629699}, {64091, 17629955}, {64092, 17630211}, {64093, 17630467},
1764
  {64095, 17630723}, {64096, 17630979}, {64097, 17631235}, {64098, 17631491},
1765
  {64099, 17631747}, {64100, 17632003}, {64101, 17632259}, {64102, 17632515},
1766
  {64103, 17617923}, {64104, 17632771}, {64105, 17633027}, {64106, 17633283},
1767
  {64107, 17633539}, {64108, 17633795}, {64109, 17634051}, {64110, 2},
1768
  {64112, 17634307}, {64113, 17634563}, {64114, 17634819}, {64115, 17635075},
1769
  {64116, 17635331}, {64117, 17635587}, {64118, 17635843}, {64119, 17636099},
1770
  {64120, 17621507}, {64121, 17636355}, {64122, 17636611}, {64123, 17636867},
1771
  {64124, 17614595}, {64125, 17637123}, {64126, 17637379}, {64127, 17637635},
1772
  {64128, 17637891}, {64129, 17638147}, {64130, 17638403}, {64131, 17638659},
1773
  {64132, 17638915}, {64133, 17639171}, {64134, 17639427}, {64135, 17639683},
1774
  {64136, 17639939}, {64137, 17623555}, {64138, 17640195}, {64139, 17623811},
1775
  {64140, 17640451}, {64141, 17640707}, {64142, 17640963}, {64143, 17641219},
1776
  {64144, 17641475}, {64145, 17614851}, {64146, 17560323}, {64147, 17641731},
1777
  {64148, 17641987}, {64149, 17171971}, {64150, 17577731}, {64151, 17598723},
1778
  {64152, 17642243}, {64153, 17642499}, {64154, 17625603}, {64155, 17642755},
1779
  {64156, 17625859}, {64157, 17643011}, {64158, 17643267}, {64159, 17643523},
1780
  {64160, 17615363}, {64161, 17643779}, {64162, 17644035}, {64163, 17644291},
1781
  {64164, 17644547}, {64165, 17644803}, {64166, 17615619}, {64167, 17645059},
1782
  {64168, 17645315}, {64169, 17645571}, {64170, 17645827}, {64171, 17646083},
1783
  {64172, 17646339}, {64173, 17628931}, {64174, 17646595}, {64175, 17646851},
1784
  {64176, 17586691}, {64177, 17647107}, {64178, 17629955}, {64179, 17647363},
1785
  {64180, 17647619}, {64181, 17647875}, {64182, 17648131}, {64183, 17648387},
1786
  {64184, 17631235}, {64185, 17648643}, {64186, 17617667}, {64187, 17648899},
1787
  {64188, 17631491}, {64189, 17572867}, {64190, 17649155}, {64191, 17631747},
1788
  {64192, 17649411}, {64193, 17632259}, {64194, 17649667}, {64195, 17649923},
1789
  {64196, 17650179}, {64197, 17650435}, {64198, 17650691}, {64199, 17632771},
1790
  {64200, 17616899}, {64201, 17650947}, {64202, 17633027}, {64203, 17651203},
1791
  {64204, 17633283}, {64205, 17651459}, {64206, 17206531}, {64207, 17651715},
1792
  {64208, 17651971}, {64209, 17652227}, {64210, 17652483}, {64211, 17652739},
1793
  {64212, 17652995}, {64213, 17653251}, {64214, 17653507}, {64215, 17653763},
1794
  {64216, 17654019}, {64217, 17654275}, {64218, 2}, {64256, 34431747},
1795
  {64257, 34432259}, {64258, 34432771}, {64259, 51209219}, {64260, 51210499},
1796
  {64261, 33559043}, {64263, 2}, {64275, 34434051}, {64276, 34434563},
1797
  {64277, 34435075}, {64278, 34435587}, {64279, 34436099}, {64280, 2},
1798
  {64285, 34436611}, {64286, 1}, {64287, 34437123}, {64288, 17660419},
1799
  {64289, 17054467}, {64290, 17055235}, {64291, 17660675}, {64292, 17660931},
1800
  {64293, 17661187}, {64294, 17661443}, {64295, 17661699}, {64296, 17661955},
1801
  {64297, 17047043}, {64298, 34439427}, {64299, 34439939}, {64300, 51217667},
1802
  {64301, 51218435}, {64302, 34441987}, {64303, 34442499}, {64304, 34443011},
1803
  {64305, 34443523}, {64306, 34444035}, {64307, 34444547}, {64308, 34445059},
1804
  {64309, 34445571}, {64310, 34446083}, {64311, 2}, {64312, 34446595},
1805
  {64313, 34447107}, {64314, 34447619}, {64315, 34448131}, {64316, 34448643},
1806
  {64317, 2}, {64318, 34449155}, {64319, 2}, {64320, 34449667},
1807
  {64321, 34450179}, {64322, 2}, {64323, 34450691}, {64324, 34451203},
1808
  {64325, 2}, {64326, 34451715}, {64327, 34452227}, {64328, 34452739},
1809
  {64329, 34440451}, {64330, 34453251}, {64331, 34453763}, {64332, 34454275},
1810
  {64333, 34454787}, {64334, 34455299}, {64335, 34455811}, {64336, 17679107},
1811
  {64338, 17679363}, {64342, 17679619}, {64346, 17679875}, {64350, 17680131},
1812
  {64354, 17680387}, {64358, 17680643}, {64362, 17680899}, {64366, 17681155},
1813
  {64370, 17681411}, {64374, 17681667}, {64378, 17681923}, {64382, 17682179},
1814
  {64386, 17682435}, {64388, 17682691}, {64390, 17682947}, {64392, 17683203},
1815
  {64394, 17683459}, {64396, 17683715}, {64398, 17683971}, {64402, 17684227},
1816
  {64406, 17684483}, {64410, 17684739}, {64414, 17684995}, {64416, 17685251},
1817
  {64420, 17685507}, {64422, 17685763}, {64426, 17686019}, {64430, 17686275},
1818
  {64432, 17686531}, {64434, 1}, {64451, 2}, {64467, 17686787},
1819
  {64471, 16911619}, {64473, 17687043}, {64475, 17687299}, {64477, 33688835},
1820
  {64478, 17687555}, {64480, 17687811}, {64482, 17688067}, {64484, 17688323},
1821
  {64488, 17688579}, {64490, 34466051}, {64492, 34466563}, {64494, 34467075},
1822
  {64496, 34467587}, {64498, 34468099}, {64500, 34468611}, {64502, 34469123},
1823
  {64505, 34469635}, {64508, 17692931}, {64512, 34470403}, {64513, 34470915},
1824
  {64514, 34471427}, {64515, 34469635}, {64516, 34471939}, {64517, 34472451},
1825
  {64518, 34472963}, {64519, 34473475}, {64520, 34473987}, {64521, 34474499},
1826
  {64522, 34475011}, {64523, 34475523}, {64524, 34476035}, {64525, 34476547},
1827
  {64526, 34477059}, {64527, 34477571}, {64528, 34478083}, {64529, 34478595},
1828
  {64530, 34479107}, {64531, 34479619}, {64532, 34480131}, {64533, 34480643},
1829
  {64534, 34481155}, {64535, 34480899}, {64536, 34481667}, {64537, 34482179},
1830
  {64538, 34482691}, {64539, 34483203}, {64540, 34483715}, {64541, 34484227},
1831
  {64542, 34484739}, {64543, 34485251}, {64544, 34485763}, {64545, 34486275},
1832
  {64546, 34486787}, {64547, 34487299}, {64548, 34487811}, {64549, 34488323},
1833
  {64550, 34488835}, {64551, 34489347}, {64552, 34489859}, {64553, 34490371},
1834
  {64554, 34490883}, {64555, 34491395}, {64556, 34491907}, {64557, 34492419},
1835
  {64558, 34492931}, {64559, 34493443}, {64560, 34493955}, {64561, 34494467},
1836
  {64562, 34494979}, {64563, 34495491}, {64564, 34496003}, {64565, 34496515},
1837
  {64566, 34497027}, {64567, 34497539}, {64568, 34498051}, {64569, 34498563},
1838
  {64570, 34499075}, {64571, 34499587}, {64572, 34500099}, {64573, 34500611},
1839
  {64574, 34501123}, {64575, 34501635}, {64576, 34502147}, {64577, 34502659},
1840
  {64578, 34503171}, {64579, 34503683}, {64580, 34504195}, {64581, 34504707},
1841
  {64582, 34481411}, {64583, 34481923}, {64584, 34505219}, {64585, 34505731},
1842
  {64586, 34506243}, {64587, 34506755}, {64588, 34507267}, {64589, 34507779},
1843
  {64590, 34508291}, {64591, 34508803}, {64592, 34509315}, {64593, 34509827},
1844
  {64594, 34510339}, {64595, 34510851}, {64596, 34511363}, {64597, 34480387},
1845
  {64598, 34511875}, {64599, 34512387}, {64600, 34504451}, {64601, 34512899},
1846
  {64602, 34511619}, {64603, 34513411}, {64604, 34513923}, {64605, 34514435},
1847
  {64606, 51292163}, {64607, 51292931}, {64608, 51293699}, {64609, 51294467},
1848
  {64610, 51295235}, {64611, 51296003}, {64612, 34519555}, {64613, 34520067},
1849
  {64614, 34471427}, {64615, 34520579}, {64616, 34469635}, {64617, 34471939},
1850
  {64618, 34521091}, {64619, 34521603}, {64620, 34473987}, {64621, 34522115},
1851
  {64622, 34474499}, {64623, 34475011}, {64624, 34522627}, {64625, 34523139},
1852
  {64626, 34477059}, {64627, 34523651}, {64628, 34477571}, {64629, 34478083},
1853
  {64630, 34524163}, {64631, 34524675}, {64632, 34479107}, {64633, 34525187},
1854
  {64634, 34479619}, {64635, 34480131}, {64636, 34494467}, {64637, 34494979},
1855
  {64638, 34496515}, {64639, 34497027}, {64640, 34497539}, {64641, 34499587},
1856
  {64642, 34500099}, {64643, 34500611}, {64644, 34501123}, {64645, 34503171},
1857
  {64646, 34503683}, {64647, 34504195}, {64648, 34525699}, {64649, 34505219},
1858
  {64650, 34526211}, {64651, 34526723}, {64652, 34508291}, {64653, 34527235},
1859
  {64654, 34508803}, {64655, 34509315}, {64656, 34514435}, {64657, 34527747},
1860
  {64658, 34528259}, {64659, 34504451}, {64660, 34506499}, {64661, 34512899},
1861
  {64662, 34511619}, {64663, 34470403}, {64664, 34470915}, {64665, 34528771},
1862
  {64666, 34471427}, {64667, 34529283}, {64668, 34472451}, {64669, 34472963},
1863
  {64670, 34473475}, {64671, 34473987}, {64672, 34529795}, {64673, 34475523},
1864
  {64674, 34476035}, {64675, 34476547}, {64676, 34477059}, {64677, 34530307},
1865
  {64678, 34479107}, {64679, 34480643}, {64680, 34481155}, {64681, 34480899},
1866
  {64682, 34481667}, {64683, 34482179}, {64684, 34483203}, {64685, 34483715},
1867
  {64686, 34484227}, {64687, 34484739}, {64688, 34485251}, {64689, 34485763},
1868
  {64690, 34530819}, {64691, 34486275}, {64692, 34486787}, {64693, 34487299},
1869
  {64694, 34487811}, {64695, 34488323}, {64696, 34488835}, {64697, 34489859},
1870
  {64698, 34490371}, {64699, 34490883}, {64700, 34491395}, {64701, 34491907},
1871
  {64702, 34492419}, {64703, 34492931}, {64704, 34493443}, {64705, 34493955},
1872
  {64706, 34495491}, {64707, 34496003}, {64708, 34498051}, {64709, 34498563},
1873
  {64710, 34499075}, {64711, 34499587}, {64712, 34500099}, {64713, 34501635},
1874
  {64714, 34502147}, {64715, 34502659}, {64716, 34503171}, {64717, 34531331},
1875
  {64718, 34504707}, {64719, 34481411}, {64720, 34481923}, {64721, 34505219},
1876
  {64722, 34506755}, {64723, 34507267}, {64724, 34507779}, {64725, 34508291},
1877
  {64726, 34531843}, {64727, 34509827}, {64728, 34510339}, {64729, 34532355},
1878
  {64730, 34480387}, {64731, 34511875}, {64732, 34512387}, {64733, 34504451},
1879
  {64734, 34509571}, {64735, 34471427}, {64736, 34529283}, {64737, 34473987},
1880
  {64738, 34529795}, {64739, 34477059}, {64740, 34530307}, {64741, 34479107},
1881
  {64742, 34532867}, {64743, 34485251}, {64744, 34533379}, {64745, 34533891},
1882
  {64746, 34534403}, {64747, 34499587}, {64748, 34500099}, {64749, 34503171},
1883
  {64750, 34508291}, {64751, 34531843}, {64752, 34504451}, {64753, 34509571},
1884
  {64754, 51312131}, {64755, 51312899}, {64756, 51313667}, {64757, 34537219},
1885
  {64758, 34537731}, {64759, 34538243}, {64760, 34538755}, {64761, 34539267},
1886
  {64762, 34539779}, {64763, 34540291}, {64764, 34540803}, {64765, 34541315},
1887
  {64766, 34541827}, {64767, 34542339}, {64768, 34512131}, {64769, 34542851},
1888
  {64770, 34543363}, {64771, 34543875}, {64772, 34512643}, {64773, 34544387},
1889
  {64774, 34544899}, {64775, 34545411}, {64776, 34545923}, {64777, 34546435},
1890
  {64778, 34546947}, {64779, 34547459}, {64780, 34533891}, {64781, 34547971},
1891
  {64782, 34548483}, {64783, 34548995}, {64784, 34549507}, {64785, 34537219},
1892
  {64786, 34537731}, {64787, 34538243}, {64788, 34538755}, {64789, 34539267},
1893
  {64790, 34539779}, {64791, 34540291}, {64792, 34540803}, {64793, 34541315},
1894
  {64794, 34541827}, {64795, 34542339}, {64796, 34512131}, {64797, 34542851},
1895
  {64798, 34543363}, {64799, 34543875}, {64800, 34512643}, {64801, 34544387},
1896
  {64802, 34544899}, {64803, 34545411}, {64804, 34545923}, {64805, 34546435},
1897
  {64806, 34546947}, {64807, 34547459}, {64808, 34533891}, {64809, 34547971},
1898
  {64810, 34548483}, {64811, 34548995}, {64812, 34549507}, {64813, 34546435},
1899
  {64814, 34546947}, {64815, 34547459}, {64816, 34533891}, {64817, 34533379},
1900
  {64818, 34534403}, {64819, 34489347}, {64820, 34483715}, {64821, 34484227},
1901
  {64822, 34484739}, {64823, 34546435}, {64824, 34546947}, {64825, 34547459},
1902
  {64826, 34489347}, {64827, 34489859}, {64828, 34550019}, {64830, 1},
1903
  {64848, 51327747}, {64849, 51328515}, {64851, 51329283}, {64852, 51330051},
1904
  {64853, 51330819}, {64854, 51331587}, {64855, 51332355}, {64856, 51258371},
1905
  {64858, 51333123}, {64859, 51333891}, {64860, 51334659}, {64861, 51335427},
1906
  {64862, 51336195}, {64863, 51336963}, {64865, 51337731}, {64866, 51338499},
1907
  {64868, 51339267}, {64870, 51340035}, {64871, 51340803}, {64873, 51341571},
1908
  {64874, 51342339}, {64876, 51343107}, {64878, 51343875}, {64879, 51344643},
1909
  {64881, 51345411}, {64883, 51346179}, {64884, 51346947}, {64885, 51347715},
1910
  {64886, 51348483}, {64888, 51349251}, {64889, 51350019}, {64890, 51350787},
1911
  {64891, 51351555}, {64892, 51352323}, {64894, 51353091}, {64895, 51353859},
1912
  {64896, 51354627}, {64897, 51355395}, {64898, 51356163}, {64899, 51356931},
1913
  {64901, 51357699}, {64903, 51358467}, {64905, 51359235}, {64906, 51258627},
1914
  {64907, 51360003}, {64908, 51360771}, {64909, 51281923}, {64910, 51259139},
1915
  {64911, 51361539}, {64912, 2}, {64914, 51362307}, {64915, 51363075},
1916
  {64916, 51363843}, {64917, 51364611}, {64918, 51365379}, {64919, 51366147},
1917
  {64921, 51366915}, {64922, 51367683}, {64923, 51368451}, {64924, 51369219},
1918
  {64926, 51369987}, {64927, 51370755}, {64928, 51371523}, {64929, 51372291},
1919
  {64930, 51373059}, {64931, 51373827}, {64932, 51374595}, {64933, 51375363},
1920
  {64934, 51376131}, {64935, 51376899}, {64936, 51377667}, {64937, 51378435},
1921
  {64938, 51379203}, {64939, 51379971}, {64940, 51380739}, {64941, 51381507},
1922
  {64942, 51289091}, {64943, 51382275}, {64944, 51383043}, {64945, 51383811},
1923
  {64946, 51384579}, {64947, 51385347}, {64948, 51353091}, {64949, 51354627},
1924
  {64950, 51386115}, {64951, 51386883}, {64952, 51387651}, {64953, 51388419},
1925
  {64954, 51389187}, {64955, 51389955}, {64956, 51389187}, {64957, 51387651},
1926
  {64958, 51390723}, {64959, 51391491}, {64960, 51392259}, {64961, 51393027},
1927
  {64962, 51393795}, {64963, 51389955}, {64964, 51347715}, {64965, 51340035},
1928
  {64966, 51394563}, {64967, 51395331}, {64968, 2}, {64975, 1},
1929
  {64976, 2}, {65008, 51396099}, {65009, 51396867}, {65010, 68174851},
1930
  {65011, 68175875}, {65012, 68176899}, {65013, 68177923}, {65014, 68178947},
1931
  {65015, 68179971}, {65016, 68180995}, {65017, 51404803}, {65018, 303063811},
1932
  {65019, 135296259}, {65020, 68189443}, {65021, 1}, {65024, 0},
1933
  {65040, 17858819}, {65041, 17859075}, {65042, 2}, {65043, 17121027},
1934
  {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17859331},
1935
  {65048, 17859587}, {65049, 2}, {65056, 1}, {65072, 2},
1936
  {65073, 17859843}, {65074, 17860099}, {65075, 17860355}, {65077, 17047811},
1937
  {65078, 17048067}, {65079, 17860611}, {65080, 17860867}, {65081, 17861123},
1938
  {65082, 17861379}, {65083, 17861635}, {65084, 17861891}, {65085, 17862147},
1939
  {65086, 17862403}, {65087, 17077763}, {65088, 17078019}, {65089, 17862659},
1940
  {65090, 17862915}, {65091, 17863171}, {65092, 17863427}, {65093, 1},
1941
  {65095, 17863683}, {65096, 17863939}, {65097, 33820675}, {65101, 17860355},
1942
  {65104, 17858819}, {65105, 17859075}, {65106, 2}, {65108, 16848643},
1943
  {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17859843},
1944
  {65113, 17047811}, {65114, 17048067}, {65115, 17860611}, {65116, 17860867},
1945
  {65117, 17861123}, {65118, 17861379}, {65119, 17864195}, {65120, 17864451},
1946
  {65121, 17864707}, {65122, 17047043}, {65123, 17864963}, {65124, 17865219},
1947
  {65125, 17865475}, {65126, 17047555}, {65127, 2}, {65128, 17865731},
1948
  {65129, 17865987}, {65130, 17866243}, {65131, 17866499}, {65132, 2},
1949
  {65136, 34643971}, {65137, 34644483}, {65138, 34514947}, {65139, 1},
1950
  {65140, 34515715}, {65141, 2}, {65142, 34516483}, {65143, 34534915},
1951
  {65144, 34517251}, {65145, 34535683}, {65146, 34518019}, {65147, 34536451},
1952
  {65148, 34518787}, {65149, 34644995}, {65150, 34645507}, {65151, 34646019},
1953
  {65152, 17869315}, {65153, 17869571}, {65155, 17869827}, {65157, 17870083},
1954
  {65159, 17870339}, {65161, 17688835}, {65165, 16910595}, {65167, 17695235},
1955
  {65171, 17870595}, {65173, 17698307}, {65177, 17701379}, {65181, 17693443},
1956
  {65185, 17693955}, {65189, 17696515}, {65193, 17846019}, {65195, 17736195},
1957
  {65197, 17736707}, {65199, 17743107}, {65201, 17706499}, {65205, 17756675},
1958
  {65209, 17708547}, {65213, 17709571}, {65217, 17711619}, {65221, 17712643},
1959
  {65225, 17713155}, {65229, 17714179}, {65233, 17715203}, {65237, 17718275},
1960
  {65241, 17720323}, {65245, 17722627}, {65249, 17694467}, {65253, 17729539},
1961
  {65257, 17732611}, {65261, 16911107}, {65263, 17688579}, {65265, 16912131},
1962
  {65269, 34648067}, {65271, 34648579}, {65273, 34649091}, {65275, 34633987},
1963
  {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947},
1964
  {65282, 17872387}, {65283, 17864195}, {65284, 17865987}, {65285, 17866243},
1965
  {65286, 17864451}, {65287, 17872643}, {65288, 17047811}, {65289, 17048067},
1966
  {65290, 17864707}, {65291, 17047043}, {65292, 17858819}, {65293, 17864963},
1967
  {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947},
1968
  {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763},
1969
  {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787},
1970
  {65306, 17121027}, {65307, 16848643}, {65308, 17865219}, {65309, 17047555},
1971
  {65310, 17865475}, {65311, 17043971}, {65312, 17866499}, {65313, 16777219},
1972
  {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243},
1973
  {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267},
1974
  {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291},
1975
  {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315},
1976
  {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339},
1977
  {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363},
1978
  {65338, 16783619}, {65339, 17863683}, {65340, 17865731}, {65341, 17863939},
1979
  {65342, 17872899}, {65343, 17860355}, {65344, 17037059}, {65345, 16777219},
1980
  {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243},
1981
  {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267},
1982
  {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291},
1983
  {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315},
1984
  {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339},
1985
  {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363},
1986
  {65370, 16783619}, {65371, 17860611}, {65372, 17873155}, {65373, 17860867},
1987
  {65374, 17873411}, {65375, 17873667}, {65376, 17873923}, {65377, 17207043},
1988
  {65378, 17862659}, {65379, 17862915}, {65380, 17859075}, {65381, 17874179},
1989
  {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17874435},
1990
  {65386, 17374467}, {65387, 17334019}, {65388, 17874691}, {65389, 17344259},
1991
  {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099},
1992
  {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123},
1993
  {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147},
1994
  {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915},
1995
  {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939},
1996
  {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707},
1997
  {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731},
1998
  {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755},
1999
  {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779},
2000
  {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803},
2001
  {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827},
2002
  {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435},
2003
  {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115},
2004
  {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139},
2005
  {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163},
2006
  {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187},
2007
  {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211},
2008
  {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235},
2009
  {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259},
2010
  {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283},
2011
  {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051},
2012
  {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075},
2013
  {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843},
2014
  {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2},
2015
  {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635},
2016
  {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403},
2017
  {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17874947},
2018
  {65505, 17875203}, {65506, 17875459}, {65507, 33561859}, {65508, 17875715},
2019
  {65509, 17875971}, {65510, 17876227}, {65511, 2}, {65512, 17876483},
2020
  {65513, 17876739}, {65514, 17876995}, {65515, 17877251}, {65516, 17877507},
2021
  {65517, 17877763}, {65518, 17878019}, {65519, 2}, {65536, 1},
2022
  {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1},
2023
  {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1},
2024
  {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1},
2025
  {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1},
2026
  {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1},
2027
  {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1},
2028
  {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1},
2029
  {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1},
2030
  {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1},
2031
  {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1},
2032
  {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17878275},
2033
  {66561, 17878531}, {66562, 17878787}, {66563, 17879043}, {66564, 17879299},
2034
  {66565, 17879555}, {66566, 17879811}, {66567, 17880067}, {66568, 17880323},
2035
  {66569, 17880579}, {66570, 17880835}, {66571, 17881091}, {66572, 17881347},
2036
  {66573, 17881603}, {66574, 17881859}, {66575, 17882115}, {66576, 17882371},
2037
  {66577, 17882627}, {66578, 17882883}, {66579, 17883139}, {66580, 17883395},
2038
  {66581, 17883651}, {66582, 17883907}, {66583, 17884163}, {66584, 17884419},
2039
  {66585, 17884675}, {66586, 17884931}, {66587, 17885187}, {66588, 17885443},
2040
  {66589, 17885699}, {66590, 17885955}, {66591, 17886211}, {66592, 17886467},
2041
  {66593, 17886723}, {66594, 17886979}, {66595, 17887235}, {66596, 17887491},
2042
  {66597, 17887747}, {66598, 17888003}, {66599, 17888259}, {66600, 1},
2043
  {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17888515},
2044
  {66737, 17888771}, {66738, 17889027}, {66739, 17889283}, {66740, 17889539},
2045
  {66741, 17889795}, {66742, 17890051}, {66743, 17890307}, {66744, 17890563},
2046
  {66745, 17890819}, {66746, 17891075}, {66747, 17891331}, {66748, 17891587},
2047
  {66749, 17891843}, {66750, 17892099}, {66751, 17892355}, {66752, 17892611},
2048
  {66753, 17892867}, {66754, 17893123}, {66755, 17893379}, {66756, 17893635},
2049
  {66757, 17893891}, {66758, 17894147}, {66759, 17894403}, {66760, 17894659},
2050
  {66761, 17894915}, {66762, 17895171}, {66763, 17895427}, {66764, 17895683},
2051
  {66765, 17895939}, {66766, 17896195}, {66767, 17896451}, {66768, 17896707},
2052
  {66769, 17896963}, {66770, 17897219}, {66771, 17897475}, {66772, 2},
2053
  {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2},
2054
  {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17897731},
2055
  {66929, 17897987}, {66930, 17898243}, {66931, 17898499}, {66932, 17898755},
2056
  {66933, 17899011}, {66934, 17899267}, {66935, 17899523}, {66936, 17899779},
2057
  {66937, 17900035}, {66938, 17900291}, {66939, 2}, {66940, 17900547},
2058
  {66941, 17900803}, {66942, 17901059}, {66943, 17901315}, {66944, 17901571},
2059
  {66945, 17901827}, {66946, 17902083}, {66947, 17902339}, {66948, 17902595},
2060
  {66949, 17902851}, {66950, 17903107}, {66951, 17903363}, {66952, 17903619},
2061
  {66953, 17903875}, {66954, 17904131}, {66955, 2}, {66956, 17904387},
2062
  {66957, 17904643}, {66958, 17904899}, {66959, 17905155}, {66960, 17905411},
2063
  {66961, 17905667}, {66962, 17905923}, {66963, 2}, {66964, 17906179},
2064
  {66965, 17906435}, {66966, 2}, {66967, 1}, {66978, 2},
2065
  {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2},
2066
  {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2},
2067
  {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2},
2068
  {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17906691},
2069
  {67458, 17906947}, {67459, 16791043}, {67460, 17907203}, {67461, 16814083},
2070
  {67462, 2}, {67463, 17907459}, {67464, 17907715}, {67465, 17907971},
2071
  {67466, 17908227}, {67467, 16815363}, {67468, 16815619}, {67469, 17908483},
2072
  {67470, 17908739}, {67471, 17908995}, {67472, 17909251}, {67473, 17527555},
2073
  {67474, 17909507}, {67475, 16817155}, {67476, 17909763}, {67477, 16802051},
2074
  {67478, 17910019}, {67479, 17910275}, {67480, 17910531}, {67481, 17910787},
2075
  {67482, 17911043}, {67483, 17523459}, {67484, 17911299}, {67485, 17911555},
2076
  {67486, 17911811}, {67487, 17912067}, {67488, 17912323}, {67489, 17912579},
2077
  {67490, 16795395}, {67491, 17912835}, {67492, 17913091}, {67493, 16781315},
2078
  {67494, 17913347}, {67495, 17913603}, {67496, 17135875}, {67497, 17913859},
2079
  {67498, 16819971}, {67499, 17914115}, {67500, 17914371}, {67501, 17914627},
2080
  {67502, 17914883}, {67503, 16820995}, {67504, 17915139}, {67505, 2},
2081
  {67506, 17915395}, {67507, 17915651}, {67508, 17915907}, {67509, 17916163},
2082
  {67510, 17916419}, {67511, 17916675}, {67512, 17916931}, {67513, 17917187},
2083
  {67514, 17917443}, {67515, 2}, {67584, 1}, {67590, 2},
2084
  {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2},
2085
  {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2},
2086
  {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2},
2087
  {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2},
2088
  {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2},
2089
  {67871, 1}, {67898, 2}, {67903, 1}, {67904, 2},
2090
  {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2},
2091
  {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2},
2092
  {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2},
2093
  {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2},
2094
  {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2},
2095
  {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2},
2096
  {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2},
2097
  {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2},
2098
  {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2},
2099
  {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2},
2100
  {68736, 17917699}, {68737, 17917955}, {68738, 17918211}, {68739, 17918467},
2101
  {68740, 17918723}, {68741, 17918979}, {68742, 17919235}, {68743, 17919491},
2102
  {68744, 17919747}, {68745, 17920003}, {68746, 17920259}, {68747, 17920515},
2103
  {68748, 17920771}, {68749, 17921027}, {68750, 17921283}, {68751, 17921539},
2104
  {68752, 17921795}, {68753, 17922051}, {68754, 17922307}, {68755, 17922563},
2105
  {68756, 17922819}, {68757, 17923075}, {68758, 17923331}, {68759, 17923587},
2106
  {68760, 17923843}, {68761, 17924099}, {68762, 17924355}, {68763, 17924611},
2107
  {68764, 17924867}, {68765, 17925123}, {68766, 17925379}, {68767, 17925635},
2108
  {68768, 17925891}, {68769, 17926147}, {68770, 17926403}, {68771, 17926659},
2109
  {68772, 17926915}, {68773, 17927171}, {68774, 17927427}, {68775, 17927683},
2110
  {68776, 17927939}, {68777, 17928195}, {68778, 17928451}, {68779, 17928707},
2111
  {68780, 17928963}, {68781, 17929219}, {68782, 17929475}, {68783, 17929731},
2112
  {68784, 17929987}, {68785, 17930243}, {68786, 17930499}, {68787, 2},
2113
  {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2},
2114
  {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17930755},
2115
  {68945, 17931011}, {68946, 17931267}, {68947, 17931523}, {68948, 17931779},
2116
  {68949, 17932035}, {68950, 17932291}, {68951, 17932547}, {68952, 17932803},
2117
  {68953, 17933059}, {68954, 17933315}, {68955, 17933571}, {68956, 17933827},
2118
  {68957, 17934083}, {68958, 17934339}, {68959, 17934595}, {68960, 17934851},
2119
  {68961, 17935107}, {68962, 17935363}, {68963, 17935619}, {68964, 17935875},
2120
  {68965, 17936131}, {68966, 2}, {68969, 1}, {68998, 2},
2121
  {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2},
2122
  {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2},
2123
  {69296, 1}, {69298, 2}, {69314, 1}, {69317, 2},
2124
  {69372, 1}, {69416, 2}, {69424, 1}, {69466, 2},
2125
  {69488, 1}, {69514, 2}, {69552, 1}, {69580, 2},
2126
  {69600, 1}, {69623, 2}, {69632, 1}, {69710, 2},
2127
  {69714, 1}, {69750, 2}, {69759, 1}, {69821, 2},
2128
  {69822, 1}, {69827, 2}, {69840, 1}, {69865, 2},
2129
  {69872, 1}, {69882, 2}, {69888, 1}, {69941, 2},
2130
  {69942, 1}, {69960, 2}, {69968, 1}, {70007, 2},
2131
  {70016, 1}, {70112, 2}, {70113, 1}, {70133, 2},
2132
  {70144, 1}, {70162, 2}, {70163, 1}, {70210, 2},
2133
  {70272, 1}, {70279, 2}, {70280, 1}, {70281, 2},
2134
  {70282, 1}, {70286, 2}, {70287, 1}, {70302, 2},
2135
  {70303, 1}, {70314, 2}, {70320, 1}, {70379, 2},
2136
  {70384, 1}, {70394, 2}, {70400, 1}, {70404, 2},
2137
  {70405, 1}, {70413, 2}, {70415, 1}, {70417, 2},
2138
  {70419, 1}, {70441, 2}, {70442, 1}, {70449, 2},
2139
  {70450, 1}, {70452, 2}, {70453, 1}, {70458, 2},
2140
  {70459, 1}, {70469, 2}, {70471, 1}, {70473, 2},
2141
  {70475, 1}, {70478, 2}, {70480, 1}, {70481, 2},
2142
  {70487, 1}, {70488, 2}, {70493, 1}, {70500, 2},
2143
  {70502, 1}, {70509, 2}, {70512, 1}, {70517, 2},
2144
  {70528, 1}, {70538, 2}, {70539, 1}, {70540, 2},
2145
  {70542, 1}, {70543, 2}, {70544, 1}, {70582, 2},
2146
  {70583, 1}, {70593, 2}, {70594, 1}, {70595, 2},
2147
  {70597, 1}, {70598, 2}, {70599, 1}, {70603, 2},
2148
  {70604, 1}, {70614, 2}, {70615, 1}, {70617, 2},
2149
  {70625, 1}, {70627, 2}, {70656, 1}, {70748, 2},
2150
  {70749, 1}, {70754, 2}, {70784, 1}, {70856, 2},
2151
  {70864, 1}, {70874, 2}, {71040, 1}, {71094, 2},
2152
  {71096, 1}, {71134, 2}, {71168, 1}, {71237, 2},
2153
  {71248, 1}, {71258, 2}, {71264, 1}, {71277, 2},
2154
  {71296, 1}, {71354, 2}, {71360, 1}, {71370, 2},
2155
  {71376, 1}, {71396, 2}, {71424, 1}, {71451, 2},
2156
  {71453, 1}, {71468, 2}, {71472, 1}, {71495, 2},
2157
  {71680, 1}, {71740, 2}, {71840, 17936387}, {71841, 17936643},
2158
  {71842, 17936899}, {71843, 17937155}, {71844, 17937411}, {71845, 17937667},
2159
  {71846, 17937923}, {71847, 17938179}, {71848, 17938435}, {71849, 17938691},
2160
  {71850, 17938947}, {71851, 17939203}, {71852, 17939459}, {71853, 17939715},
2161
  {71854, 17939971}, {71855, 17940227}, {71856, 17940483}, {71857, 17940739},
2162
  {71858, 17940995}, {71859, 17941251}, {71860, 17941507}, {71861, 17941763},
2163
  {71862, 17942019}, {71863, 17942275}, {71864, 17942531}, {71865, 17942787},
2164
  {71866, 17943043}, {71867, 17943299}, {71868, 17943555}, {71869, 17943811},
2165
  {71870, 17944067}, {71871, 17944323}, {71872, 1}, {71923, 2},
2166
  {71935, 1}, {71943, 2}, {71945, 1}, {71946, 2},
2167
  {71948, 1}, {71956, 2}, {71957, 1}, {71959, 2},
2168
  {71960, 1}, {71990, 2}, {71991, 1}, {71993, 2},
2169
  {71995, 1}, {72007, 2}, {72016, 1}, {72026, 2},
2170
  {72096, 1}, {72104, 2}, {72106, 1}, {72152, 2},
2171
  {72154, 1}, {72165, 2}, {72192, 1}, {72264, 2},
2172
  {72272, 1}, {72355, 2}, {72368, 1}, {72441, 2},
2173
  {72448, 1}, {72458, 2}, {72640, 1}, {72674, 2},
2174
  {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2},
2175
  {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2},
2176
  {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2},
2177
  {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2},
2178
  {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2},
2179
  {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2},
2180
  {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2},
2181
  {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2},
2182
  {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2},
2183
  {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2},
2184
  {73120, 1}, {73130, 2}, {73440, 1}, {73465, 2},
2185
  {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2},
2186
  {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2},
2187
  {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2},
2188
  {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2},
2189
  {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2},
2190
  {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2},
2191
  {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2},
2192
  {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2},
2193
  {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2},
2194
  {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2},
2195
  {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2},
2196
  {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2},
2197
  {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2},
2198
  {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2},
2199
  {93760, 17944579}, {93761, 17944835}, {93762, 17945091}, {93763, 17945347},
2200
  {93764, 17945603}, {93765, 17945859}, {93766, 17946115}, {93767, 17946371},
2201
  {93768, 17946627}, {93769, 17946883}, {93770, 17947139}, {93771, 17947395},
2202
  {93772, 17947651}, {93773, 17947907}, {93774, 17948163}, {93775, 17948419},
2203
  {93776, 17948675}, {93777, 17948931}, {93778, 17949187}, {93779, 17949443},
2204
  {93780, 17949699}, {93781, 17949955}, {93782, 17950211}, {93783, 17950467},
2205
  {93784, 17950723}, {93785, 17950979}, {93786, 17951235}, {93787, 17951491},
2206
  {93788, 17951747}, {93789, 17952003}, {93790, 17952259}, {93791, 17952515},
2207
  {93792, 1}, {93851, 2}, {93952, 1}, {94027, 2},
2208
  {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2},
2209
  {94176, 1}, {94181, 2}, {94192, 1}, {94194, 2},
2210
  {94208, 1}, {100344, 2}, {100352, 1}, {101590, 2},
2211
  {101631, 1}, {101641, 2}, {110576, 1}, {110580, 2},
2212
  {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2},
2213
  {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2},
2214
  {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2},
2215
  {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2},
2216
  {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2},
2217
  {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2},
2218
  {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1},
2219
  {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987},
2220
  {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011},
2221
  {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035},
2222
  {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059},
2223
  {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083},
2224
  {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107},
2225
  {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947},
2226
  {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763},
2227
  {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787},
2228
  {118010, 2}, {118016, 1}, {118452, 2}, {118528, 1},
2229
  {118574, 2}, {118576, 1}, {118599, 2}, {118608, 1},
2230
  {118724, 2}, {118784, 1}, {119030, 2}, {119040, 1},
2231
  {119079, 2}, {119081, 1}, {119134, 34729987}, {119135, 34730499},
2232
  {119136, 51508227}, {119137, 51508995}, {119138, 51509763}, {119139, 51510531},
2233
  {119140, 51511299}, {119141, 1}, {119155, 0}, {119163, 1},
2234
  {119227, 34734851}, {119228, 34735363}, {119229, 51513091}, {119230, 51513859},
2235
  {119231, 51514627}, {119232, 51515395}, {119233, 1}, {119275, 2},
2236
  {119296, 1}, {119366, 2}, {119488, 1}, {119508, 2},
2237
  {119520, 1}, {119540, 2}, {119552, 1}, {119639, 2},
2238
  {119648, 1}, {119673, 2}, {119808, 16777219}, {119809, 16777475},
2239
  {119810, 16777731}, {119811, 16777987}, {119812, 16778243}, {119813, 16778499},
2240
  {119814, 16778755}, {119815, 16779011}, {119816, 16779267}, {119817, 16779523},
2241
  {119818, 16779779}, {119819, 16780035}, {119820, 16780291}, {119821, 16780547},
2242
  {119822, 16780803}, {119823, 16781059}, {119824, 16781315}, {119825, 16781571},
2243
  {119826, 16781827}, {119827, 16782083}, {119828, 16782339}, {119829, 16782595},
2244
  {119830, 16782851}, {119831, 16783107}, {119832, 16783363}, {119833, 16783619},
2245
  {119834, 16777219}, {119835, 16777475}, {119836, 16777731}, {119837, 16777987},
2246
  {119838, 16778243}, {119839, 16778499}, {119840, 16778755}, {119841, 16779011},
2247
  {119842, 16779267}, {119843, 16779523}, {119844, 16779779}, {119845, 16780035},
2248
  {119846, 16780291}, {119847, 16780547}, {119848, 16780803}, {119849, 16781059},
2249
  {119850, 16781315}, {119851, 16781571}, {119852, 16781827}, {119853, 16782083},
2250
  {119854, 16782339}, {119855, 16782595}, {119856, 16782851}, {119857, 16783107},
2251
  {119858, 16783363}, {119859, 16783619}, {119860, 16777219}, {119861, 16777475},
2252
  {119862, 16777731}, {119863, 16777987}, {119864, 16778243}, {119865, 16778499},
2253
  {119866, 16778755}, {119867, 16779011}, {119868, 16779267}, {119869, 16779523},
2254
  {119870, 16779779}, {119871, 16780035}, {119872, 16780291}, {119873, 16780547},
2255
  {119874, 16780803}, {119875, 16781059}, {119876, 16781315}, {119877, 16781571},
2256
  {119878, 16781827}, {119879, 16782083}, {119880, 16782339}, {119881, 16782595},
2257
  {119882, 16782851}, {119883, 16783107}, {119884, 16783363}, {119885, 16783619},
2258
  {119886, 16777219}, {119887, 16777475}, {119888, 16777731}, {119889, 16777987},
2259
  {119890, 16778243}, {119891, 16778499}, {119892, 16778755}, {119893, 2},
2260
  {119894, 16779267}, {119895, 16779523}, {119896, 16779779}, {119897, 16780035},
2261
  {119898, 16780291}, {119899, 16780547}, {119900, 16780803}, {119901, 16781059},
2262
  {119902, 16781315}, {119903, 16781571}, {119904, 16781827}, {119905, 16782083},
2263
  {119906, 16782339}, {119907, 16782595}, {119908, 16782851}, {119909, 16783107},
2264
  {119910, 16783363}, {119911, 16783619}, {119912, 16777219}, {119913, 16777475},
2265
  {119914, 16777731}, {119915, 16777987}, {119916, 16778243}, {119917, 16778499},
2266
  {119918, 16778755}, {119919, 16779011}, {119920, 16779267}, {119921, 16779523},
2267
  {119922, 16779779}, {119923, 16780035}, {119924, 16780291}, {119925, 16780547},
2268
  {119926, 16780803}, {119927, 16781059}, {119928, 16781315}, {119929, 16781571},
2269
  {119930, 16781827}, {119931, 16782083}, {119932, 16782339}, {119933, 16782595},
2270
  {119934, 16782851}, {119935, 16783107}, {119936, 16783363}, {119937, 16783619},
2271
  {119938, 16777219}, {119939, 16777475}, {119940, 16777731}, {119941, 16777987},
2272
  {119942, 16778243}, {119943, 16778499}, {119944, 16778755}, {119945, 16779011},
2273
  {119946, 16779267}, {119947, 16779523}, {119948, 16779779}, {119949, 16780035},
2274
  {119950, 16780291}, {119951, 16780547}, {119952, 16780803}, {119953, 16781059},
2275
  {119954, 16781315}, {119955, 16781571}, {119956, 16781827}, {119957, 16782083},
2276
  {119958, 16782339}, {119959, 16782595}, {119960, 16782851}, {119961, 16783107},
2277
  {119962, 16783363}, {119963, 16783619}, {119964, 16777219}, {119965, 2},
2278
  {119966, 16777731}, {119967, 16777987}, {119968, 2}, {119970, 16778755},
2279
  {119971, 2}, {119973, 16779523}, {119974, 16779779}, {119975, 2},
2280
  {119977, 16780547}, {119978, 16780803}, {119979, 16781059}, {119980, 16781315},
2281
  {119981, 2}, {119982, 16781827}, {119983, 16782083}, {119984, 16782339},
2282
  {119985, 16782595}, {119986, 16782851}, {119987, 16783107}, {119988, 16783363},
2283
  {119989, 16783619}, {119990, 16777219}, {119991, 16777475}, {119992, 16777731},
2284
  {119993, 16777987}, {119994, 2}, {119995, 16778499}, {119996, 2},
2285
  {119997, 16779011}, {119998, 16779267}, {119999, 16779523}, {120000, 16779779},
2286
  {120001, 16780035}, {120002, 16780291}, {120003, 16780547}, {120004, 2},
2287
  {120005, 16781059}, {120006, 16781315}, {120007, 16781571}, {120008, 16781827},
2288
  {120009, 16782083}, {120010, 16782339}, {120011, 16782595}, {120012, 16782851},
2289
  {120013, 16783107}, {120014, 16783363}, {120015, 16783619}, {120016, 16777219},
2290
  {120017, 16777475}, {120018, 16777731}, {120019, 16777987}, {120020, 16778243},
2291
  {120021, 16778499}, {120022, 16778755}, {120023, 16779011}, {120024, 16779267},
2292
  {120025, 16779523}, {120026, 16779779}, {120027, 16780035}, {120028, 16780291},
2293
  {120029, 16780547}, {120030, 16780803}, {120031, 16781059}, {120032, 16781315},
2294
  {120033, 16781571}, {120034, 16781827}, {120035, 16782083}, {120036, 16782339},
2295
  {120037, 16782595}, {120038, 16782851}, {120039, 16783107}, {120040, 16783363},
2296
  {120041, 16783619}, {120042, 16777219}, {120043, 16777475}, {120044, 16777731},
2297
  {120045, 16777987}, {120046, 16778243}, {120047, 16778499}, {120048, 16778755},
2298
  {120049, 16779011}, {120050, 16779267}, {120051, 16779523}, {120052, 16779779},
2299
  {120053, 16780035}, {120054, 16780291}, {120055, 16780547}, {120056, 16780803},
2300
  {120057, 16781059}, {120058, 16781315}, {120059, 16781571}, {120060, 16781827},
2301
  {120061, 16782083}, {120062, 16782339}, {120063, 16782595}, {120064, 16782851},
2302
  {120065, 16783107}, {120066, 16783363}, {120067, 16783619}, {120068, 16777219},
2303
  {120069, 16777475}, {120070, 2}, {120071, 16777987}, {120072, 16778243},
2304
  {120073, 16778499}, {120074, 16778755}, {120075, 2}, {120077, 16779523},
2305
  {120078, 16779779}, {120079, 16780035}, {120080, 16780291}, {120081, 16780547},
2306
  {120082, 16780803}, {120083, 16781059}, {120084, 16781315}, {120085, 2},
2307
  {120086, 16781827}, {120087, 16782083}, {120088, 16782339}, {120089, 16782595},
2308
  {120090, 16782851}, {120091, 16783107}, {120092, 16783363}, {120093, 2},
2309
  {120094, 16777219}, {120095, 16777475}, {120096, 16777731}, {120097, 16777987},
2310
  {120098, 16778243}, {120099, 16778499}, {120100, 16778755}, {120101, 16779011},
2311
  {120102, 16779267}, {120103, 16779523}, {120104, 16779779}, {120105, 16780035},
2312
  {120106, 16780291}, {120107, 16780547}, {120108, 16780803}, {120109, 16781059},
2313
  {120110, 16781315}, {120111, 16781571}, {120112, 16781827}, {120113, 16782083},
2314
  {120114, 16782339}, {120115, 16782595}, {120116, 16782851}, {120117, 16783107},
2315
  {120118, 16783363}, {120119, 16783619}, {120120, 16777219}, {120121, 16777475},
2316
  {120122, 2}, {120123, 16777987}, {120124, 16778243}, {120125, 16778499},
2317
  {120126, 16778755}, {120127, 2}, {120128, 16779267}, {120129, 16779523},
2318
  {120130, 16779779}, {120131, 16780035}, {120132, 16780291}, {120133, 2},
2319
  {120134, 16780803}, {120135, 2}, {120138, 16781827}, {120139, 16782083},
2320
  {120140, 16782339}, {120141, 16782595}, {120142, 16782851}, {120143, 16783107},
2321
  {120144, 16783363}, {120145, 2}, {120146, 16777219}, {120147, 16777475},
2322
  {120148, 16777731}, {120149, 16777987}, {120150, 16778243}, {120151, 16778499},
2323
  {120152, 16778755}, {120153, 16779011}, {120154, 16779267}, {120155, 16779523},
2324
  {120156, 16779779}, {120157, 16780035}, {120158, 16780291}, {120159, 16780547},
2325
  {120160, 16780803}, {120161, 16781059}, {120162, 16781315}, {120163, 16781571},
2326
  {120164, 16781827}, {120165, 16782083}, {120166, 16782339}, {120167, 16782595},
2327
  {120168, 16782851}, {120169, 16783107}, {120170, 16783363}, {120171, 16783619},
2328
  {120172, 16777219}, {120173, 16777475}, {120174, 16777731}, {120175, 16777987},
2329
  {120176, 16778243}, {120177, 16778499}, {120178, 16778755}, {120179, 16779011},
2330
  {120180, 16779267}, {120181, 16779523}, {120182, 16779779}, {120183, 16780035},
2331
  {120184, 16780291}, {120185, 16780547}, {120186, 16780803}, {120187, 16781059},
2332
  {120188, 16781315}, {120189, 16781571}, {120190, 16781827}, {120191, 16782083},
2333
  {120192, 16782339}, {120193, 16782595}, {120194, 16782851}, {120195, 16783107},
2334
  {120196, 16783363}, {120197, 16783619}, {120198, 16777219}, {120199, 16777475},
2335
  {120200, 16777731}, {120201, 16777987}, {120202, 16778243}, {120203, 16778499},
2336
  {120204, 16778755}, {120205, 16779011}, {120206, 16779267}, {120207, 16779523},
2337
  {120208, 16779779}, {120209, 16780035}, {120210, 16780291}, {120211, 16780547},
2338
  {120212, 16780803}, {120213, 16781059}, {120214, 16781315}, {120215, 16781571},
2339
  {120216, 16781827}, {120217, 16782083}, {120218, 16782339}, {120219, 16782595},
2340
  {120220, 16782851}, {120221, 16783107}, {120222, 16783363}, {120223, 16783619},
2341
  {120224, 16777219}, {120225, 16777475}, {120226, 16777731}, {120227, 16777987},
2342
  {120228, 16778243}, {120229, 16778499}, {120230, 16778755}, {120231, 16779011},
2343
  {120232, 16779267}, {120233, 16779523}, {120234, 16779779}, {120235, 16780035},
2344
  {120236, 16780291}, {120237, 16780547}, {120238, 16780803}, {120239, 16781059},
2345
  {120240, 16781315}, {120241, 16781571}, {120242, 16781827}, {120243, 16782083},
2346
  {120244, 16782339}, {120245, 16782595}, {120246, 16782851}, {120247, 16783107},
2347
  {120248, 16783363}, {120249, 16783619}, {120250, 16777219}, {120251, 16777475},
2348
  {120252, 16777731}, {120253, 16777987}, {120254, 16778243}, {120255, 16778499},
2349
  {120256, 16778755}, {120257, 16779011}, {120258, 16779267}, {120259, 16779523},
2350
  {120260, 16779779}, {120261, 16780035}, {120262, 16780291}, {120263, 16780547},
2351
  {120264, 16780803}, {120265, 16781059}, {120266, 16781315}, {120267, 16781571},
2352
  {120268, 16781827}, {120269, 16782083}, {120270, 16782339}, {120271, 16782595},
2353
  {120272, 16782851}, {120273, 16783107}, {120274, 16783363}, {120275, 16783619},
2354
  {120276, 16777219}, {120277, 16777475}, {120278, 16777731}, {120279, 16777987},
2355
  {120280, 16778243}, {120281, 16778499}, {120282, 16778755}, {120283, 16779011},
2356
  {120284, 16779267}, {120285, 16779523}, {120286, 16779779}, {120287, 16780035},
2357
  {120288, 16780291}, {120289, 16780547}, {120290, 16780803}, {120291, 16781059},
2358
  {120292, 16781315}, {120293, 16781571}, {120294, 16781827}, {120295, 16782083},
2359
  {120296, 16782339}, {120297, 16782595}, {120298, 16782851}, {120299, 16783107},
2360
  {120300, 16783363}, {120301, 16783619}, {120302, 16777219}, {120303, 16777475},
2361
  {120304, 16777731}, {120305, 16777987}, {120306, 16778243}, {120307, 16778499},
2362
  {120308, 16778755}, {120309, 16779011}, {120310, 16779267}, {120311, 16779523},
2363
  {120312, 16779779}, {120313, 16780035}, {120314, 16780291}, {120315, 16780547},
2364
  {120316, 16780803}, {120317, 16781059}, {120318, 16781315}, {120319, 16781571},
2365
  {120320, 16781827}, {120321, 16782083}, {120322, 16782339}, {120323, 16782595},
2366
  {120324, 16782851}, {120325, 16783107}, {120326, 16783363}, {120327, 16783619},
2367
  {120328, 16777219}, {120329, 16777475}, {120330, 16777731}, {120331, 16777987},
2368
  {120332, 16778243}, {120333, 16778499}, {120334, 16778755}, {120335, 16779011},
2369
  {120336, 16779267}, {120337, 16779523}, {120338, 16779779}, {120339, 16780035},
2370
  {120340, 16780291}, {120341, 16780547}, {120342, 16780803}, {120343, 16781059},
2371
  {120344, 16781315}, {120345, 16781571}, {120346, 16781827}, {120347, 16782083},
2372
  {120348, 16782339}, {120349, 16782595}, {120350, 16782851}, {120351, 16783107},
2373
  {120352, 16783363}, {120353, 16783619}, {120354, 16777219}, {120355, 16777475},
2374
  {120356, 16777731}, {120357, 16777987}, {120358, 16778243}, {120359, 16778499},
2375
  {120360, 16778755}, {120361, 16779011}, {120362, 16779267}, {120363, 16779523},
2376
  {120364, 16779779}, {120365, 16780035}, {120366, 16780291}, {120367, 16780547},
2377
  {120368, 16780803}, {120369, 16781059}, {120370, 16781315}, {120371, 16781571},
2378
  {120372, 16781827}, {120373, 16782083}, {120374, 16782339}, {120375, 16782595},
2379
  {120376, 16782851}, {120377, 16783107}, {120378, 16783363}, {120379, 16783619},
2380
  {120380, 16777219}, {120381, 16777475}, {120382, 16777731}, {120383, 16777987},
2381
  {120384, 16778243}, {120385, 16778499}, {120386, 16778755}, {120387, 16779011},
2382
  {120388, 16779267}, {120389, 16779523}, {120390, 16779779}, {120391, 16780035},
2383
  {120392, 16780291}, {120393, 16780547}, {120394, 16780803}, {120395, 16781059},
2384
  {120396, 16781315}, {120397, 16781571}, {120398, 16781827}, {120399, 16782083},
2385
  {120400, 16782339}, {120401, 16782595}, {120402, 16782851}, {120403, 16783107},
2386
  {120404, 16783363}, {120405, 16783619}, {120406, 16777219}, {120407, 16777475},
2387
  {120408, 16777731}, {120409, 16777987}, {120410, 16778243}, {120411, 16778499},
2388
  {120412, 16778755}, {120413, 16779011}, {120414, 16779267}, {120415, 16779523},
2389
  {120416, 16779779}, {120417, 16780035}, {120418, 16780291}, {120419, 16780547},
2390
  {120420, 16780803}, {120421, 16781059}, {120422, 16781315}, {120423, 16781571},
2391
  {120424, 16781827}, {120425, 16782083}, {120426, 16782339}, {120427, 16782595},
2392
  {120428, 16782851}, {120429, 16783107}, {120430, 16783363}, {120431, 16783619},
2393
  {120432, 16777219}, {120433, 16777475}, {120434, 16777731}, {120435, 16777987},
2394
  {120436, 16778243}, {120437, 16778499}, {120438, 16778755}, {120439, 16779011},
2395
  {120440, 16779267}, {120441, 16779523}, {120442, 16779779}, {120443, 16780035},
2396
  {120444, 16780291}, {120445, 16780547}, {120446, 16780803}, {120447, 16781059},
2397
  {120448, 16781315}, {120449, 16781571}, {120450, 16781827}, {120451, 16782083},
2398
  {120452, 16782339}, {120453, 16782595}, {120454, 16782851}, {120455, 16783107},
2399
  {120456, 16783363}, {120457, 16783619}, {120458, 16777219}, {120459, 16777475},
2400
  {120460, 16777731}, {120461, 16777987}, {120462, 16778243}, {120463, 16778499},
2401
  {120464, 16778755}, {120465, 16779011}, {120466, 16779267}, {120467, 16779523},
2402
  {120468, 16779779}, {120469, 16780035}, {120470, 16780291}, {120471, 16780547},
2403
  {120472, 16780803}, {120473, 16781059}, {120474, 16781315}, {120475, 16781571},
2404
  {120476, 16781827}, {120477, 16782083}, {120478, 16782339}, {120479, 16782595},
2405
  {120480, 16782851}, {120481, 16783107}, {120482, 16783363}, {120483, 16783619},
2406
  {120484, 17961731}, {120485, 17961987}, {120486, 2}, {120488, 16851715},
2407
  {120489, 16851971}, {120490, 16852227}, {120491, 16852483}, {120492, 16852739},
2408
  {120493, 16852995}, {120494, 16853251}, {120495, 16853507}, {120496, 16846851},
2409
  {120497, 16853763}, {120498, 16854019}, {120499, 16786179}, {120500, 16854275},
2410
  {120501, 16854531}, {120502, 16854787}, {120503, 16855043}, {120504, 16855299},
2411
  {120505, 16853507}, {120506, 16855555}, {120507, 16855811}, {120508, 16856067},
2412
  {120509, 16856323}, {120510, 16856579}, {120511, 16856835}, {120512, 16857091},
2413
  {120513, 17962243}, {120514, 16851715}, {120515, 16851971}, {120516, 16852227},
2414
  {120517, 16852483}, {120518, 16852739}, {120519, 16852995}, {120520, 16853251},
2415
  {120521, 16853507}, {120522, 16846851}, {120523, 16853763}, {120524, 16854019},
2416
  {120525, 16786179}, {120526, 16854275}, {120527, 16854531}, {120528, 16854787},
2417
  {120529, 16855043}, {120530, 16855299}, {120531, 16855555}, {120533, 16855811},
2418
  {120534, 16856067}, {120535, 16856323}, {120536, 16856579}, {120537, 16856835},
2419
  {120538, 16857091}, {120539, 17962499}, {120540, 16852739}, {120541, 16853507},
2420
  {120542, 16853763}, {120543, 16856323}, {120544, 16855299}, {120545, 16855043},
2421
  {120546, 16851715}, {120547, 16851971}, {120548, 16852227}, {120549, 16852483},
2422
  {120550, 16852739}, {120551, 16852995}, {120552, 16853251}, {120553, 16853507},
2423
  {120554, 16846851}, {120555, 16853763}, {120556, 16854019}, {120557, 16786179},
2424
  {120558, 16854275}, {120559, 16854531}, {120560, 16854787}, {120561, 16855043},
2425
  {120562, 16855299}, {120563, 16853507}, {120564, 16855555}, {120565, 16855811},
2426
  {120566, 16856067}, {120567, 16856323}, {120568, 16856579}, {120569, 16856835},
2427
  {120570, 16857091}, {120571, 17962243}, {120572, 16851715}, {120573, 16851971},
2428
  {120574, 16852227}, {120575, 16852483}, {120576, 16852739}, {120577, 16852995},
2429
  {120578, 16853251}, {120579, 16853507}, {120580, 16846851}, {120581, 16853763},
2430
  {120582, 16854019}, {120583, 16786179}, {120584, 16854275}, {120585, 16854531},
2431
  {120586, 16854787}, {120587, 16855043}, {120588, 16855299}, {120589, 16855555},
2432
  {120591, 16855811}, {120592, 16856067}, {120593, 16856323}, {120594, 16856579},
2433
  {120595, 16856835}, {120596, 16857091}, {120597, 17962499}, {120598, 16852739},
2434
  {120599, 16853507}, {120600, 16853763}, {120601, 16856323}, {120602, 16855299},
2435
  {120603, 16855043}, {120604, 16851715}, {120605, 16851971}, {120606, 16852227},
2436
  {120607, 16852483}, {120608, 16852739}, {120609, 16852995}, {120610, 16853251},
2437
  {120611, 16853507}, {120612, 16846851}, {120613, 16853763}, {120614, 16854019},
2438
  {120615, 16786179}, {120616, 16854275}, {120617, 16854531}, {120618, 16854787},
2439
  {120619, 16855043}, {120620, 16855299}, {120621, 16853507}, {120622, 16855555},
2440
  {120623, 16855811}, {120624, 16856067}, {120625, 16856323}, {120626, 16856579},
2441
  {120627, 16856835}, {120628, 16857091}, {120629, 17962243}, {120630, 16851715},
2442
  {120631, 16851971}, {120632, 16852227}, {120633, 16852483}, {120634, 16852739},
2443
  {120635, 16852995}, {120636, 16853251}, {120637, 16853507}, {120638, 16846851},
2444
  {120639, 16853763}, {120640, 16854019}, {120641, 16786179}, {120642, 16854275},
2445
  {120643, 16854531}, {120644, 16854787}, {120645, 16855043}, {120646, 16855299},
2446
  {120647, 16855555}, {120649, 16855811}, {120650, 16856067}, {120651, 16856323},
2447
  {120652, 16856579}, {120653, 16856835}, {120654, 16857091}, {120655, 17962499},
2448
  {120656, 16852739}, {120657, 16853507}, {120658, 16853763}, {120659, 16856323},
2449
  {120660, 16855299}, {120661, 16855043}, {120662, 16851715}, {120663, 16851971},
2450
  {120664, 16852227}, {120665, 16852483}, {120666, 16852739}, {120667, 16852995},
2451
  {120668, 16853251}, {120669, 16853507}, {120670, 16846851}, {120671, 16853763},
2452
  {120672, 16854019}, {120673, 16786179}, {120674, 16854275}, {120675, 16854531},
2453
  {120676, 16854787}, {120677, 16855043}, {120678, 16855299}, {120679, 16853507},
2454
  {120680, 16855555}, {120681, 16855811}, {120682, 16856067}, {120683, 16856323},
2455
  {120684, 16856579}, {120685, 16856835}, {120686, 16857091}, {120687, 17962243},
2456
  {120688, 16851715}, {120689, 16851971}, {120690, 16852227}, {120691, 16852483},
2457
  {120692, 16852739}, {120693, 16852995}, {120694, 16853251}, {120695, 16853507},
2458
  {120696, 16846851}, {120697, 16853763}, {120698, 16854019}, {120699, 16786179},
2459
  {120700, 16854275}, {120701, 16854531}, {120702, 16854787}, {120703, 16855043},
2460
  {120704, 16855299}, {120705, 16855555}, {120707, 16855811}, {120708, 16856067},
2461
  {120709, 16856323}, {120710, 16856579}, {120711, 16856835}, {120712, 16857091},
2462
  {120713, 17962499}, {120714, 16852739}, {120715, 16853507}, {120716, 16853763},
2463
  {120717, 16856323}, {120718, 16855299}, {120719, 16855043}, {120720, 16851715},
2464
  {120721, 16851971}, {120722, 16852227}, {120723, 16852483}, {120724, 16852739},
2465
  {120725, 16852995}, {120726, 16853251}, {120727, 16853507}, {120728, 16846851},
2466
  {120729, 16853763}, {120730, 16854019}, {120731, 16786179}, {120732, 16854275},
2467
  {120733, 16854531}, {120734, 16854787}, {120735, 16855043}, {120736, 16855299},
2468
  {120737, 16853507}, {120738, 16855555}, {120739, 16855811}, {120740, 16856067},
2469
  {120741, 16856323}, {120742, 16856579}, {120743, 16856835}, {120744, 16857091},
2470
  {120745, 17962243}, {120746, 16851715}, {120747, 16851971}, {120748, 16852227},
2471
  {120749, 16852483}, {120750, 16852739}, {120751, 16852995}, {120752, 16853251},
2472
  {120753, 16853507}, {120754, 16846851}, {120755, 16853763}, {120756, 16854019},
2473
  {120757, 16786179}, {120758, 16854275}, {120759, 16854531}, {120760, 16854787},
2474
  {120761, 16855043}, {120762, 16855299}, {120763, 16855555}, {120765, 16855811},
2475
  {120766, 16856067}, {120767, 16856323}, {120768, 16856579}, {120769, 16856835},
2476
  {120770, 16857091}, {120771, 17962499}, {120772, 16852739}, {120773, 16853507},
2477
  {120774, 16853763}, {120775, 16856323}, {120776, 16855299}, {120777, 16855043},
2478
  {120778, 16858627}, {120780, 2}, {120782, 17045507}, {120783, 16786947},
2479
  {120784, 16785155}, {120785, 16785411}, {120786, 16787715}, {120787, 17045763},
2480
  {120788, 17046019}, {120789, 17046275}, {120790, 17046531}, {120791, 17046787},
2481
  {120792, 17045507}, {120793, 16786947}, {120794, 16785155}, {120795, 16785411},
2482
  {120796, 16787715}, {120797, 17045763}, {120798, 17046019}, {120799, 17046275},
2483
  {120800, 17046531}, {120801, 17046787}, {120802, 17045507}, {120803, 16786947},
2484
  {120804, 16785155}, {120805, 16785411}, {120806, 16787715}, {120807, 17045763},
2485
  {120808, 17046019}, {120809, 17046275}, {120810, 17046531}, {120811, 17046787},
2486
  {120812, 17045507}, {120813, 16786947}, {120814, 16785155}, {120815, 16785411},
2487
  {120816, 16787715}, {120817, 17045763}, {120818, 17046019}, {120819, 17046275},
2488
  {120820, 17046531}, {120821, 17046787}, {120822, 17045507}, {120823, 16786947},
2489
  {120824, 16785155}, {120825, 16785411}, {120826, 16787715}, {120827, 17045763},
2490
  {120828, 17046019}, {120829, 17046275}, {120830, 17046531}, {120831, 17046787},
2491
  {120832, 1}, {121484, 2}, {121499, 1}, {121504, 2},
2492
  {121505, 1}, {121520, 2}, {122624, 1}, {122655, 2},
2493
  {122661, 1}, {122667, 2}, {122880, 1}, {122887, 2},
2494
  {122888, 1}, {122905, 2}, {122907, 1}, {122914, 2},
2495
  {122915, 1}, {122917, 2}, {122918, 1}, {122923, 2},
2496
  {122928, 16866563}, {122929, 16866819}, {122930, 16867075}, {122931, 16867331},
2497
  {122932, 16867587}, {122933, 16867843}, {122934, 16868099}, {122935, 16868355},
2498
  {122936, 16868611}, {122937, 16869123}, {122938, 16869379}, {122939, 16869635},
2499
  {122940, 16870147}, {122941, 16870403}, {122942, 16870659}, {122943, 16870915},
2500
  {122944, 16871171}, {122945, 16871427}, {122946, 16871683}, {122947, 16871939},
2501
  {122948, 16872195}, {122949, 16872451}, {122950, 16872707}, {122951, 16873475},
2502
  {122952, 16873987}, {122953, 16874243}, {122954, 17505795}, {122955, 16889091},
2503
  {122956, 16864003}, {122957, 16864515}, {122958, 16891139}, {122959, 16883715},
2504
  {122960, 16886019}, {122961, 16866563}, {122962, 16866819}, {122963, 16867075},
2505
  {122964, 16867331}, {122965, 16867587}, {122966, 16867843}, {122967, 16868099},
2506
  {122968, 16868355}, {122969, 16868611}, {122970, 16869123}, {122971, 16869379},
2507
  {122972, 16870147}, {122973, 16870403}, {122974, 16870915}, {122975, 16871427},
2508
  {122976, 16871683}, {122977, 16871939}, {122978, 16872195}, {122979, 16872451},
2509
  {122980, 16872707}, {122981, 16873219}, {122982, 16873475}, {122983, 16879875},
2510
  {122984, 16864003}, {122985, 16863747}, {122986, 16866307}, {122987, 16883203},
2511
  {122988, 17500931}, {122989, 16883971}, {122990, 2}, {123023, 1},
2512
  {123024, 2}, {123136, 1}, {123181, 2}, {123184, 1},
2513
  {123198, 2}, {123200, 1}, {123210, 2}, {123214, 1},
2514
  {123216, 2}, {123536, 1}, {123567, 2}, {123584, 1},
2515
  {123642, 2}, {123647, 1}, {123648, 2}, {124112, 1},
2516
  {124154, 2}, {124368, 1}, {124411, 2}, {124415, 1},
2517
  {124416, 2}, {124896, 1}, {124903, 2}, {124904, 1},
2518
  {124908, 2}, {124909, 1}, {124911, 2}, {124912, 1},
2519
  {124927, 2}, {124928, 1}, {125125, 2}, {125127, 1},
2520
  {125143, 2}, {125184, 17962755}, {125185, 17963011}, {125186, 17963267},
2521
  {125187, 17963523}, {125188, 17963779}, {125189, 17964035}, {125190, 17964291},
2522
  {125191, 17964547}, {125192, 17964803}, {125193, 17965059}, {125194, 17965315},
2523
  {125195, 17965571}, {125196, 17965827}, {125197, 17966083}, {125198, 17966339},
2524
  {125199, 17966595}, {125200, 17966851}, {125201, 17967107}, {125202, 17967363},
2525
  {125203, 17967619}, {125204, 17967875}, {125205, 17968131}, {125206, 17968387},
2526
  {125207, 17968643}, {125208, 17968899}, {125209, 17969155}, {125210, 17969411},
2527
  {125211, 17969667}, {125212, 17969923}, {125213, 17970179}, {125214, 17970435},
2528
  {125215, 17970691}, {125216, 17970947}, {125217, 17971203}, {125218, 1},
2529
  {125260, 2}, {125264, 1}, {125274, 2}, {125278, 1},
2530
  {125280, 2}, {126065, 1}, {126133, 2}, {126209, 1},
2531
  {126270, 2}, {126464, 16910595}, {126465, 17695235}, {126466, 17693443},
2532
  {126467, 17846019}, {126468, 2}, {126469, 16911107}, {126470, 17743107},
2533
  {126471, 17693955}, {126472, 17711619}, {126473, 16912131}, {126474, 17720323},
2534
  {126475, 17722627}, {126476, 17694467}, {126477, 17729539}, {126478, 17706499},
2535
  {126479, 17713155}, {126480, 17715203}, {126481, 17708547}, {126482, 17718275},
2536
  {126483, 17736707}, {126484, 17756675}, {126485, 17698307}, {126486, 17701379},
2537
  {126487, 17696515}, {126488, 17736195}, {126489, 17709571}, {126490, 17712643},
2538
  {126491, 17714179}, {126492, 17971459}, {126493, 17684995}, {126494, 17971715},
2539
  {126495, 17971971}, {126496, 2}, {126497, 17695235}, {126498, 17693443},
2540
  {126499, 2}, {126500, 17732611}, {126501, 2}, {126503, 17693955},
2541
  {126504, 2}, {126505, 16912131}, {126506, 17720323}, {126507, 17722627},
2542
  {126508, 17694467}, {126509, 17729539}, {126510, 17706499}, {126511, 17713155},
2543
  {126512, 17715203}, {126513, 17708547}, {126514, 17718275}, {126515, 2},
2544
  {126516, 17756675}, {126517, 17698307}, {126518, 17701379}, {126519, 17696515},
2545
  {126520, 2}, {126521, 17709571}, {126522, 2}, {126523, 17714179},
2546
  {126524, 2}, {126530, 17693443}, {126531, 2}, {126535, 17693955},
2547
  {126536, 2}, {126537, 16912131}, {126538, 2}, {126539, 17722627},
2548
  {126540, 2}, {126541, 17729539}, {126542, 17706499}, {126543, 17713155},
2549
  {126544, 2}, {126545, 17708547}, {126546, 17718275}, {126547, 2},
2550
  {126548, 17756675}, {126549, 2}, {126551, 17696515}, {126552, 2},
2551
  {126553, 17709571}, {126554, 2}, {126555, 17714179}, {126556, 2},
2552
  {126557, 17684995}, {126558, 2}, {126559, 17971971}, {126560, 2},
2553
  {126561, 17695235}, {126562, 17693443}, {126563, 2}, {126564, 17732611},
2554
  {126565, 2}, {126567, 17693955}, {126568, 17711619}, {126569, 16912131},
2555
  {126570, 17720323}, {126571, 2}, {126572, 17694467}, {126573, 17729539},
2556
  {126574, 17706499}, {126575, 17713155}, {126576, 17715203}, {126577, 17708547},
2557
  {126578, 17718275}, {126579, 2}, {126580, 17756675}, {126581, 17698307},
2558
  {126582, 17701379}, {126583, 17696515}, {126584, 2}, {126585, 17709571},
2559
  {126586, 17712643}, {126587, 17714179}, {126588, 17971459}, {126589, 2},
2560
  {126590, 17971715}, {126591, 2}, {126592, 16910595}, {126593, 17695235},
2561
  {126594, 17693443}, {126595, 17846019}, {126596, 17732611}, {126597, 16911107},
2562
  {126598, 17743107}, {126599, 17693955}, {126600, 17711619}, {126601, 16912131},
2563
  {126602, 2}, {126603, 17722627}, {126604, 17694467}, {126605, 17729539},
2564
  {126606, 17706499}, {126607, 17713155}, {126608, 17715203}, {126609, 17708547},
2565
  {126610, 17718275}, {126611, 17736707}, {126612, 17756675}, {126613, 17698307},
2566
  {126614, 17701379}, {126615, 17696515}, {126616, 17736195}, {126617, 17709571},
2567
  {126618, 17712643}, {126619, 17714179}, {126620, 2}, {126625, 17695235},
2568
  {126626, 17693443}, {126627, 17846019}, {126628, 2}, {126629, 16911107},
2569
  {126630, 17743107}, {126631, 17693955}, {126632, 17711619}, {126633, 16912131},
2570
  {126634, 2}, {126635, 17722627}, {126636, 17694467}, {126637, 17729539},
2571
  {126638, 17706499}, {126639, 17713155}, {126640, 17715203}, {126641, 17708547},
2572
  {126642, 17718275}, {126643, 17736707}, {126644, 17756675}, {126645, 17698307},
2573
  {126646, 17701379}, {126647, 17696515}, {126648, 17736195}, {126649, 17709571},
2574
  {126650, 17712643}, {126651, 17714179}, {126652, 2}, {126704, 1},
2575
  {126706, 2}, {126976, 1}, {127020, 2}, {127024, 1},
2576
  {127124, 2}, {127136, 1}, {127151, 2}, {127153, 1},
2577
  {127168, 2}, {127169, 1}, {127184, 2}, {127185, 1},
2578
  {127222, 2}, {127233, 34749443}, {127234, 34749955}, {127235, 34750467},
2579
  {127236, 34750979}, {127237, 34751491}, {127238, 34752003}, {127239, 34752515},
2580
  {127240, 34753027}, {127241, 34753539}, {127242, 34754051}, {127243, 1},
2581
  {127248, 50655491}, {127249, 50656259}, {127250, 50657027}, {127251, 50657795},
2582
  {127252, 50658563}, {127253, 50659331}, {127254, 50660099}, {127255, 50660867},
2583
  {127256, 50661635}, {127257, 50662403}, {127258, 50663171}, {127259, 50663939},
2584
  {127260, 50664707}, {127261, 50665475}, {127262, 50666243}, {127263, 50667011},
2585
  {127264, 50667779}, {127265, 50668547}, {127266, 50669315}, {127267, 50670083},
2586
  {127268, 50670851}, {127269, 50671619}, {127270, 50672387}, {127271, 50673155},
2587
  {127272, 50673923}, {127273, 50674691}, {127274, 51531779}, {127275, 16777731},
2588
  {127276, 16781571}, {127277, 33554947}, {127278, 34755331}, {127279, 1},
2589
  {127280, 16777219}, {127281, 16777475}, {127282, 16777731}, {127283, 16777987},
2590
  {127284, 16778243}, {127285, 16778499}, {127286, 16778755}, {127287, 16779011},
2591
  {127288, 16779267}, {127289, 16779523}, {127290, 16779779}, {127291, 16780035},
2592
  {127292, 16780291}, {127293, 16780547}, {127294, 16780803}, {127295, 16781059},
2593
  {127296, 16781315}, {127297, 16781571}, {127298, 16781827}, {127299, 16782083},
2594
  {127300, 16782339}, {127301, 16782595}, {127302, 16782851}, {127303, 16783107},
2595
  {127304, 16783363}, {127305, 16783619}, {127306, 34755843}, {127307, 34237187},
2596
  {127308, 34756355}, {127309, 34756867}, {127310, 51534595}, {127311, 34758147},
2597
  {127312, 1}, {127338, 34220035}, {127339, 34200067}, {127340, 34758659},
2598
  {127341, 1}, {127376, 34759171}, {127377, 1}, {127406, 2},
2599
  {127462, 1}, {127488, 34759683}, {127489, 34760195}, {127490, 17318403},
2600
  {127491, 2}, {127504, 17168387}, {127505, 17983491}, {127506, 17983747},
2601
  {127507, 17362179}, {127508, 17153795}, {127509, 17984003}, {127510, 17984259},
2602
  {127511, 17235971}, {127512, 17984515}, {127513, 17984771}, {127514, 17985027},
2603
  {127515, 17596163}, {127516, 17985283}, {127517, 17985539}, {127518, 17985795},
2604
  {127519, 17986051}, {127520, 17986307}, {127521, 17986563}, {127522, 17177603},
2605
  {127523, 17986819}, {127524, 17987075}, {127525, 17987331}, {127526, 17987587},
2606
  {127527, 17987843}, {127528, 17988099}, {127529, 17152259}, {127530, 17233923},
2607
  {127531, 17988355}, {127532, 17299203}, {127533, 17234691}, {127534, 17299459},
2608
  {127535, 17988611}, {127536, 17191939}, {127537, 17988867}, {127538, 17989123},
2609
  {127539, 17989379}, {127540, 17989635}, {127541, 17989891}, {127542, 17274883},
2610
  {127543, 17170947}, {127544, 17990147}, {127545, 17990403}, {127546, 17990659},
2611
  {127547, 17990915}, {127548, 2}, {127552, 51545603}, {127553, 51546371},
2612
  {127554, 51547139}, {127555, 51547907}, {127556, 51548675}, {127557, 51549443},
2613
  {127558, 51550211}, {127559, 51550979}, {127560, 51551747}, {127561, 2},
2614
  {127568, 17998083}, {127569, 17998339}, {127570, 2}, {127584, 1},
2615
  {127590, 2}, {127744, 1}, {128728, 2}, {128732, 1},
2616
  {128749, 2}, {128752, 1}, {128765, 2}, {128768, 1},
2617
  {128887, 2}, {128891, 1}, {128986, 2}, {128992, 1},
2618
  {129004, 2}, {129008, 1}, {129009, 2}, {129024, 1},
2619
  {129036, 2}, {129040, 1}, {129096, 2}, {129104, 1},
2620
  {129114, 2}, {129120, 1}, {129160, 2}, {129168, 1},
2621
  {129198, 2}, {129200, 1}, {129212, 2}, {129216, 1},
2622
  {129218, 2}, {129280, 1}, {129620, 2}, {129632, 1},
2623
  {129646, 2}, {129648, 1}, {129661, 2}, {129664, 1},
2624
  {129674, 2}, {129679, 1}, {129735, 2}, {129742, 1},
2625
  {129757, 2}, {129759, 1}, {129770, 2}, {129776, 1},
2626
  {129785, 2}, {129792, 1}, {129939, 2}, {129940, 1},
2627
  {130032, 17045507}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2628
  {130036, 16787715}, {130037, 17045763}, {130038, 17046019}, {130039, 17046275},
2629
  {130040, 17046531}, {130041, 17046787}, {130042, 2}, {131072, 1},
2630
  {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2631
  {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2632
  {191457, 2}, {191472, 1}, {192094, 2}, {194560, 17998595},
2633
  {194561, 17998851}, {194562, 17999107}, {194563, 17999363}, {194564, 17999619},
2634
  {194565, 17619971}, {194566, 17999875}, {194567, 18000131}, {194568, 18000387},
2635
  {194569, 18000643}, {194570, 17620227}, {194571, 18000899}, {194572, 18001155},
2636
  {194573, 18001411}, {194574, 17620483}, {194575, 18001667}, {194576, 18001923},
2637
  {194577, 18002179}, {194578, 18002435}, {194579, 18002691}, {194580, 18002947},
2638
  {194581, 17985795}, {194582, 18003203}, {194583, 18003459}, {194584, 18003715},
2639
  {194585, 18003971}, {194586, 18004227}, {194587, 17634563}, {194588, 18004483},
2640
  {194589, 17156355}, {194590, 18004739}, {194591, 18004995}, {194592, 18005251},
2641
  {194593, 18005507}, {194594, 17990403}, {194595, 18005763}, {194596, 18006019},
2642
  {194597, 17635843}, {194598, 17620739}, {194599, 17620995}, {194600, 17636099},
2643
  {194601, 18006275}, {194602, 18006531}, {194603, 17574403}, {194604, 18006787},
2644
  {194605, 17621251}, {194606, 18007043}, {194607, 18007299}, {194608, 18007555},
2645
  {194609, 18007811}, {194612, 18008067}, {194613, 18008323}, {194614, 18008579},
2646
  {194615, 18008835}, {194616, 18009091}, {194617, 18009347}, {194618, 18009603},
2647
  {194619, 18009859}, {194620, 18010115}, {194621, 18010371}, {194622, 18010627},
2648
  {194623, 18010883}, {194624, 18011139}, {194625, 18011395}, {194626, 18011651},
2649
  {194627, 18011907}, {194628, 18012163}, {194629, 18012419}, {194631, 17636611},
2650
  {194632, 18012675}, {194633, 18012931}, {194634, 18013187}, {194635, 18013443},
2651
  {194636, 17621763}, {194637, 18013699}, {194638, 18013955}, {194639, 18014211},
2652
  {194640, 17611523}, {194641, 18014467}, {194642, 18014723}, {194643, 18014979},
2653
  {194644, 18015235}, {194645, 18015491}, {194646, 18015747}, {194647, 18016003},
2654
  {194648, 18016259}, {194649, 18016515}, {194650, 18016771}, {194651, 18017027},
2655
  {194652, 18017283}, {194653, 17984003}, {194654, 18017539}, {194655, 18017795},
2656
  {194656, 18018051}, {194657, 18018307}, {194658, 18018563}, {194659, 18018819},
2657
  {194660, 18019075}, {194661, 18019331}, {194662, 18019587}, {194663, 18019843},
2658
  {194664, 18020099}, {194665, 18020355}, {194666, 18020611}, {194668, 18020867},
2659
  {194669, 18021123}, {194670, 18021379}, {194671, 17573379}, {194672, 18021635},
2660
  {194673, 18021891}, {194674, 18022147}, {194675, 18022403}, {194676, 18022659},
2661
  {194677, 17163011}, {194678, 18022915}, {194679, 18023171}, {194680, 17163523},
2662
  {194681, 18023427}, {194682, 18023683}, {194683, 18023939}, {194684, 18024195},
2663
  {194685, 18024451}, {194686, 18024707}, {194687, 18024963}, {194688, 18025219},
2664
  {194689, 18025475}, {194690, 18025731}, {194691, 18025987}, {194692, 18026243},
2665
  {194693, 18026499}, {194694, 18026755}, {194695, 18027011}, {194696, 18027267},
2666
  {194697, 18027523}, {194698, 18027779}, {194699, 18028035}, {194700, 18028291},
2667
  {194701, 18028547}, {194702, 17560067}, {194703, 18028803}, {194704, 17166083},
2668
  {194705, 18029059}, {194707, 18029315}, {194708, 18029571}, {194710, 18029827},
2669
  {194711, 18030083}, {194712, 18030339}, {194713, 18030595}, {194714, 18030851},
2670
  {194715, 18031107}, {194716, 18031363}, {194717, 18031619}, {194718, 18031875},
2671
  {194719, 18032131}, {194720, 18032387}, {194721, 18032643}, {194722, 18032899},
2672
  {194723, 17623043}, {194724, 18033155}, {194725, 18033411}, {194726, 18033667},
2673
  {194727, 18033923}, {194728, 17639683}, {194729, 18033923}, {194730, 18034179},
2674
  {194731, 17623555}, {194732, 18034435}, {194733, 18034691}, {194734, 18034947},
2675
  {194735, 18035203}, {194736, 17623811}, {194737, 17553155}, {194738, 17425411},
2676
  {194739, 18035459}, {194740, 18035715}, {194741, 18035971}, {194742, 18036227},
2677
  {194743, 18036483}, {194744, 18036739}, {194745, 18036995}, {194746, 18037251},
2678
  {194747, 18037507}, {194748, 18037763}, {194749, 18038019}, {194750, 18038275},
2679
  {194751, 18038531}, {194752, 18038787}, {194753, 18039043}, {194754, 18039299},
2680
  {194755, 18039555}, {194756, 18039811}, {194757, 18040067}, {194758, 18040323},
2681
  {194759, 18040579}, {194760, 17624067}, {194761, 18040835}, {194762, 18041091},
2682
  {194763, 18041347}, {194764, 18041603}, {194765, 18041859}, {194766, 18042115},
2683
  {194767, 17624579}, {194768, 18042371}, {194769, 18042627}, {194770, 18042883},
2684
  {194771, 18043139}, {194772, 18043395}, {194773, 18043651}, {194774, 18043907},
2685
  {194775, 18044163}, {194776, 17560323}, {194777, 17641731}, {194778, 18044419},
2686
  {194779, 18044675}, {194780, 18044931}, {194781, 18045187}, {194782, 18045443},
2687
  {194783, 18045699}, {194784, 18045955}, {194785, 18046211}, {194786, 17624835},
2688
  {194787, 18046467}, {194788, 18046723}, {194789, 18046979}, {194790, 18047235},
2689
  {194791, 17652483}, {194792, 18047491}, {194793, 18047747}, {194794, 18048003},
2690
  {194795, 18048259}, {194796, 18048515}, {194797, 18048771}, {194798, 18049027},
2691
  {194799, 18049283}, {194800, 18049539}, {194801, 18049795}, {194802, 18050051},
2692
  {194803, 18050307}, {194804, 18050563}, {194805, 17577731}, {194806, 18050819},
2693
  {194807, 18051075}, {194808, 18051331}, {194809, 18051587}, {194810, 18051843},
2694
  {194811, 18052099}, {194812, 18052355}, {194813, 18052611}, {194814, 18052867},
2695
  {194815, 18053123}, {194816, 18053379}, {194817, 17625091}, {194818, 17598723},
2696
  {194819, 18053635}, {194820, 18053891}, {194821, 18054147}, {194822, 18054403},
2697
  {194823, 18054659}, {194824, 18054915}, {194825, 18055171}, {194826, 18055427},
2698
  {194827, 17642499}, {194828, 18055683}, {194829, 18055939}, {194830, 18056195},
2699
  {194831, 18056451}, {194832, 18056707}, {194833, 18056963}, {194834, 18057219},
2700
  {194835, 18057475}, {194836, 17642755}, {194837, 18057731}, {194838, 18057987},
2701
  {194839, 18058243}, {194840, 18058499}, {194841, 18058755}, {194842, 18059011},
2702
  {194843, 18059267}, {194844, 18059523}, {194845, 18059779}, {194846, 18060035},
2703
  {194847, 18060291}, {194848, 18060547}, {194849, 17643267}, {194850, 18060803},
2704
  {194851, 18061059}, {194852, 18061315}, {194853, 18061571}, {194854, 18061827},
2705
  {194855, 18062083}, {194856, 18062339}, {194857, 18062595}, {194858, 18062851},
2706
  {194859, 18063107}, {194860, 18063363}, {194862, 18063619}, {194863, 18063875},
2707
  {194864, 17643779}, {194865, 18064131}, {194866, 18064387}, {194867, 18064643},
2708
  {194868, 18064899}, {194869, 18065155}, {194870, 18065411}, {194871, 18065667},
2709
  {194872, 17574147}, {194873, 18065923}, {194874, 18066179}, {194875, 18066435},
2710
  {194876, 18066691}, {194877, 18066947}, {194878, 18067203}, {194879, 18067459},
2711
  {194880, 17645315}, {194881, 18067715}, {194882, 18067971}, {194883, 18068227},
2712
  {194884, 18068483}, {194885, 18068739}, {194886, 18068995}, {194888, 17645571},
2713
  {194889, 17652995}, {194890, 18069251}, {194891, 18069507}, {194892, 18069763},
2714
  {194893, 18070019}, {194894, 18070275}, {194895, 17564675}, {194896, 17646083},
2715
  {194897, 18070531}, {194898, 18070787}, {194899, 17627651}, {194900, 18071043},
2716
  {194901, 18071299}, {194902, 17616643}, {194903, 18071555}, {194904, 18071811},
2717
  {194905, 17628419}, {194906, 18072067}, {194907, 18072323}, {194908, 18072579},
2718
  {194909, 18072835}, {194911, 18073091}, {194912, 18073347}, {194913, 18073603},
2719
  {194914, 18073859}, {194915, 18074115}, {194916, 18074371}, {194917, 18074627},
2720
  {194918, 18074883}, {194919, 18075139}, {194920, 18075395}, {194921, 18075651},
2721
  {194922, 18075907}, {194923, 18076163}, {194924, 18076419}, {194925, 18076675},
2722
  {194926, 18076931}, {194927, 18077187}, {194928, 18077443}, {194929, 18077699},
2723
  {194930, 18077955}, {194931, 18078211}, {194932, 18078467}, {194933, 18078723},
2724
  {194934, 18078979}, {194935, 18079235}, {194936, 18079491}, {194937, 18079747},
2725
  {194938, 17629955}, {194939, 18080003}, {194940, 18080259}, {194941, 18080515},
2726
  {194942, 18080771}, {194943, 18081027}, {194944, 18081283}, {194945, 18081539},
2727
  {194946, 18081795}, {194947, 18082051}, {194948, 18082307}, {194949, 18082563},
2728
  {194950, 18082819}, {194951, 18083075}, {194952, 18083331}, {194953, 18083587},
2729
  {194954, 18083843}, {194955, 18029315}, {194956, 18084099}, {194957, 18084355},
2730
  {194958, 18084611}, {194959, 18084867}, {194960, 18085123}, {194961, 18085379},
2731
  {194962, 18085635}, {194963, 18085891}, {194964, 18086147}, {194965, 18086403},
2732
  {194966, 18086659}, {194967, 18086915}, {194968, 17578499}, {194969, 18087171},
2733
  {194970, 18087427}, {194971, 18087683}, {194972, 18087939}, {194973, 18088195},
2734
  {194974, 18088451}, {194975, 17630723}, {194976, 18088707}, {194977, 18088963},
2735
  {194978, 18089219}, {194979, 18089475}, {194980, 18089731}, {194981, 18089987},
2736
  {194982, 18090243}, {194983, 18090499}, {194984, 18090755}, {194985, 18091011},
2737
  {194986, 18091267}, {194987, 18091523}, {194988, 18091779}, {194989, 18092035},
2738
  {194990, 18092291}, {194991, 18092547}, {194992, 18092803}, {194993, 18093059},
2739
  {194994, 18093315}, {194995, 18093571}, {194996, 17563395}, {194997, 18093827},
2740
  {194998, 18094083}, {194999, 18094339}, {195000, 18094595}, {195001, 18094851},
2741
  {195002, 18095107}, {195003, 17647875}, {195004, 18095363}, {195005, 18095619},
2742
  {195006, 18095875}, {195007, 18096131}, {195008, 18096387}, {195009, 18096643},
2743
  {195010, 18096899}, {195011, 18097155}, {195012, 17189123}, {195013, 18097411},
2744
  {195014, 18097667}, {195015, 18097923}, {195016, 18098179}, {195017, 18098435},
2745
  {195018, 18098691}, {195019, 18098947}, {195020, 18099203}, {195021, 18099459},
2746
  {195022, 18099715}, {195023, 18099971}, {195024, 17649155}, {195025, 17649411},
2747
  {195026, 17190915}, {195027, 18100227}, {195028, 18100483}, {195029, 18100739},
2748
  {195030, 18100995}, {195031, 18101251}, {195032, 18101507}, {195033, 18101763},
2749
  {195034, 18102019}, {195035, 18102275}, {195036, 18102531}, {195037, 18102787},
2750
  {195038, 18103043}, {195039, 17649667}, {195040, 18103299}, {195041, 18103555},
2751
  {195042, 18103811}, {195043, 18104067}, {195044, 18104323}, {195045, 18104579},
2752
  {195046, 18104835}, {195047, 18105091}, {195048, 18105347}, {195049, 18105603},
2753
  {195050, 18105859}, {195051, 18106115}, {195052, 18106371}, {195053, 18106627},
2754
  {195054, 18106883}, {195055, 18107139}, {195056, 18107395}, {195057, 18107651},
2755
  {195058, 18107907}, {195059, 18108163}, {195060, 18108419}, {195061, 18108675},
2756
  {195062, 18108931}, {195063, 18109187}, {195064, 18109443}, {195065, 18109699},
2757
  {195066, 18109955}, {195067, 18110211}, {195068, 18110467}, {195069, 18110723},
2758
  {195070, 17651203}, {195072, 18110979}, {195073, 18111235}, {195074, 18111491},
2759
  {195075, 18111747}, {195076, 18112003}, {195077, 18112259}, {195078, 18112515},
2760
  {195079, 18112771}, {195080, 18113027}, {195081, 18113283}, {195082, 17651459},
2761
  {195083, 18113539}, {195084, 18113795}, {195085, 18114051}, {195086, 18114307},
2762
  {195087, 18114563}, {195088, 18114819}, {195089, 18115075}, {195090, 18115331},
2763
  {195091, 18115587}, {195092, 18115843}, {195093, 17203203}, {195094, 18116099},
2764
  {195095, 17204227}, {195096, 18116355}, {195097, 18116611}, {195098, 18116867},
2765
  {195099, 18117123}, {195100, 17205507}, {195101, 18117379}, {195102, 2},
2766
  {196608, 1}, {201547, 2}, {201552, 1}, {205744, 2},
2767
  {917760, 0}, {918000, 2}
2768
};
2769
2770
2771
} // namespace ada::idna
2772
#endif // ADA_IDNA_TABLES_H
2773
/* end file src/mapping_tables.cpp */
2774
2775
namespace ada::idna {
2776
2777
// This can be greatly accelerated. For now we just use a simply
2778
// binary search. In practice, you should *not* do that.
2779
0
uint32_t find_range_index(uint32_t key) {
2780
  ////////////////
2781
  // This could be implemented with std::lower_bound, but we roll our own
2782
  // because we want to allow further optimizations in the future.
2783
  ////////////////
2784
0
  uint32_t len = std::size(table);
2785
0
  uint32_t low = 0;
2786
0
  uint32_t high = len - 1;
2787
0
  while (low <= high) {
2788
0
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2789
0
    uint32_t middle_value = table[middle_index][0];
2790
0
    if (middle_value < key) {
2791
0
      low = middle_index + 1;
2792
0
    } else if (middle_value > key) {
2793
0
      high = middle_index - 1;
2794
0
    } else {
2795
0
      return middle_index;  // perfect match
2796
0
    }
2797
0
  }
2798
0
  return low == 0 ? 0 : low - 1;
2799
0
}
2800
2801
0
void ascii_map(char* input, size_t length) {
2802
0
  auto broadcast = [](uint8_t v) -> uint64_t {
2803
0
    return 0x101010101010101ull * v;
2804
0
  };
2805
0
  uint64_t broadcast_80 = broadcast(0x80);
2806
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2807
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2808
0
  size_t i = 0;
2809
2810
0
  for (; i + 7 < length; i += 8) {
2811
0
    uint64_t word{};
2812
0
    memcpy(&word, input + i, sizeof(word));
2813
0
    word ^=
2814
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2815
0
    memcpy(input + i, &word, sizeof(word));
2816
0
  }
2817
0
  if (i < length) {
2818
0
    uint64_t word{};
2819
0
    memcpy(&word, input + i, length - i);
2820
0
    word ^=
2821
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2822
0
    memcpy(input + i, &word, length - i);
2823
0
  }
2824
0
}
2825
2826
// Map the characters according to IDNA, returning the empty string on error.
2827
0
std::u32string map(std::u32string_view input) {
2828
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2829
  //  For each code point in the domain_name string, look up the status
2830
  //  value in Section 5, [IDNA Mapping
2831
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2832
  //  and take the following actions:
2833
  //    * disallowed: Leave the code point unchanged in the string, and
2834
  //    record that there was an error.
2835
  //    * ignored: Remove the code point from the string. This is
2836
  //    equivalent to mapping the code point to an empty string.
2837
  //    * mapped: Replace the code point in the string by the value for
2838
  //    the mapping in Section 5, [IDNA Mapping
2839
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2840
  //    * valid: Leave the code point unchanged in the string.
2841
0
  static std::u32string error = U"";
2842
0
  std::u32string answer;
2843
0
  answer.reserve(input.size());
2844
0
  for (char32_t x : input) {
2845
0
    size_t index = find_range_index(x);
2846
0
    uint32_t descriptor = table[index][1];
2847
0
    uint8_t code = uint8_t(descriptor);
2848
0
    switch (code) {
2849
0
      case 0:
2850
0
        break;  // nothing to do, ignored
2851
0
      case 1:
2852
0
        answer.push_back(x);  // valid, we just copy it to output
2853
0
        break;
2854
0
      case 2:
2855
0
        return error;  // disallowed
2856
      // case 3 :
2857
0
      default:
2858
        // We have a mapping
2859
0
        {
2860
0
          size_t char_count = (descriptor >> 24);
2861
0
          uint16_t char_index = uint16_t(descriptor >> 8);
2862
0
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2863
0
            answer.push_back(mappings[idx]);
2864
0
          }
2865
0
        }
2866
0
    }
2867
0
  }
2868
0
  return answer;
2869
0
}
2870
}  // namespace ada::idna
2871
/* end file src/mapping.cpp */
2872
/* begin file src/normalization.cpp */
2873
/* begin file src/normalization_tables.cpp */
2874
// IDNA  15.0.0
2875
2876
// clang-format off
2877
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2878
#define ADA_IDNA_NORMALIZATION_TABLES_H
2879
#include <cstdint>
2880
2881
/**
2882
 * Unicode Standard Annex #15
2883
 *
2884
 * UNICODE NORMALIZATION FORMS
2885
 * https://www.unicode.org/reports/tr15/
2886
 *
2887
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2888
 */
2889
2890
namespace ada::idna {
2891
2892
const uint8_t decomposition_index[4352] = {
2893
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2894
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2895
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2896
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2897
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2898
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2899
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2900
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2901
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  34, 35, 7,  7,  7,
2902
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2903
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2904
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2905
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2906
    7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2907
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2908
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2910
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2911
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2912
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2913
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2914
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2915
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2916
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2917
    7,  7,  7,  7,  7,  7,  7,  7,  7,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2918
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2919
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2920
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2922
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2923
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2924
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2925
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2926
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2927
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2928
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2929
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2930
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2931
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2932
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2933
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2934
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2935
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2936
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2937
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2938
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2939
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2940
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2941
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2942
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2943
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2944
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2945
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2946
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2947
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2948
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  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};
3123
3124
const uint16_t decomposition_block[67][257] = {
3125
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3126
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3127
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3128
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3129
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3130
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3131
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3132
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3133
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3134
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3135
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3136
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3137
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3138
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3139
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3140
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3141
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3142
     516, 524},
3143
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3144
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3145
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3146
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3147
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3148
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3149
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3150
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3151
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3152
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3153
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3154
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3155
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3156
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3157
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3158
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3159
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3160
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3161
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3162
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3163
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3164
     1948, 1956, 1964, 1972, 1980},
3165
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3166
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3167
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3168
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3169
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3170
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3171
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3172
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3173
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3174
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3175
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3176
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3177
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3178
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3179
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3180
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3181
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3182
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3183
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3184
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3185
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3186
     2460, 2460, 2460, 2460, 2460},
3187
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3188
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3189
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3190
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3191
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3192
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3193
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3194
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3195
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3196
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3197
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3198
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3199
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3200
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3201
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3202
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3203
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3204
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3205
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3206
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3207
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3208
     2744, 2744, 2744, 2744, 2744},
3209
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3210
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3211
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3212
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3213
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3214
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3215
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3216
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3217
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3218
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3219
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3220
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3221
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3222
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3223
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3224
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3225
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3226
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3227
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3228
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3229
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3230
     3160, 3160, 3160, 3160, 3160},
3231
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3232
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3233
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3234
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3235
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3236
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3237
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3238
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3239
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3240
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3241
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3242
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3243
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3244
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3245
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3246
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3247
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3248
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3249
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3250
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3251
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3252
     3168, 3168, 3168, 3168, 3168},
3253
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3254
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3255
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3256
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3257
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3258
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3259
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3260
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3261
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3262
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3263
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3264
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3265
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3266
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3267
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3268
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3269
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3270
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3271
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3272
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3273
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3274
     3264, 3264, 3264, 3264, 3264},
3275
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3276
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3277
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3278
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3279
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3280
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3281
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3282
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3283
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3284
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3285
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3290
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3291
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3292
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3293
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3294
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3295
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3296
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3297
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3298
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3299
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3300
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3301
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3302
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3303
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3304
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3305
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3306
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3307
     3392, 3392, 3392, 3392, 3392},
3308
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3309
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3310
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3311
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3312
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3313
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3314
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3315
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3316
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3317
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3318
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3319
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3320
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3321
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3322
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3323
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3324
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3325
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3326
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3327
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3328
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3329
     3440, 3440, 3440, 3440, 3440},
3330
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 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, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3337
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3338
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3339
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3340
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3341
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3342
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3343
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3344
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3345
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3346
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3347
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3348
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3349
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3350
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3351
     3512, 3512, 3512, 3512, 3512},
3352
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3353
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3354
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3355
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3356
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3357
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3358
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3359
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3360
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3361
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3362
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3363
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3364
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3365
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3366
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3367
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3368
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3369
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3370
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3371
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3372
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3373
     3564, 3564, 3564, 3564, 3564},
3374
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3375
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3376
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3377
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3378
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3379
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3380
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3381
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3382
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3383
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3384
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3385
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3386
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3387
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3388
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3389
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3390
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3391
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3392
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3393
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3394
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3395
     3624, 3624, 3624, 3624, 3624},
3396
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3397
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3398
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3399
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3400
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3401
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3402
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3403
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3404
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3405
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3406
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3407
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3408
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3409
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3410
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3411
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3412
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3413
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3414
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3415
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3416
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3417
     3656, 3656, 3656, 3656, 3656},
3418
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3419
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3420
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3421
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3422
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3423
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3424
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3425
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3426
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3427
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3428
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3429
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3430
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3431
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3432
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3433
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3434
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3435
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3436
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3437
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3438
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3439
     3820, 3820, 3820, 3820, 3820},
3440
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3441
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3442
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3443
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3444
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3445
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3446
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3447
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3448
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3449
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3450
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3451
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3452
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3453
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3454
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3455
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3456
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3457
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3458
     3828, 3828, 3828, 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
     3829, 3832, 3832, 3832, 3832},
3462
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3463
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3464
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3465
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3466
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3467
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3468
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3469
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3470
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3471
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3472
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3473
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3474
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3475
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3476
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3477
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3478
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3479
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3480
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3481
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3482
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3483
     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, 3921, 3925, 3929, 3932,
3488
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3489
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3490
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3491
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3492
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3493
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3494
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3495
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3496
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3497
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3498
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3499
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3500
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3501
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3502
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3503
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3504
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3505
     4312, 4312, 4312, 4312, 4312},
3506
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3507
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3508
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3509
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3510
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3511
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3512
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3513
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3514
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3515
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3516
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3517
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3518
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3519
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3520
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3521
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3522
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3523
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3524
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3525
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3526
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3527
     6648, 6648, 6648, 6648, 6648},
3528
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3529
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3530
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3531
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3532
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3533
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3534
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3535
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3536
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3537
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3538
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3539
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3540
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3541
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3542
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3543
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3544
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3545
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3546
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3547
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3548
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3549
     9168, 9178, 9181, 9188, 9190},
3550
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3551
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3552
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3553
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3554
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3555
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3556
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3557
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3558
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3559
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3560
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3561
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3562
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3563
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3564
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3565
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3566
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3567
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3568
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3569
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3570
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3571
     9548, 9548, 9548, 9548, 9549},
3572
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3573
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3574
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3575
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3576
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3577
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3578
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3579
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3580
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3581
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3582
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3583
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3584
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3585
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3586
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3587
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3588
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3589
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3590
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3591
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3592
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3593
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3594
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3595
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3596
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3597
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3598
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3599
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3600
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3601
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3602
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3603
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3604
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3605
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3606
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3607
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3608
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3609
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3610
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3611
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3612
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3613
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3614
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3615
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3616
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3617
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3618
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3619
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3620
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3621
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3622
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3623
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3624
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3625
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3626
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3627
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3628
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3629
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3630
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3631
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3632
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3633
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3634
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3635
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3636
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3637
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3638
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3639
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3640
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3641
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3642
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3643
     10688, 10688, 10688, 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},
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, 10689, 10693, 10697, 10701,
3660
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3661
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3662
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3663
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3664
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3665
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3666
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3667
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3668
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3669
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3670
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3671
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3672
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3673
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3674
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3675
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3676
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3677
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3678
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3679
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3680
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3681
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3682
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3683
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3684
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3685
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3686
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3687
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3688
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3689
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3690
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3691
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3692
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3693
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3694
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3695
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3696
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3697
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3698
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3699
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3700
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3701
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3702
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3703
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3704
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3705
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3706
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3707
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3708
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3709
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3710
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3711
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3712
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3713
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3714
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3715
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3716
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3717
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3718
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3719
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3720
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3721
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3722
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3723
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3724
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3725
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3726
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3727
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3728
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3729
     11888, 11888, 11888, 11888, 11888, 11888, 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, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3740
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3741
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3742
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3743
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3744
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3745
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3746
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3747
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3748
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3749
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3750
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3751
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3752
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3753
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3754
    {11892, 11892, 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, 11892, 11892, 11892,
3769
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3770
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3771
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3772
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3773
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3774
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3775
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3776
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3777
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3778
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3779
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3780
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3781
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3782
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3783
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3784
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3785
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3786
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3787
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3788
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3789
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3790
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3791
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3792
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3793
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3794
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3795
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3796
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3797
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3798
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3799
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3800
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3801
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3802
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3803
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3804
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3805
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3806
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3807
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3808
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3809
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3810
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3811
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3812
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3813
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3814
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3815
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3816
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3817
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3818
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3819
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3820
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3821
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3822
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3823
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3824
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3825
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3826
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3827
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3828
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3829
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3830
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3831
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3832
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3833
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3834
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3835
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3836
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3837
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3838
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3839
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3840
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3841
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3842
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3843
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3844
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3845
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3846
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3847
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3848
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3849
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3850
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3851
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3852
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3853
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3854
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3855
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3856
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3857
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3858
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3859
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3860
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3861
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3862
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3863
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3864
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3865
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3866
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3867
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3868
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3869
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3870
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3871
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3872
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3873
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3874
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3875
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3876
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3877
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3878
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3879
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3880
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3881
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3882
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3883
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3884
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3885
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3886
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3887
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3888
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3889
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3890
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3891
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3892
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3893
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3894
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3895
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3896
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3897
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3898
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3899
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3900
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3901
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3902
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3903
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3904
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3905
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3906
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3907
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3908
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3909
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3910
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3911
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3912
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3913
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3914
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3915
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3916
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3917
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3918
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3919
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3920
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3921
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3922
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3923
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3924
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3925
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3926
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3927
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3928
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3929
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3930
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3931
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3932
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3933
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3934
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3935
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3936
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3937
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3938
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3939
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3940
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 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, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3948
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3949
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3950
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3951
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3952
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3953
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3954
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3955
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3956
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3957
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3958
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3959
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3960
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3961
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3962
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3963
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3964
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3965
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3966
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3967
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3968
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3969
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3970
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
3971
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3972
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3973
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3974
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3975
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3976
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3977
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3978
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3979
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3980
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3981
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3982
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3983
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3984
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3985
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3986
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
3987
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
3988
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3989
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3990
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3991
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3992
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3993
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3994
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3995
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3996
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3997
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3998
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3999
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4000
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4001
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4002
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4003
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4004
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4005
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4006
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4007
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4008
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4009
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4010
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4011
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4012
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4013
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4014
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4015
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4016
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4017
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4018
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4019
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4020
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4021
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4022
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4023
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4024
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4025
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4026
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4027
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4028
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4029
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4030
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4031
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4032
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4033
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4034
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4035
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4036
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4037
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4038
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4039
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4040
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4041
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4042
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4043
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4044
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4045
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4046
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4047
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4048
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4049
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4050
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4051
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4052
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4053
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4054
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4055
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4056
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4057
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4058
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4059
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4060
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4061
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4062
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4063
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4064
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4065
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4066
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4067
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4068
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4069
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4070
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4071
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4072
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4073
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4074
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4075
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4076
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4077
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4078
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4079
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4080
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4081
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4082
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4083
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4084
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4085
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4086
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4087
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4088
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4089
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4090
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4091
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4092
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4093
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4094
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4095
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4096
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4097
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4098
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4099
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4100
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4101
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4102
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4103
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4104
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4105
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4106
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4107
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4108
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4109
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4110
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4111
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4112
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4113
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4114
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4115
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4116
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4117
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4118
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4119
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4120
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4121
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4122
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4123
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4124
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4125
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4126
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4127
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4128
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4129
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4130
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4131
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4132
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4133
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4134
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4135
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4136
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4137
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4138
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4139
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4140
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4141
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4142
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4143
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4144
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4145
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4146
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4147
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4148
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4149
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4150
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4151
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4152
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4153
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4154
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4155
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4156
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4157
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4158
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4159
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4160
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4161
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4162
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4163
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4164
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4165
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4166
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4167
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4168
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4169
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4170
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4171
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4172
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4173
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4174
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4175
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4176
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4177
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4178
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4179
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4180
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4181
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4182
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4183
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4184
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4185
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4186
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4187
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4188
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4189
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4190
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4191
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4192
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4193
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4194
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4195
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4196
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4197
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4198
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4199
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4200
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4201
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4202
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4203
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 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, 28220, 28220, 28220,
4211
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4212
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4213
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4214
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4215
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4216
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4217
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4218
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4219
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4220
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4221
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4222
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4223
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4224
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4225
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4226
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4227
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4228
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4229
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4230
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4231
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4232
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4233
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4234
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4235
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4236
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4237
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4238
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4239
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4240
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4241
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 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},
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, 28268, 28276, 28276, 28276,
4256
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4257
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4258
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4259
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4260
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4261
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4262
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4263
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4264
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4265
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4266
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4267
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4268
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4269
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4270
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 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},
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, 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, 28284, 28292,
4293
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4294
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4295
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4296
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4297
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4298
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4299
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4300
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4301
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4302
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4303
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4304
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4305
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4306
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4307
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4308
     28300, 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, 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, 28308, 28316, 28316,
4319
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4320
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4321
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4322
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4323
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4324
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4325
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4326
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4327
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4328
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4329
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4330
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4331
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4332
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4333
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4334
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4335
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4336
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4337
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4338
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4339
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4340
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4341
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4342
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4343
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4344
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4345
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4346
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 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},
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, 28332, 28340, 28352, 28364, 28376,
4362
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4363
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4364
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4365
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4366
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4367
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4368
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4369
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4370
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4371
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4372
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4373
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4374
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4375
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4376
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4377
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4378
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4379
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4380
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4381
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4382
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4383
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4384
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4385
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4386
     28464, 28464, 28464, 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, 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, 28465},
4404
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4405
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4406
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4407
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4408
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4409
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4410
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4411
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4412
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4413
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4414
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4415
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4416
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4417
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4418
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4419
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4420
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4421
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4422
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4423
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4424
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4425
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4426
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4427
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4428
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4429
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4430
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4431
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4432
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4433
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4434
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4435
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4436
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4437
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4438
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4439
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4440
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4441
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4442
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4443
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4444
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4445
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4446
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4447
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4448
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4449
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4450
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4451
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4452
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4453
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4454
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4455
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4456
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4457
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4458
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4459
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4460
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4461
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4462
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4463
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4464
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4465
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4466
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4467
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4468
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4469
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4470
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4471
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4472
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4473
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4474
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4475
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4476
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4477
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4478
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4479
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4480
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4481
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4482
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4483
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4484
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4485
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4486
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4487
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4488
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4489
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4490
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4491
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4492
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4493
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4494
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4495
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4496
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4497
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4498
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4499
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4500
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4501
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4502
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4503
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4504
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4505
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4506
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4507
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4508
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4509
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4510
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4511
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4512
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4513
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4514
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4515
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4516
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4517
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4518
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4519
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4520
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4521
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4522
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4523
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4524
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4525
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4526
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4527
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4528
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4529
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4530
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4531
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4532
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4533
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
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, 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, 32697},
4560
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4561
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4562
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4563
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4564
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4565
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4566
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4567
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4568
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4569
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4570
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4571
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4572
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4573
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4574
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4575
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4576
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4577
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4578
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4579
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4580
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4581
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4582
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4583
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4584
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4585
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4586
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4587
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4588
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4589
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4590
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4591
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4592
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4593
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 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, 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, 33261},
4612
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4613
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4614
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4615
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4616
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4617
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4618
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4619
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4620
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4621
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4622
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4623
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4624
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4625
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4626
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4627
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4628
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4629
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4630
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4631
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4632
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4633
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4634
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4635
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4636
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4637
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4638
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4639
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4640
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4641
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4642
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4643
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4644
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4645
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4646
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4647
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4648
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4649
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4650
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4651
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4652
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4653
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4654
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4655
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4656
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4657
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4658
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4659
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4660
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4661
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4663
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
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, 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
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4689
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4690
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4691
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4692
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4693
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4694
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4695
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4696
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4697
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4698
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4699
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4700
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4701
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4702
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4703
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4704
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4705
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4706
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4707
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4708
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4709
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4710
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4711
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4712
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4713
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4714
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4715
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4716
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4717
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4718
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4719
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4720
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4721
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4722
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4723
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4724
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4725
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4726
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4727
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4728
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4729
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4730
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4731
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4732
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4733
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4734
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4735
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4736
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4737
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4738
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4739
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4740
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4741
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4742
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4743
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4744
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4745
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4746
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4747
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4748
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4749
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4750
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4751
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4752
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4753
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4754
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4755
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4756
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4757
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4758
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4759
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
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}};
4768
const char32_t decomposition_data[9102] = {
4769
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4770
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4771
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4772
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4773
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4774
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4775
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4776
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4777
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4778
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4779
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4780
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4781
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4782
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4783
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4784
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4785
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4786
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4787
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4788
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4789
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4790
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4791
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4792
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4793
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4794
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4795
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4796
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4797
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4798
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4799
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4800
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4801
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4802
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4803
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4804
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4805
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4806
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4807
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4808
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4809
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4810
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4811
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4812
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4813
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4814
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4815
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4816
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4817
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4818
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4819
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4820
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4821
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4822
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4823
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4824
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4825
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4826
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4827
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4828
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4829
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4830
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4831
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4832
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4833
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4834
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4835
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4836
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4837
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4838
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4839
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4840
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4841
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4842
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4843
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4844
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4845
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4846
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4847
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4848
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4849
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4850
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4851
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4852
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4853
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4854
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4855
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4856
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4857
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4858
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4859
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4860
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4861
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4862
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4863
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4864
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4865
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4866
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4867
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4868
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4869
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4870
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4871
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4872
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4873
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4874
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4875
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4876
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4877
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4878
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4879
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4880
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4881
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4882
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4883
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4884
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4885
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4886
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4887
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4888
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4889
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4890
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4891
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4892
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4893
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4894
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4895
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4896
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4897
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4898
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4899
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4900
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4901
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4902
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4903
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4904
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4905
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4906
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4907
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4908
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4909
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4910
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4911
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4912
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4913
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4914
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4915
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4916
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4917
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4918
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4919
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4920
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4921
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4922
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4923
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4924
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4925
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4926
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4927
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4928
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4929
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4930
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4931
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4932
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4933
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4934
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4935
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4936
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4937
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4938
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4939
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4940
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4941
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4942
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4943
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4944
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4945
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4946
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4947
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4948
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4949
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4950
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4951
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4952
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4953
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4954
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4955
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4956
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4957
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4958
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4959
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4960
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4961
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4962
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4963
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4964
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4965
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4966
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4967
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4968
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4969
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4970
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4971
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4972
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4973
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4974
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4975
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4976
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4977
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4978
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4979
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4980
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4981
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4982
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4983
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4984
    945,    768,    945,    769,    949,    768,    949,    769,    951,
4985
    768,    951,    769,    953,    768,    953,    769,    959,    768,
4986
    959,    769,    965,    768,    965,    769,    969,    768,    969,
4987
    769,    945,    787,    837,    945,    788,    837,    945,    787,
4988
    768,    837,    945,    788,    768,    837,    945,    787,    769,
4989
    837,    945,    788,    769,    837,    945,    787,    834,    837,
4990
    945,    788,    834,    837,    913,    787,    837,    913,    788,
4991
    837,    913,    787,    768,    837,    913,    788,    768,    837,
4992
    913,    787,    769,    837,    913,    788,    769,    837,    913,
4993
    787,    834,    837,    913,    788,    834,    837,    951,    787,
4994
    837,    951,    788,    837,    951,    787,    768,    837,    951,
4995
    788,    768,    837,    951,    787,    769,    837,    951,    788,
4996
    769,    837,    951,    787,    834,    837,    951,    788,    834,
4997
    837,    919,    787,    837,    919,    788,    837,    919,    787,
4998
    768,    837,    919,    788,    768,    837,    919,    787,    769,
4999
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5000
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5001
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5002
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5003
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5004
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5005
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5006
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5007
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5008
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5009
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5010
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5011
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5012
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5013
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5014
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5015
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5016
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5017
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5018
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5019
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5020
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5021
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5022
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5023
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5024
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5025
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5026
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5027
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5028
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5029
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5030
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5031
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5032
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5033
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5034
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5035
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5036
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5037
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5038
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5039
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5040
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5041
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5042
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5043
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5044
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5045
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5046
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5047
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5048
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5049
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5050
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5051
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5052
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5053
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5054
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5055
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5056
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5057
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5058
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5059
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5060
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5061
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5062
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5063
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5064
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5065
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5066
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5067
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5068
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5069
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5070
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5071
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5072
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5073
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5074
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5075
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5076
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5077
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5078
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5079
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5080
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5081
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5082
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5083
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5084
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5085
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5086
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5087
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5088
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5089
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5090
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5091
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5092
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5093
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5094
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5095
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5096
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5097
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5098
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5099
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5100
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5101
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5102
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5103
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5104
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5105
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5106
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5107
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5108
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5109
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5110
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5111
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5112
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5113
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5114
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5115
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5116
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5117
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5118
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5119
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5120
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5121
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5122
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5123
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5124
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5125
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5126
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5127
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5128
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5129
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5130
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5131
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5132
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5133
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5134
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5135
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5136
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5137
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5138
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5139
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5140
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5141
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5142
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5143
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5144
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5145
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5146
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5147
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5148
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5149
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5150
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5151
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5152
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5153
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5154
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5155
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5156
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5157
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5158
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5159
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5160
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5161
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5162
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5163
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5164
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5165
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5166
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5167
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5168
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5169
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5170
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5171
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5172
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5173
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5174
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5175
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5176
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5177
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5178
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5179
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5180
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5181
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5182
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5183
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5184
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5185
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5186
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5187
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5188
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5189
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5190
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5191
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5192
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5193
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5194
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5195
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5196
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5197
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5198
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5199
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5200
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5201
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5202
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5203
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5204
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5205
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5206
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5207
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5208
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5209
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5210
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5211
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5212
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5213
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5214
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5215
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5216
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5217
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5218
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5219
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5220
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5221
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5222
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5223
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5224
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5225
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5226
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5227
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5228
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5229
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5230
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5231
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5232
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5233
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5234
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5235
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5236
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5237
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5238
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5239
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5240
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5241
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5242
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5243
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5244
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5245
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5246
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5247
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5248
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5249
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5250
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5251
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5252
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5253
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5254
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5255
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5256
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5257
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5258
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5259
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5260
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5261
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5262
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5263
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5264
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5265
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5266
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5267
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5268
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5269
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5270
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5271
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5272
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5273
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5274
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5275
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5276
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5277
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5278
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5279
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5280
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5281
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5282
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5283
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5284
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5285
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5286
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5287
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5288
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5289
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5290
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5291
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5292
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5293
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5294
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5295
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5296
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5297
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5298
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5299
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5300
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5301
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5302
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5303
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5304
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5305
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5306
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5307
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5308
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5309
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5310
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5311
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5312
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5313
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5314
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5315
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5316
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5317
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5318
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5319
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5320
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5321
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5322
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5323
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5324
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5325
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5326
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5327
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5328
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5329
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5330
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5331
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5332
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5333
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5334
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5335
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5336
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5337
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5338
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5339
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5340
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5341
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5342
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5343
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5344
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5345
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5346
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5347
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5348
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5349
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5350
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5351
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5352
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5353
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5354
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5355
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5356
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5357
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5358
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5359
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5360
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5361
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5362
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5363
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5364
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5365
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5366
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5367
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5368
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5369
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5370
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5371
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5372
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5373
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5374
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5375
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5376
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5377
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5378
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5379
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5380
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5381
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5382
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5383
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5384
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5385
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5386
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5387
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5388
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5389
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5390
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5391
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5392
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5393
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5394
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5395
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5396
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5397
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5398
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5399
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5400
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5401
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5402
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5403
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5404
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5405
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5406
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5407
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5408
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5409
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5410
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5411
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5412
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5413
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5414
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5415
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5416
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5417
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5418
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5419
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5420
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5421
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5422
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5423
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5424
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5425
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5426
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5427
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5428
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5429
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5430
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5431
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5432
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5433
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5434
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5435
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5436
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5437
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5438
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5439
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5440
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5441
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5442
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5443
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5444
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5445
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5446
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5447
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5448
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5449
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5450
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5451
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5452
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5453
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5454
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5455
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5456
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5457
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5458
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5459
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5460
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5461
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5462
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5463
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5464
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5465
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5466
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5467
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5468
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5469
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5470
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5471
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5472
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5473
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5474
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5475
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5476
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5477
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5478
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5479
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5480
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5481
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5482
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5483
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5484
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5485
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5486
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5487
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5488
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5489
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5490
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5491
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5492
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5493
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5494
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5495
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5496
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5497
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5498
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5499
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5500
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5501
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5502
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5503
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5504
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5505
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5506
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5507
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5508
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5509
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5510
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5511
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5512
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5513
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5514
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5515
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5516
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5517
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5518
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5519
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5520
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5521
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5522
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5523
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5524
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5525
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5526
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5527
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5528
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5529
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5530
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5531
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5532
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5533
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5534
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5535
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5536
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5537
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5538
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5539
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5540
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5541
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5542
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5543
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5544
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5545
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5546
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5547
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5548
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5549
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5550
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5551
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5552
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5553
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5554
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5555
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5556
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5557
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5558
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5559
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5560
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5561
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5562
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5563
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5564
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5565
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5566
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5567
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5568
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5569
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5570
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5571
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5572
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5573
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5574
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5575
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5576
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5577
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5578
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5579
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5580
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5581
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5582
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5583
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5584
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5585
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5586
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5587
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5588
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5589
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5590
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5591
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5592
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5593
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5594
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5595
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5596
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5597
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5598
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5599
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5600
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5601
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5602
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5603
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5604
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5605
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5606
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5607
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5608
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5609
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5610
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5611
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5612
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5613
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5614
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5615
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5616
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5617
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5618
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5619
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5620
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5621
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5622
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5623
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5624
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5625
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5626
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5627
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5628
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5629
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5630
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5631
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5632
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5633
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5634
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5635
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5636
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5637
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5638
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5639
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5640
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5641
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5642
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5643
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5644
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5645
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5646
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5647
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5648
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5649
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5650
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5651
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5652
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5653
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5654
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5655
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5656
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5657
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5658
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5659
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5660
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5661
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5662
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5663
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5664
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5665
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5666
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5667
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5668
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5669
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5670
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5671
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5672
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5673
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5674
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5675
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5676
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5677
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5678
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5679
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5680
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5681
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5682
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5683
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5684
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5685
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5686
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5687
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5688
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5689
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5690
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5691
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5692
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5693
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5694
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5695
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5696
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5697
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5698
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5699
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5700
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5701
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5702
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5703
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5704
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5705
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5706
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5707
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5708
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5709
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5710
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5711
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5712
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5713
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5714
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5715
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5716
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5717
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5718
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5719
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5720
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5721
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5722
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5723
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5724
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5725
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5726
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5727
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5728
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5729
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5730
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5731
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5732
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5733
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5734
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5735
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5736
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5737
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5738
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5739
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5740
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5741
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5742
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5743
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5744
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5745
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5746
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5747
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5748
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5749
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5750
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5751
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5752
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5753
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5754
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5755
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5756
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5757
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5758
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5759
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5760
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5761
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5762
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5763
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5764
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5765
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5766
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5767
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5768
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5769
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5770
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5771
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5772
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5773
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5774
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5775
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5776
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5777
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5778
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5779
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5780
    40726,  40763,  173568};
5781
5782
const uint8_t canonical_combining_class_index[4352] = {
5783
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5784
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5785
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5786
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5787
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5788
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5789
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5790
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5791
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5792
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5793
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5794
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5795
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5796
    0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5797
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5798
    53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5799
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5801
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5802
    0,  55, 56, 0,  0,  0,  57, 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,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5807
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5809
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5812
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5813
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5814
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5815
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5816
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5817
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5818
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5819
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5820
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5821
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5824
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  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};
6013
const uint8_t canonical_combining_class_block[67][256] = {
6014
    {0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0,
6020
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6021
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6022
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6023
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6024
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6025
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6026
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6027
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6028
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6029
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6030
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6031
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6032
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6033
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6034
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6035
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6036
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6037
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6038
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6039
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6040
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6041
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6042
     0},
6043
    {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6044
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6045
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6046
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6047
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6048
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6049
     230, 230, 230, 230, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6051
     0,   0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6053
     0,   0,   0,   0,   0, 0, 0, 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},
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,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6058
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6059
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6060
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6061
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6062
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6063
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6064
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6065
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6066
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6067
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6068
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6069
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6070
     0,   0,   0,   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},
6073
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6074
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  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
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6079
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6080
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6081
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6082
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6083
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6088
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6089
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6090
     0},
6091
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6094
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6095
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
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,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6103
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6105
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6106
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6107
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6108
     0},
6109
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6110
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6111
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6112
     230, 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,   220,
6115
     220, 220, 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,   230, 220, 220, 220, 230, 230, 230, 230, 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,   0,   0,   0,   0,   0,
6122
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6123
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6124
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6125
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6126
     230},
6127
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6128
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6129
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6130
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6131
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6132
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6133
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6134
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6135
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6136
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6137
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6138
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6139
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6140
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6141
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6142
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6143
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6145
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6146
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6147
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6148
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6149
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6150
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6151
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6152
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6153
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6154
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6157
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6158
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6160
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6161
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 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, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  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},
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0, 0, 0, 0, 0, 9, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6179
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
6183
    {0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6184
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6185
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6186
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6187
     107, 107, 107, 107, 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,
6189
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6190
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6191
     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,
6193
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6194
     0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6196
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6197
     0,   0,   0,   0},
6198
    {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,   220, 220, 0,   0,   0, 0,
6200
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6201
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6202
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6203
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6204
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6205
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6206
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6207
     230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6208
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6209
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6210
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6211
     0,   0, 0,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6212
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
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,   0,   0,   0,   0,   0, 0,
6215
     0},
6216
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6217
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6218
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6219
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6220
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6221
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6222
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6223
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6224
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6225
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6226
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6227
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6228
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6229
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6230
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6231
     0, 0, 0, 0, 0, 230, 230, 230, 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,
6233
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6234
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6235
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6236
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6237
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6238
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0},
6239
    {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 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, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6242
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 0, 0,
6246
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6247
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 230, 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},
6250
    {0, 0,   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, 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, 0, 0,
6253
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6254
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6255
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6256
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 228, 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},
6261
    {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, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6264
     0, 0, 0, 0, 0, 0, 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,
6266
     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,
6268
     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,
6270
     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,
6272
     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,
6274
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6275
     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,
6277
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6278
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6279
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6280
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6281
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6282
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6283
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6284
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6285
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6286
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6287
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6288
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6289
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6290
     0},
6291
    {0,   0,   0, 0, 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,   0,   0,   0,   0,
6293
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6294
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6296
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6297
     230, 230, 0, 0, 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,   0,   0,   0,   0,
6299
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6300
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6301
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6302
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6303
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6304
     0,   0,   0, 0, 0, 0, 0, 0, 0},
6305
    {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6306
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6307
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6308
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6309
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6310
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6311
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6312
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6313
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6314
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6315
     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,
6317
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6318
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6319
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6320
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6321
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6322
     0},
6323
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6324
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   0,   0,
6334
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6335
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 220,
6336
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6337
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6338
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6339
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6340
     220},
6341
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6342
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6343
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6344
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6345
     0,   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,   0,
6347
     0,   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,   0,
6349
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6350
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6351
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6352
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6353
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6354
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6355
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6356
     230, 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, 0, 0, 0, 0,   0,   0,
6358
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,   0,   0,
6360
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,   0,   0,
6362
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,   0,   0,
6364
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6365
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6366
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6367
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6368
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6369
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6370
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6371
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6372
     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,
6374
     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,
6376
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6377
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6378
     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,
6380
     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,
6382
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6383
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6384
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6385
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6386
     230},
6387
    {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6388
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6389
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6390
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6391
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6392
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6393
     0, 0, 0,   0,   0,   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, 8, 8, 0, 0, 0, 0, 0,
6395
     0, 0, 0,   0,   0,   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, 0, 0, 0, 0, 0,
6397
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6398
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6399
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0},
6400
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6401
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6402
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6403
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6404
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6405
     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,   230,
6407
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6408
     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,   0,   230, 230,
6410
     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,
6412
     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,
6414
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6415
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6416
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     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,   9,
6419
     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,
6421
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6422
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6423
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6424
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6425
     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,
6427
     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,
6429
     0,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6430
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6431
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6432
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6433
     0},
6434
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6435
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6436
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6437
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6438
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6439
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6440
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6441
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6442
     0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6443
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6444
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6445
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6446
    {0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6447
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6448
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6449
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6450
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6451
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6452
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6453
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6454
     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, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6456
     230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6457
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6458
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6459
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6460
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0, 0, 9, 0, 0,
6470
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6471
    {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6472
     0, 0, 0, 0, 0, 0, 26, 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, 0, 0, 0, 0, 0, 0,
6474
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6475
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 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},
6482
    {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,
6484
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6485
     220, 230, 230, 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,
6487
     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,
6489
     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,
6491
     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,
6493
     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,
6495
     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,
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},
6500
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6501
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6502
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6503
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6504
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6505
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6506
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6507
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6508
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6509
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6510
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6511
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6512
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6513
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6514
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6515
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 220, 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},
6522
    {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,
6524
     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,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6526
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6528
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6529
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6530
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6531
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6532
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6533
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6534
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6536
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6537
     0, 0, 0, 9, 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,
6539
     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,
6541
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6542
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6543
     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,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 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},
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, 230, 230, 230, 230, 0, 0, 0, 0,
6549
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6550
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6551
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6552
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   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, 0, 0,
6554
     0, 0, 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, 0, 0,
6556
     0, 0, 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, 0, 0,
6558
     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, 0, 0,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6561
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   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,  0, 0, 0, 0,   0,   0, 0, 0,
6564
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
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, 230, 230, 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, 220, 220, 220},
6571
    {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,
6573
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6574
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6575
     230, 230, 230, 220, 230, 220, 220, 220, 220, 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,
6577
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6578
     0,   0,   0,   0,   230, 220, 230, 220, 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,
6580
     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,   0,
6582
     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,
6584
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6585
     0,   0,   0,   0},
6586
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6587
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6588
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6589
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6590
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
6591
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6592
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6593
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6594
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6596
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6597
    {230, 230, 230, 0, 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, 0, 0, 0, 0,
6599
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6600
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
6602
     0,   0,   0,   0, 0, 7, 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,
6604
     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,
6606
     0,   0,   0,   0, 7, 0, 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,
6608
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6609
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6612
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6613
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6614
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6615
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6616
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6617
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6618
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0,
6619
     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,
6621
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6622
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6623
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6624
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6625
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6626
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6627
     230, 230, 230, 230, 230, 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,
6629
     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,
6631
     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,
6633
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6634
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6635
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0},
6636
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6637
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6638
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 7,   0,
6639
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6640
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6641
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6642
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6643
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6644
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6645
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6646
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6647
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6648
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6649
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6650
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6651
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6652
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6653
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6654
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6655
     7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6657
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6658
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6659
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6660
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6661
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6662
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6668
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6669
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6670
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6671
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6672
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6673
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6674
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6675
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6676
     0, 0, 0, 0, 0, 0, 0, 0, 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},
6680
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6683
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6684
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6685
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6686
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
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, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6694
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6695
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6696
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6697
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700
     0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6701
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6702
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6704
     0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6706
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6709
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6711
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6712
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6713
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6715
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6716
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6717
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6720
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6722
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6723
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6724
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6725
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6726
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6727
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6728
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6729
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6730
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6731
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6734
     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, 9, 9, 0, 0, 0, 0, 0,
6738
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6742
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6746
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6747
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6748
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6749
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6750
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6751
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6752
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6753
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6754
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6755
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6756
     1, 1, 1, 1, 1, 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,
6758
     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, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6760
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6761
     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,
6763
     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,
6765
     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,
6767
     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,
6769
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6770
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0,
6774
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6775
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 0, 0, 0, 0,
6780
     6, 6, 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, 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, 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, 0, 0, 0, 0,
6784
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 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},
6792
    {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,
6794
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6795
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6796
     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,
6798
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6799
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6800
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6801
     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,   230, 230, 230, 230, 0,   0,
6803
     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,
6805
     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, 0, 0, 0, 0, 0, 0,
6809
     0,   0,   0,   0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6811
     230, 230, 230, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6813
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6814
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6815
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6816
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6817
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6818
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6819
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6820
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6821
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6822
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6823
     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,
6825
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6826
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6827
     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,
6829
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6830
     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,
6832
     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,
6834
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6835
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6836
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6837
     0},
6838
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6839
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6840
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6841
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6842
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6843
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6844
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6845
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6846
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6847
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6848
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6849
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6850
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6851
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6852
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6853
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   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, 232, 232, 220, 230, 0, 0,
6861
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6862
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6864
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6865
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 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,
6867
     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,
6869
     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,
6871
     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, 220, 220, 220, 220, 220, 220, 220, 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,
6874
     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, 0, 0, 0, 0,
6876
     0, 0, 0, 0, 0, 0, 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, 230, 230, 230, 230, 230, 230, 7, 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, 0,   0,   0,   0,   0,   0,   0, 0}};
6888
6889
const uint8_t composition_index[4352] = {
6890
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6891
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6892
    5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6893
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6894
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6895
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6896
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6897
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6898
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6899
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6900
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6901
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6902
    5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6903
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6904
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6905
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6908
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6909
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6910
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6911
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6912
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6913
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6914
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6915
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6916
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6917
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6918
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  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};
7088
const uint16_t composition_block[67][257] = {
7089
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7090
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7091
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7092
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7093
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7094
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7095
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7096
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7097
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7098
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7099
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7100
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7101
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7102
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7103
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7104
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7105
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7106
     869, 869},
7107
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7108
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7109
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7110
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7111
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7112
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7113
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7114
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7115
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7116
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7117
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7118
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7119
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7120
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7121
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7122
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7123
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7124
     965, 965},
7125
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7126
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7127
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7128
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7129
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7130
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7131
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7132
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7133
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7134
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7135
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7136
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7137
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7138
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7139
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7140
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7141
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7142
     979, 979},
7143
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7144
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7145
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7146
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7147
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7148
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7149
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7150
     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,
7152
     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,
7154
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7155
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7156
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7157
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7158
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7159
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7160
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7161
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7162
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7163
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7164
     1171, 1171, 1171, 1171, 1171},
7165
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7166
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7167
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7168
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7169
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7170
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7171
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7172
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7173
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7174
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7175
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7176
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7177
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7178
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7179
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7180
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7181
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7182
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7183
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7184
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7185
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7186
     1275, 1275, 1275, 1275, 1275},
7187
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7188
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7190
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7191
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7192
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7193
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7194
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7195
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7196
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7197
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7198
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7199
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7200
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7201
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7202
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7203
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7204
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7205
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7206
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7207
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7208
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7209
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7210
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7211
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7212
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7213
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7214
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7215
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7216
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7217
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7218
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7219
     1291, 1291, 1291, 1291, 1291},
7220
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7221
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7222
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7223
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7224
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7225
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7226
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7227
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7228
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7229
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7230
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7231
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7232
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7233
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7234
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7235
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7236
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7237
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7238
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7239
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7240
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7241
     1301, 1301, 1301, 1301, 1301},
7242
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7243
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7244
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7245
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7246
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7247
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7248
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7249
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7250
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7251
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7252
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7253
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7254
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7255
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7256
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7257
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7258
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7259
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7260
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7261
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7262
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7263
     1315, 1315, 1315, 1315, 1315},
7264
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7265
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7266
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7267
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7268
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7269
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7270
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7271
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7272
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7273
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7274
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7275
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7276
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7277
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7278
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7279
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7280
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7281
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7282
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7283
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7284
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7285
     1327, 1327, 1327, 1327, 1327},
7286
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7287
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7288
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7289
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7290
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7291
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7292
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7293
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7294
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7295
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7296
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7297
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7298
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7299
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7300
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7301
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7302
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7303
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7304
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7305
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7306
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7307
     1341, 1341, 1341, 1341, 1341},
7308
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7309
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7310
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7311
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7312
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7313
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7314
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7315
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7316
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7317
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7318
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7319
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7320
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7321
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7322
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7323
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7324
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7325
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7326
     1343, 1343, 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},
7330
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7331
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7332
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7333
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7334
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7335
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7336
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7337
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7338
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7339
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7340
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7341
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7342
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7343
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7344
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7345
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7346
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7347
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7348
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7349
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7350
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7351
     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, 1367, 1369, 1369, 1369, 1369,
7357
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7358
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7359
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7360
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7361
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7362
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7363
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7364
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7365
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7366
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7367
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7368
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7369
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7370
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7371
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7372
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7373
     1393, 1393, 1393, 1393, 1393},
7374
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7375
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7376
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7377
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7378
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7379
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7380
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7381
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7382
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7383
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7384
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7385
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7386
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7387
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7388
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7389
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7390
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7391
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7392
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7393
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7394
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7395
     1653, 1653, 1653, 1659, 1659},
7396
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7397
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7398
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7399
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7400
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7401
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7402
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7403
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7404
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7405
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7406
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7407
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7408
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7409
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7410
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7411
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7412
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7413
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7414
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7415
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7416
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7417
     1671, 1671, 1671, 1671, 1671},
7418
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7419
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7420
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7421
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7422
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7423
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7424
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7425
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7426
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7427
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7428
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7429
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7430
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7431
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7432
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7433
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7434
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7435
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7436
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7437
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7438
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7439
     1741, 1741, 1741, 1741, 1741},
7440
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7441
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7442
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7443
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7444
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7445
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7446
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7447
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7448
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7449
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7450
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7451
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7452
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7453
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7454
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7455
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7456
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7457
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7458
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7459
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7460
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7461
     1855, 1855, 1857, 1857, 1857},
7462
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7463
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7464
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7465
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7466
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7467
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7468
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7469
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7470
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7471
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7472
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7473
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7474
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7475
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7476
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7477
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7478
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7479
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7480
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7481
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7482
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7483
     1863, 1863, 1863, 1863, 1863},
7484
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7485
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7486
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7487
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7488
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7489
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7490
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7491
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7492
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7493
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7494
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7495
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7496
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7497
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7498
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7499
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7500
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7501
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7502
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7503
     1867, 1867, 1867, 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},
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
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7513
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7514
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7515
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7516
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7517
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7518
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7519
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7520
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7521
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7522
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7523
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7524
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7525
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7526
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7527
     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, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7543
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7544
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7545
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7546
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7547
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7548
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7549
     1877, 1877, 1877, 1877, 1877},
7550
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7551
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7552
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7553
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7554
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7555
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7556
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7557
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7558
     1877, 1877, 1877, 1877, 1877, 1877, 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, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7565
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7566
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7567
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7568
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7569
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7570
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7571
     1881, 1881, 1881, 1881, 1881},
7572
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7573
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7574
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7575
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7576
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7577
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7578
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7579
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7580
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7581
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7582
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7583
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7584
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7585
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7586
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7587
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7588
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7589
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7590
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7591
     1883, 1883, 1883, 1883, 1883, 1883, 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}};
7594
const char32_t composition_data[1883] = {
7595
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7596
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7597
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7598
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7599
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7600
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7601
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7602
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7603
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7604
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7605
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7606
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7607
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7608
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7609
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7610
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7611
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7612
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7613
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7614
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7615
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7616
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7617
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7618
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7619
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7620
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7621
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7622
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7623
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7624
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7625
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7626
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7627
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7628
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7629
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7630
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7631
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7632
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7633
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7634
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7635
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7636
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7637
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7638
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7639
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7640
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7641
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7642
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7643
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7644
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7645
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7646
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7647
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7648
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7649
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7650
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7651
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7652
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7653
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7654
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7655
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7656
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7657
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7658
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7659
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7660
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7661
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7662
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7663
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7664
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7665
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7666
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7667
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7668
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7669
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7670
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7671
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7672
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7673
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7674
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7675
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7676
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7677
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7678
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7679
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7680
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7681
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7682
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7683
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7684
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7685
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7686
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7687
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7688
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7689
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7690
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7691
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7692
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7693
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7694
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7695
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7696
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7697
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7698
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7699
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7700
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7701
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7702
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7703
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7704
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7705
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7706
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7707
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7708
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7709
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7710
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7711
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7712
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7713
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7714
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7715
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7716
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7717
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7718
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7719
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7720
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7721
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7722
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7723
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7724
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7725
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7726
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7727
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7728
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7729
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7730
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7731
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7732
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7733
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7734
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7735
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7736
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7737
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7738
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7739
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7740
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7741
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7742
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7743
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7744
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7745
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7746
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7747
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7748
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7749
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7750
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7751
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7752
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7753
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7754
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7755
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7756
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7757
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7758
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7759
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7760
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7761
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7762
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7763
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7764
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7765
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7766
    71984, 71992};
7767
7768
}  // namespace ada::idna
7769
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7770
/* end file src/normalization_tables.cpp */
7771
7772
namespace ada::idna {
7773
7774
// See
7775
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7776
constexpr char32_t hangul_sbase = 0xAC00;
7777
constexpr char32_t hangul_tbase = 0x11A7;
7778
constexpr char32_t hangul_vbase = 0x1161;
7779
constexpr char32_t hangul_lbase = 0x1100;
7780
constexpr char32_t hangul_lcount = 19;
7781
constexpr char32_t hangul_vcount = 21;
7782
constexpr char32_t hangul_tcount = 28;
7783
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7784
constexpr char32_t hangul_scount =
7785
    hangul_lcount * hangul_vcount * hangul_tcount;
7786
7787
std::pair<bool, size_t> compute_decomposition_length(
7788
0
    const std::u32string_view input) noexcept {
7789
0
  bool decomposition_needed{false};
7790
0
  size_t additional_elements{0};
7791
0
  for (char32_t current_character : input) {
7792
0
    size_t decomposition_length{0};
7793
7794
0
    if (current_character >= hangul_sbase &&
7795
0
        current_character < hangul_sbase + hangul_scount) {
7796
0
      decomposition_length = 2;
7797
0
      if ((current_character - hangul_sbase) % hangul_tcount) {
7798
0
        decomposition_length = 3;
7799
0
      }
7800
0
    } else if (current_character < 0x110000) {
7801
0
      const uint8_t di = decomposition_index[current_character >> 8];
7802
0
      const uint16_t* const decomposition =
7803
0
          decomposition_block[di] + (current_character % 256);
7804
0
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7805
0
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7806
0
        decomposition_length = 0;
7807
0
      }
7808
0
    }
7809
0
    if (decomposition_length != 0) {
7810
0
      decomposition_needed = true;
7811
0
      additional_elements += decomposition_length - 1;
7812
0
    }
7813
0
  }
7814
0
  return {decomposition_needed, additional_elements};
7815
0
}
7816
7817
0
void decompose(std::u32string& input, size_t additional_elements) {
7818
0
  input.resize(input.size() + additional_elements);
7819
0
  for (size_t descending_idx = input.size(),
7820
0
              input_count = descending_idx - additional_elements;
7821
0
       input_count--;) {
7822
0
    if (input[input_count] >= hangul_sbase &&
7823
0
        input[input_count] < hangul_sbase + hangul_scount) {
7824
      // Hangul decomposition.
7825
0
      char32_t s_index = input[input_count] - hangul_sbase;
7826
0
      if (s_index % hangul_tcount != 0) {
7827
0
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7828
0
      }
7829
0
      input[--descending_idx] =
7830
0
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7831
0
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7832
0
    } else if (input[input_count] < 0x110000) {
7833
      // Check decomposition_data.
7834
0
      const uint16_t* decomposition =
7835
0
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7836
0
          (input[input_count] % 256);
7837
0
      uint16_t decomposition_length =
7838
0
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7839
0
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7840
0
        decomposition_length = 0;
7841
0
      }
7842
0
      if (decomposition_length > 0) {
7843
        // Non-recursive decomposition.
7844
0
        while (decomposition_length-- > 0) {
7845
0
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7846
0
                                                       decomposition_length];
7847
0
        }
7848
0
      } else {
7849
        // No decomposition.
7850
0
        input[--descending_idx] = input[input_count];
7851
0
      }
7852
0
    } else {
7853
      // Non-Unicode character.
7854
0
      input[--descending_idx] = input[input_count];
7855
0
    }
7856
0
  }
7857
0
}
7858
7859
0
uint8_t get_ccc(char32_t c) noexcept {
7860
0
  return c < 0x110000 ? canonical_combining_class_block
7861
0
                            [canonical_combining_class_index[c >> 8]][c % 256]
7862
0
                      : 0;
7863
0
}
7864
7865
0
void sort_marks(std::u32string& input) {
7866
0
  for (size_t idx = 1; idx < input.size(); idx++) {
7867
0
    uint8_t ccc = get_ccc(input[idx]);
7868
0
    if (ccc == 0) {
7869
0
      continue;
7870
0
    }  // Skip non-combining characters.
7871
0
    auto current_character = input[idx];
7872
0
    size_t back_idx = idx;
7873
0
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7874
0
      input[back_idx] = input[back_idx - 1];
7875
0
      back_idx--;
7876
0
    }
7877
0
    input[back_idx] = current_character;
7878
0
  }
7879
0
}
7880
7881
0
void decompose_nfc(std::u32string& input) {
7882
  /**
7883
   * Decompose the domain_name string to Unicode Normalization Form C.
7884
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7885
   */
7886
0
  auto [decomposition_needed, additional_elements] =
7887
0
      compute_decomposition_length(input);
7888
0
  if (decomposition_needed) {
7889
0
    decompose(input, additional_elements);
7890
0
  }
7891
0
  sort_marks(input);
7892
0
}
7893
7894
0
void compose(std::u32string& input) {
7895
  /**
7896
   * Compose the domain_name string to Unicode Normalization Form C.
7897
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7898
   */
7899
0
  size_t input_count{0};
7900
0
  size_t composition_count{0};
7901
0
  for (; input_count < input.size(); input_count++, composition_count++) {
7902
0
    input[composition_count] = input[input_count];
7903
0
    if (input[input_count] >= hangul_lbase &&
7904
0
        input[input_count] < hangul_lbase + hangul_lcount) {
7905
0
      if (input_count + 1 < input.size() &&
7906
0
          input[input_count + 1] >= hangul_vbase &&
7907
0
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7908
0
        input[composition_count] =
7909
0
            hangul_sbase +
7910
0
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7911
0
             input[input_count + 1] - hangul_vbase) *
7912
0
                hangul_tcount;
7913
0
        input_count++;
7914
0
        if (input_count + 1 < input.size() &&
7915
0
            input[input_count + 1] > hangul_tbase &&
7916
0
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7917
0
          input[composition_count] += input[++input_count] - hangul_tbase;
7918
0
        }
7919
0
      }
7920
0
    } else if (input[input_count] >= hangul_sbase &&
7921
0
               input[input_count] < hangul_sbase + hangul_scount) {
7922
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7923
0
          input_count + 1 < input.size() &&
7924
0
          input[input_count + 1] > hangul_tbase &&
7925
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7926
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7927
0
      }
7928
0
    } else if (input[input_count] < 0x110000) {
7929
0
      const uint16_t* composition =
7930
0
          &composition_block[composition_index[input[input_count] >> 8]]
7931
0
                            [input[input_count] % 256];
7932
0
      size_t initial_composition_count = composition_count;
7933
0
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7934
0
           input_count++) {
7935
0
        uint8_t ccc = get_ccc(input[input_count + 1]);
7936
7937
0
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7938
          // Try finding a composition.
7939
0
          int left = composition[0];
7940
0
          int right = composition[1];
7941
0
          while (left + 2 < right) {
7942
            // mean without overflow
7943
0
            int middle = left + (((right - left) >> 1) & ~1);
7944
0
            if (composition_data[middle] <= input[input_count + 1]) {
7945
0
              left = middle;
7946
0
            }
7947
0
            if (composition_data[middle] >= input[input_count + 1]) {
7948
0
              right = middle;
7949
0
            }
7950
0
          }
7951
0
          if (composition_data[left] == input[input_count + 1]) {
7952
0
            input[initial_composition_count] = composition_data[left + 1];
7953
0
            composition =
7954
0
                &composition_block
7955
0
                    [composition_index[composition_data[left + 1] >> 8]]
7956
0
                    [composition_data[left + 1] % 256];
7957
0
            continue;
7958
0
          }
7959
0
        }
7960
7961
0
        if (ccc == 0) {
7962
0
          break;
7963
0
        }  // Not a combining character.
7964
0
        previous_ccc = ccc;
7965
0
        input[++composition_count] = input[input_count + 1];
7966
0
      }
7967
0
    }
7968
0
  }
7969
7970
0
  if (composition_count < input_count) {
7971
0
    input.resize(composition_count);
7972
0
  }
7973
0
}
7974
7975
0
void normalize(std::u32string& input) {
7976
  /**
7977
   * Normalize the domain_name string to Unicode Normalization Form C.
7978
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7979
   */
7980
0
  decompose_nfc(input);
7981
0
  compose(input);
7982
0
}
7983
7984
}  // namespace ada::idna
7985
/* end file src/normalization.cpp */
7986
/* begin file src/punycode.cpp */
7987
7988
#include <cstdint>
7989
7990
namespace ada::idna {
7991
7992
constexpr int32_t base = 36;
7993
constexpr int32_t tmin = 1;
7994
constexpr int32_t tmax = 26;
7995
constexpr int32_t skew = 38;
7996
constexpr int32_t damp = 700;
7997
constexpr int32_t initial_bias = 72;
7998
constexpr uint32_t initial_n = 128;
7999
8000
0
static constexpr int32_t char_to_digit_value(char value) {
8001
0
  if (value >= 'a' && value <= 'z') return value - 'a';
8002
0
  if (value >= '0' && value <= '9') return value - '0' + 26;
8003
0
  return -1;
8004
0
}
8005
8006
0
static constexpr char digit_to_char(int32_t digit) {
8007
0
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8008
0
}
8009
8010
0
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8011
0
  if (firsttime) {
8012
0
    d = d / damp;
8013
0
  } else {
8014
0
    d = d / 2;
8015
0
  }
8016
0
  d += d / n;
8017
0
  int32_t k = 0;
8018
0
  while (d > ((base - tmin) * tmax) / 2) {
8019
0
    d /= base - tmin;
8020
0
    k += base;
8021
0
  }
8022
0
  return k + (((base - tmin + 1) * d) / (d + skew));
8023
0
}
8024
8025
0
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8026
  // See https://github.com/whatwg/url/issues/803
8027
0
  if (input.starts_with("xn--")) {
8028
0
    return false;
8029
0
  }
8030
0
  int32_t written_out{0};
8031
0
  out.reserve(out.size() + input.size());
8032
0
  uint32_t n = initial_n;
8033
0
  int32_t i = 0;
8034
0
  int32_t bias = initial_bias;
8035
  // grab ascii content
8036
0
  size_t end_of_ascii = input.find_last_of('-');
8037
0
  if (end_of_ascii != std::string_view::npos) {
8038
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8039
0
      if (c >= 0x80) {
8040
0
        return false;
8041
0
      }
8042
0
      out.push_back(c);
8043
0
      written_out++;
8044
0
    }
8045
0
    input.remove_prefix(end_of_ascii + 1);
8046
0
  }
8047
0
  while (!input.empty()) {
8048
0
    int32_t oldi = i;
8049
0
    int32_t w = 1;
8050
0
    for (int32_t k = base;; k += base) {
8051
0
      if (input.empty()) {
8052
0
        return false;
8053
0
      }
8054
0
      uint8_t code_point = input.front();
8055
0
      input.remove_prefix(1);
8056
0
      int32_t digit = char_to_digit_value(code_point);
8057
0
      if (digit < 0) {
8058
0
        return false;
8059
0
      }
8060
0
      if (digit > (0x7fffffff - i) / w) {
8061
0
        return false;
8062
0
      }
8063
0
      i = i + digit * w;
8064
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8065
0
      if (digit < t) {
8066
0
        break;
8067
0
      }
8068
0
      if (w > 0x7fffffff / (base - t)) {
8069
0
        return false;
8070
0
      }
8071
0
      w = w * (base - t);
8072
0
    }
8073
0
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8074
0
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8075
0
      return false;
8076
0
    }
8077
0
    n = n + i / (written_out + 1);
8078
0
    i = i % (written_out + 1);
8079
0
    if (n < 0x80) {
8080
0
      return false;
8081
0
    }
8082
0
    out.insert(out.begin() + i, n);
8083
0
    written_out++;
8084
0
    ++i;
8085
0
  }
8086
0
  return true;
8087
0
}
8088
8089
0
bool verify_punycode(std::string_view input) {
8090
0
  if (input.starts_with("xn--")) {
8091
0
    return false;
8092
0
  }
8093
0
  size_t written_out{0};
8094
0
  uint32_t n = initial_n;
8095
0
  int32_t i = 0;
8096
0
  int32_t bias = initial_bias;
8097
  // grab ascii content
8098
0
  size_t end_of_ascii = input.find_last_of('-');
8099
0
  if (end_of_ascii != std::string_view::npos) {
8100
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8101
0
      if (c >= 0x80) {
8102
0
        return false;
8103
0
      }
8104
0
      written_out++;
8105
0
    }
8106
0
    input.remove_prefix(end_of_ascii + 1);
8107
0
  }
8108
0
  while (!input.empty()) {
8109
0
    int32_t oldi = i;
8110
0
    int32_t w = 1;
8111
0
    for (int32_t k = base;; k += base) {
8112
0
      if (input.empty()) {
8113
0
        return false;
8114
0
      }
8115
0
      uint8_t code_point = input.front();
8116
0
      input.remove_prefix(1);
8117
0
      int32_t digit = char_to_digit_value(code_point);
8118
0
      if (digit < 0) {
8119
0
        return false;
8120
0
      }
8121
0
      if (digit > (0x7fffffff - i) / w) {
8122
0
        return false;
8123
0
      }
8124
0
      i = i + digit * w;
8125
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8126
0
      if (digit < t) {
8127
0
        break;
8128
0
      }
8129
0
      if (w > 0x7fffffff / (base - t)) {
8130
0
        return false;
8131
0
      }
8132
0
      w = w * (base - t);
8133
0
    }
8134
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8135
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
8136
0
      return false;
8137
0
    }
8138
0
    n = n + i / int32_t(written_out + 1);
8139
0
    i = i % int32_t(written_out + 1);
8140
0
    if (n < 0x80) {
8141
0
      return false;
8142
0
    }
8143
0
    written_out++;
8144
0
    ++i;
8145
0
  }
8146
8147
0
  return true;
8148
0
}
8149
8150
0
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8151
0
  out.reserve(input.size() + out.size());
8152
0
  uint32_t n = initial_n;
8153
0
  int32_t d = 0;
8154
0
  int32_t bias = initial_bias;
8155
0
  size_t h = 0;
8156
  // first push the ascii content
8157
0
  for (uint32_t c : input) {
8158
0
    if (c < 0x80) {
8159
0
      ++h;
8160
0
      out.push_back(char(c));
8161
0
    }
8162
0
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8163
0
      return false;
8164
0
    }
8165
0
  }
8166
0
  size_t b = h;
8167
0
  if (b > 0) {
8168
0
    out.push_back('-');
8169
0
  }
8170
0
  while (h < input.size()) {
8171
0
    uint32_t m = 0x10FFFF;
8172
0
    for (auto code_point : input) {
8173
0
      if (code_point >= n && code_point < m) m = code_point;
8174
0
    }
8175
8176
0
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8177
0
      return false;
8178
0
    }
8179
0
    d = d + int32_t((m - n) * (h + 1));
8180
0
    n = m;
8181
0
    for (auto c : input) {
8182
0
      if (c < n) {
8183
0
        if (d == 0x7fffffff) {
8184
0
          return false;
8185
0
        }
8186
0
        ++d;
8187
0
      }
8188
0
      if (c == n) {
8189
0
        int32_t q = d;
8190
0
        for (int32_t k = base;; k += base) {
8191
0
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8192
8193
0
          if (q < t) {
8194
0
            break;
8195
0
          }
8196
0
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8197
0
          q = (q - t) / (base - t);
8198
0
        }
8199
0
        out.push_back(digit_to_char(q));
8200
0
        bias = adapt(d, int32_t(h + 1), h == b);
8201
0
        d = 0;
8202
0
        ++h;
8203
0
      }
8204
0
    }
8205
0
    ++d;
8206
0
    ++n;
8207
0
  }
8208
0
  return true;
8209
0
}
8210
8211
}  // namespace ada::idna
8212
/* end file src/punycode.cpp */
8213
/* begin file src/validity.cpp */
8214
#include <algorithm>
8215
#include <string_view>
8216
8217
namespace ada::idna {
8218
8219
enum direction : uint8_t {
8220
  NONE,
8221
  BN,
8222
  CS,
8223
  ES,
8224
  ON,
8225
  EN,
8226
  L,
8227
  R,
8228
  NSM,
8229
  AL,
8230
  AN,
8231
  ET,
8232
  WS,
8233
  RLO,
8234
  LRO,
8235
  PDF,
8236
  RLE,
8237
  RLI,
8238
  FSI,
8239
  PDI,
8240
  LRI,
8241
  B,
8242
  S,
8243
  LRE
8244
};
8245
8246
struct directions {
8247
  uint32_t start_code;
8248
  uint32_t final_code;
8249
  direction direct;
8250
};
8251
8252
static directions dir_table[] = {
8253
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8254
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8255
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8256
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8257
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8258
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8259
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8260
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8261
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8262
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8263
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8264
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8265
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8266
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8267
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8268
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8269
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8270
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8271
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8272
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8273
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8274
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8275
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8276
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8277
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8278
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8279
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8280
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8281
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8282
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8283
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8284
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8285
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8286
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8287
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8288
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8289
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8290
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8291
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8292
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8293
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8294
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8295
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8296
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8297
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8298
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8299
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8300
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8301
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8302
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8303
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8304
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8305
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8306
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8307
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8308
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8309
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8310
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8311
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8312
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8313
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8314
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8315
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8316
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8317
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8318
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8319
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8320
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8321
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8322
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8323
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8324
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8325
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8326
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8327
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8328
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8329
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8330
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8331
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8332
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8333
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8334
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8335
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8336
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8337
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8338
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8339
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8340
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8341
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8342
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8343
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8344
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8345
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8346
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8347
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8348
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8349
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8350
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8351
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8352
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8353
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8354
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8355
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8356
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8357
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8358
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8359
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8360
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8361
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8362
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8363
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8364
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8365
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8366
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8367
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8368
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8369
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8370
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8371
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8372
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8373
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8374
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8375
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8376
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8377
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8378
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8379
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8380
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8381
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8382
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8383
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8384
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8385
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8386
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8387
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8388
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8389
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8390
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8391
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8392
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8393
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8394
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8395
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8396
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8397
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8398
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8399
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8400
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8401
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8402
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8403
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8404
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8405
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8406
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8407
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8408
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8409
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8410
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8411
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8412
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8413
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8414
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8415
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8416
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8417
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8418
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8419
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8420
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8421
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8422
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8423
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8424
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8425
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8426
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8427
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8428
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8429
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8430
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8431
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8432
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8433
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8434
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8435
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8436
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8437
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8438
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8439
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8440
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8441
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8442
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8443
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8444
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8445
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8446
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8447
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8448
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8449
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8450
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8451
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8452
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8453
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8454
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8455
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8456
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8457
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8458
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8459
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8460
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8461
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8462
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8463
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8464
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8465
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8466
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8467
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8468
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8469
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8470
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8471
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8472
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8473
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8474
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8475
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8476
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8477
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8478
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8479
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8480
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8481
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8482
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8483
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8484
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8485
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8486
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8487
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8488
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8489
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8490
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8491
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8492
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8493
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8494
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8495
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8496
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8497
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8498
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8499
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8500
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8501
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8502
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8503
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8504
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8505
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8506
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8507
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8508
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8509
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8510
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8511
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8512
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8513
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8514
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8515
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8516
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8517
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8518
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8519
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8520
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8521
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8522
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8523
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8524
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8525
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8526
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8527
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8528
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8529
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8530
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8531
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8532
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8533
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8534
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8535
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8536
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8537
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8538
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8539
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8540
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8541
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8542
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8543
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8544
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8545
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8546
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8547
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8548
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8549
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8550
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8551
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8552
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8553
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8554
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8555
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8556
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8557
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8558
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8559
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8560
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8561
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8562
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8563
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8564
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8565
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8566
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8567
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8568
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8569
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8570
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8571
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8572
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8573
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8574
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8575
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8576
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8577
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8578
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8579
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8580
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8581
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8582
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8583
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8584
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8585
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8586
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8587
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8588
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8589
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8590
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8591
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8592
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8593
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8594
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8595
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8596
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8597
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8598
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8599
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8600
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8601
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8602
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8603
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8604
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8605
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8606
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8607
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8608
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8609
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8610
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8611
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8612
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8613
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8614
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8615
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8616
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8617
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8618
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8619
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8620
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8621
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8622
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8623
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8624
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8625
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8626
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8627
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8628
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8629
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8630
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8631
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8632
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8633
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8634
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8635
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8636
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8637
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8638
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8639
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8640
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8641
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8642
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8643
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8644
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8645
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8646
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8647
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8648
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8649
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8650
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8651
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8652
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8653
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8654
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8655
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8656
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8657
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8658
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8659
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8660
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8661
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8662
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8663
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8664
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8665
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8666
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8667
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8668
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8669
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8670
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8671
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8672
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8673
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8674
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8675
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8676
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8677
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8678
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8679
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8680
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8681
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8682
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8683
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8684
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8685
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8686
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8687
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8688
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8689
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8690
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8691
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8692
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8693
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8694
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8695
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8696
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8697
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8698
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8699
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8700
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8701
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8702
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8703
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8704
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8705
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8706
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8707
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8708
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8709
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8710
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8711
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8712
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8713
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8714
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8715
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8716
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8717
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8718
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8719
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8720
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8721
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8722
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8723
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8724
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8725
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8726
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8727
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8728
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8729
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8730
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8731
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8732
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8733
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8734
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8735
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8736
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8737
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8738
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8739
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8740
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8741
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8742
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8743
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8744
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8745
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8746
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8747
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8748
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8749
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8750
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8751
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8752
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8753
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8754
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8755
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8756
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8757
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8758
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8759
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8760
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8761
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8762
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8763
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8764
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8765
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8766
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8767
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8768
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8769
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8770
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8771
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8772
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8773
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8774
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8775
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8776
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8777
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8778
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8779
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8780
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8781
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8782
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8783
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8784
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8785
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8786
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8787
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8788
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8789
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8790
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8791
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8792
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8793
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8794
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8795
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8796
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8797
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8798
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8799
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8800
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8801
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8802
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8803
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8804
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8805
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8806
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8807
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8808
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8809
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8810
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8811
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8812
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8813
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8814
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8815
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8816
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8817
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8818
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8819
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8820
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8821
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8822
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8823
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8824
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8825
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8826
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8827
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8828
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8829
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8830
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8831
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8832
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8833
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8834
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8835
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8836
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8837
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8838
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8839
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8840
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8841
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8842
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8843
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8844
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8845
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8846
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8847
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8848
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8849
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8850
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8851
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8852
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8853
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8854
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8855
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8856
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8857
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8858
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8859
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8860
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8861
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8862
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8863
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8864
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8865
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8866
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8867
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8868
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8869
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8870
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8871
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8872
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8873
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8874
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8875
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8876
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8877
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8878
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8879
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8880
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8881
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8882
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8883
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8884
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8885
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8886
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8887
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8888
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8889
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8890
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8891
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8892
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8893
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8894
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8895
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8896
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8897
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8898
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8899
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8900
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8901
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8902
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8903
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8904
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8905
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8906
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8907
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8908
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8909
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8910
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8911
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8912
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8913
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8914
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8915
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8916
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8917
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8918
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8919
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8920
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8921
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8922
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8923
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8924
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8925
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8926
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8927
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8928
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8929
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8930
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8931
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8932
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8933
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8934
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8935
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8936
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8937
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8938
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8939
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8940
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8941
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8942
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8943
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8944
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8945
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8946
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8947
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8948
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8949
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8950
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8951
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8952
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8953
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8954
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8955
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8956
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8957
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8958
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8959
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8960
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8961
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8962
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8963
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8964
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8965
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8966
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8967
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8968
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8969
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8970
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8971
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8972
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8973
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8974
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8975
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8976
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8977
    {0x100000, 0x10fffd, direction::L}};
8978
8979
// CheckJoiners and CheckBidi are true for URL specification.
8980
8981
0
inline static direction find_direction(uint32_t code_point) noexcept {
8982
0
  auto it = std::lower_bound(
8983
0
      std::begin(dir_table), std::end(dir_table), code_point,
8984
0
      [](const directions& d, uint32_t c) { return d.final_code < c; });
8985
8986
  // next check is almost surely in vain, but we use it for safety.
8987
0
  if (it == std::end(dir_table)) {
8988
0
    return direction::NONE;
8989
0
  }
8990
  // We have that d.final_code >= c.
8991
0
  if (code_point >= it->start_code) {
8992
0
    return it->direct;
8993
0
  }
8994
0
  return direction::NONE;
8995
0
}
8996
8997
inline static size_t find_last_not_of_nsm(
8998
0
    const std::u32string_view label) noexcept {
8999
0
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9000
0
    if (find_direction(label[i]) != direction::NSM) return i;
9001
9002
0
  return std::u32string_view::npos;
9003
0
}
9004
9005
// An RTL label is a label that contains at least one character of type R, AL,
9006
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9007
0
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9008
0
  const size_t mask =
9009
0
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9010
9011
0
  size_t directions = 0;
9012
0
  for (size_t i = 0; i < label.size(); i++) {
9013
0
    directions |= 1u << find_direction(label[i]);
9014
0
  }
9015
0
  return (directions & mask) != 0;
9016
0
}
9017
9018
0
bool is_label_valid(const std::u32string_view label) {
9019
0
  if (label.empty()) {
9020
0
    return true;
9021
0
  }
9022
9023
  ///////////////
9024
  // We have a normalization step which ensures that we are in NFC.
9025
  // If we receive punycode, we normalize and check that the normalized
9026
  // version matches the original.
9027
  // --------------------------------------
9028
  // The label must be in Unicode Normalization Form NFC.
9029
9030
  // Current URL standard indicatest that CheckHyphens is set to false.
9031
  // ---------------------------------------
9032
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9033
  // in both the third and fourth positions. If CheckHyphens, the label must
9034
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9035
9036
  // This is not necessary because we segment the
9037
  // labels by '.'.
9038
  // ---------------------------------------
9039
  // The label must not contain a U+002E ( . ) FULL STOP.
9040
  // if (label.find('.') != std::string_view::npos) return false;
9041
9042
  // The label must not begin with a combining mark, that is:
9043
  // General_Category=Mark.
9044
0
  constexpr static uint32_t combining[] = {
9045
0
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9046
0
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9047
0
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9048
0
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9049
0
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9050
0
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9051
0
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9052
0
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9053
0
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9054
0
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9055
0
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9056
0
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9057
0
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9058
0
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9059
0
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9060
0
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9061
0
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9062
0
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9063
0
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9064
0
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9065
0
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9066
0
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9067
0
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9068
0
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9069
0
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9070
0
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9071
0
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9072
0
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9073
0
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9074
0
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9075
0
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9076
0
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9077
0
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9078
0
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9079
0
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9080
0
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9081
0
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9082
0
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9083
0
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9084
0
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9085
0
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9086
0
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9087
0
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9088
0
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9089
0
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9090
0
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9091
0
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9092
0
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9093
0
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9094
0
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9095
0
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9096
0
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9097
0
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9098
0
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9099
0
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9100
0
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9101
0
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9102
0
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9103
0
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9104
0
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9105
0
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9106
0
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9107
0
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9108
0
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9109
0
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9110
0
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9111
0
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9112
0
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9113
0
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9114
0
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9115
0
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9116
0
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9117
0
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9118
0
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9119
0
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9120
0
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9121
0
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9122
0
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9123
0
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9124
0
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9125
0
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9126
0
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9127
0
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9128
0
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9129
0
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9130
0
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9131
0
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9132
0
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9133
0
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9134
0
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9135
0
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9136
0
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9137
0
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9138
0
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9139
0
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9140
0
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9141
0
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9142
0
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9143
0
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9144
0
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9145
0
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9146
0
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9147
0
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9148
0
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9149
0
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9150
0
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9151
0
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9152
0
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9153
0
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9154
0
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9155
0
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9156
0
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9157
0
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9158
0
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9159
0
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9160
0
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9161
0
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9162
0
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9163
0
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9164
0
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9165
0
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9166
0
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9167
0
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9168
0
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9169
0
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9170
0
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9171
0
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9172
0
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9173
0
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9174
0
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9175
0
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9176
0
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9177
0
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9178
0
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9179
0
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9180
0
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9181
0
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9182
0
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9183
0
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9184
0
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9185
0
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9186
0
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9187
0
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9188
0
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9189
0
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9190
0
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9191
0
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9192
0
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9193
0
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9194
0
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9195
0
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9196
0
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9197
0
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9198
0
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9199
0
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9200
0
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9201
0
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9202
0
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9203
0
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9204
0
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9205
0
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9206
0
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9207
0
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9208
0
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9209
0
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9210
0
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9211
0
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9212
0
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9213
0
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9214
0
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9215
0
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9216
0
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9217
0
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9218
0
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9219
0
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9220
0
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9221
0
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9222
0
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9223
0
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9224
0
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9225
0
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9226
0
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9227
0
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9228
0
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9229
0
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9230
0
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9231
0
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9232
0
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9233
0
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9234
0
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9235
0
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9236
0
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9237
0
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9238
0
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9239
0
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9240
0
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9241
0
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9242
0
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9243
0
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9244
0
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9245
0
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9246
0
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9247
0
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9248
0
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9249
0
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9250
0
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9251
0
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9252
0
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9253
0
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9254
0
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9255
0
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9256
0
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9257
0
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9258
0
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9259
0
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9260
0
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9261
0
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9262
0
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9263
0
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9264
0
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9265
0
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9266
0
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9267
0
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9268
0
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9269
0
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9270
0
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9271
0
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9272
0
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9273
0
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9274
0
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9275
0
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9276
0
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9277
0
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9278
0
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9279
0
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9280
0
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9281
0
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9282
0
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9283
0
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9284
0
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9285
0
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9286
0
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9287
0
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9288
0
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9289
0
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9290
0
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9291
0
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9292
0
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9293
0
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9294
0
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9295
0
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9296
0
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9297
0
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9298
0
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9299
0
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9300
0
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9301
0
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9302
0
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9303
0
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9304
0
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9305
0
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9306
0
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9307
0
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9308
0
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9309
0
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9310
0
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9311
0
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9312
0
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9313
0
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9314
0
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9315
0
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9316
0
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9317
0
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9318
0
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9319
0
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9320
0
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9321
0
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9322
0
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9323
0
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9324
0
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9325
0
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9326
0
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9327
0
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9328
0
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9329
0
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9330
0
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9331
0
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9332
0
  if (std::binary_search(std::begin(combining), std::end(combining),
9333
0
                         label.front())) {
9334
0
    return false;
9335
0
  }
9336
  // We verify this next step as part of the mapping:
9337
  // ---------------------------------------------
9338
  // Each code point in the label must only have certain status values
9339
  // according to Section 5, IDNA Mapping Table:
9340
  // - For Transitional Processing, each value must be valid.
9341
  // - For Nontransitional Processing, each value must be either valid or
9342
  // deviation.
9343
9344
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9345
  // A, in The Unicode Code Points and Internationalized Domain Names for
9346
  // Applications (IDNA) [IDNA2008].
9347
0
  constexpr static uint32_t virama[] = {
9348
0
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9349
0
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9350
0
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9351
0
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9352
0
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9353
0
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9354
0
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9355
0
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9356
0
  constexpr static uint32_t R[] = {
9357
0
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9358
0
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9359
0
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9360
0
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9361
0
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9362
0
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9363
0
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9364
0
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9365
0
  constexpr static uint32_t L[] = {0xa872};
9366
0
  constexpr static uint32_t D[] = {
9367
0
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9368
0
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9369
0
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9370
0
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9371
0
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9372
0
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9373
0
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9374
0
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9375
0
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9376
0
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9377
0
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9378
0
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9379
0
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9380
0
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9381
0
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9382
0
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9383
0
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9384
0
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9385
0
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9386
0
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9387
0
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9388
0
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9389
0
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9390
0
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9391
0
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9392
0
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9393
0
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9394
0
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9395
0
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9396
0
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9397
0
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9398
0
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9399
0
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9400
0
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9401
0
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9402
0
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9403
0
      0xa870, 0xa871};
9404
9405
0
  for (size_t i = 0; i < label.size(); i++) {
9406
0
    uint32_t c = label[i];
9407
0
    if (c == 0x200c) {
9408
0
      if (i > 0) {
9409
0
        if (std::binary_search(std::begin(virama), std::end(virama),
9410
0
                               label[i - 1])) {
9411
0
          return true;
9412
0
        }
9413
0
      }
9414
0
      if ((i == 0) || (i + 1 >= label.size())) {
9415
0
        return false;
9416
0
      }
9417
      // we go backward looking for L or D
9418
0
      auto is_l_or_d = [](uint32_t code) {
9419
0
        return std::binary_search(std::begin(L), std::end(L), code) ||
9420
0
               std::binary_search(std::begin(D), std::end(D), code);
9421
0
      };
9422
0
      auto is_r_or_d = [](uint32_t code) {
9423
0
        return std::binary_search(std::begin(R), std::end(R), code) ||
9424
0
               std::binary_search(std::begin(D), std::end(D), code);
9425
0
      };
9426
0
      std::u32string_view before = label.substr(0, i);
9427
0
      std::u32string_view after = label.substr(i + 1);
9428
0
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9429
0
              before.end()) &&
9430
0
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9431
0
              after.end());
9432
0
    } else if (c == 0x200d) {
9433
0
      if (i > 0) {
9434
0
        if (std::binary_search(std::begin(virama), std::end(virama),
9435
0
                               label[i - 1])) {
9436
0
          return true;
9437
0
        }
9438
0
      }
9439
0
      return false;
9440
0
    }
9441
0
  }
9442
9443
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9444
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9445
  // Section 2.
9446
9447
  // The following rule, consisting of six conditions, applies to labels
9448
  // in Bidi domain names.  The requirements that this rule satisfies are
9449
  // described in Section 3.  All of the conditions must be satisfied for
9450
  // the rule to be satisfied.
9451
  //
9452
  //  1.  The first character must be a character with Bidi property L, R,
9453
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9454
  //     has the L property, it is an LTR label.
9455
  //
9456
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9457
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9458
  //
9459
  //   3.  In an RTL label, the end of the label must be a character with
9460
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9461
  //       characters with Bidi property NSM.
9462
  //
9463
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9464
  //       vice versa.
9465
  //
9466
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9467
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9468
  //
9469
  //   6.  In an LTR label, the end of the label must be a character with
9470
  //       Bidi property L or EN, followed by zero or more characters with
9471
  //       Bidi property NSM.
9472
9473
0
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9474
0
  if (last_non_nsm_char == std::u32string_view::npos) {
9475
0
    return false;
9476
0
  }
9477
9478
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9479
  // The following rule, consisting of six conditions, applies to labels in Bidi
9480
  // domain names.
9481
0
  if (is_rtl_label(label)) {
9482
    // The first character must be a character with Bidi property L, R,
9483
    // or AL. If it has the R or AL property, it is an RTL label; if it
9484
    // has the L property, it is an LTR label.
9485
9486
0
    if (find_direction(label[0]) == direction::L) {
9487
      // Eval as LTR
9488
9489
      // In an LTR label, only characters with the Bidi properties L, EN,
9490
      // ES, CS, ET, ON, BN, or NSM are allowed.
9491
0
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9492
0
        const direction d = find_direction(label[i]);
9493
0
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9494
0
              d == direction::CS || d == direction::ET || d == direction::ON ||
9495
0
              d == direction::BN || d == direction::NSM)) {
9496
0
          return false;
9497
0
        }
9498
9499
0
        if ((i == last_non_nsm_char) &&
9500
0
            !(d == direction::L || d == direction::EN)) {
9501
0
          return false;
9502
0
        }
9503
0
      }
9504
9505
0
      return true;
9506
9507
0
    } else {
9508
      // Eval as RTL
9509
9510
0
      bool has_an = false;
9511
0
      bool has_en = false;
9512
0
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9513
0
        const direction d = find_direction(label[i]);
9514
9515
        // NOLINTBEGIN(bugprone-assignment-in-if-condition)
9516
        // In an RTL label, if an EN is present, no AN may be present, and vice
9517
        // versa.
9518
0
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9519
0
            (d == direction::AN && ((has_an = true) && has_en))) {
9520
0
          return false;
9521
0
        }
9522
        // NOLINTEND(bugprone-assignment-in-if-condition)
9523
9524
0
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9525
0
              d == direction::EN || d == direction::ES || d == direction::CS ||
9526
0
              d == direction::ET || d == direction::ON || d == direction::BN ||
9527
0
              d == direction::NSM)) {
9528
0
          return false;
9529
0
        }
9530
9531
0
        if (i == last_non_nsm_char &&
9532
0
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9533
0
              d == direction::EN)) {
9534
0
          return false;
9535
0
        }
9536
0
      }
9537
9538
0
      return true;
9539
0
    }
9540
0
  }
9541
9542
0
  return true;
9543
0
}
9544
9545
}  // namespace ada::idna
9546
/* end file src/validity.cpp */
9547
/* begin file src/to_ascii.cpp */
9548
9549
#include <algorithm>
9550
#include <cstdint>
9551
#include <ranges>
9552
9553
9554
#ifdef ADA_USE_SIMDUTF
9555
#include "simdutf.h"
9556
#endif
9557
9558
namespace ada::idna {
9559
9560
0
bool constexpr is_ascii(std::u32string_view view) {
9561
0
  for (uint32_t c : view) {
9562
0
    if (c >= 0x80) {
9563
0
      return false;
9564
0
    }
9565
0
  }
9566
0
  return true;
9567
0
}
9568
9569
0
bool constexpr is_ascii(std::string_view view) {
9570
0
  for (uint8_t c : view) {
9571
0
    if (c >= 0x80) {
9572
0
      return false;
9573
0
    }
9574
0
  }
9575
0
  return true;
9576
0
}
9577
9578
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9579
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9580
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9581
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9582
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9583
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9584
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9585
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9586
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9587
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9588
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9589
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9590
9591
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9592
9593
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9594
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9595
0
}
9596
9597
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9598
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9599
0
}
9600
9601
// We return "" on error.
9602
0
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9603
0
  static const std::string error = "";
9604
  // copy and map
9605
  // we could be more efficient by avoiding the copy when unnecessary.
9606
0
  std::string mapped_string = std::string(ut8_string);
9607
0
  ascii_map(mapped_string.data(), mapped_string.size());
9608
0
  std::string out;
9609
0
  size_t label_start = 0;
9610
9611
0
  while (label_start != mapped_string.size()) {
9612
0
    size_t loc_dot = mapped_string.find('.', label_start);
9613
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9614
0
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9615
0
                                      : loc_dot - label_start;
9616
0
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9617
0
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9618
0
    label_start += label_size_with_dot;
9619
0
    if (label_size == 0) {
9620
      // empty label? Nothing to do.
9621
0
    } else if (label_view.starts_with("xn--")) {
9622
      // The xn-- part is the expensive game.
9623
0
      out.append(label_view);
9624
0
      std::string_view puny_segment_ascii(
9625
0
          out.data() + out.size() - label_view.size() + 4,
9626
0
          label_view.size() - 4);
9627
0
      std::u32string tmp_buffer;
9628
0
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9629
0
      if (!is_ok) {
9630
0
        return error;
9631
0
      }
9632
      // If the input is just ASCII, it should not have been encoded
9633
      // as punycode.
9634
      // https://github.com/whatwg/url/issues/760
9635
0
      if (is_ascii(tmp_buffer)) {
9636
0
        return error;
9637
0
      }
9638
0
      std::u32string post_map = ada::idna::map(tmp_buffer);
9639
0
      if (tmp_buffer != post_map) {
9640
0
        return error;
9641
0
      }
9642
0
      std::u32string pre_normal = post_map;
9643
0
      normalize(post_map);
9644
0
      if (post_map != pre_normal) {
9645
0
        return error;
9646
0
      }
9647
0
      if (post_map.empty()) {
9648
0
        return error;
9649
0
      }
9650
0
      if (!is_label_valid(post_map)) {
9651
0
        return error;
9652
0
      }
9653
0
    } else {
9654
0
      out.append(label_view);
9655
0
    }
9656
0
    if (!is_last_label) {
9657
0
      out.push_back('.');
9658
0
    }
9659
0
  }
9660
0
  return out;
9661
0
}
9662
9663
// We return "" on error.
9664
0
std::string to_ascii(std::string_view ut8_string) {
9665
0
  if (is_ascii(ut8_string)) {
9666
0
    return from_ascii_to_ascii(ut8_string);
9667
0
  }
9668
0
  static const std::string error = "";
9669
  // We convert to UTF-32
9670
9671
#ifdef ADA_USE_SIMDUTF
9672
  size_t utf32_length =
9673
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9674
  std::u32string utf32(utf32_length, '\0');
9675
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9676
      ut8_string.data(), ut8_string.size(), utf32.data());
9677
#else
9678
0
  size_t utf32_length =
9679
0
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9680
0
  std::u32string utf32(utf32_length, '\0');
9681
0
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9682
0
      ut8_string.data(), ut8_string.size(), utf32.data());
9683
0
#endif
9684
0
  if (actual_utf32_length == 0) {
9685
0
    return error;
9686
0
  }
9687
  // mapping
9688
0
  utf32 = ada::idna::map(utf32);
9689
0
  normalize(utf32);
9690
0
  std::string out;
9691
0
  size_t label_start = 0;
9692
9693
0
  while (label_start != utf32.size()) {
9694
0
    size_t loc_dot = utf32.find('.', label_start);
9695
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9696
0
    size_t label_size =
9697
0
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9698
0
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9699
0
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9700
0
    label_start += label_size_with_dot;
9701
0
    if (label_size == 0) {
9702
      // empty label? Nothing to do.
9703
0
    } else if (label_view.starts_with(U"xn--")) {
9704
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9705
0
      for (char32_t c : label_view) {
9706
0
        if (c >= 0x80) {
9707
0
          return error;
9708
0
        }
9709
0
        out += (unsigned char)(c);
9710
0
      }
9711
0
      std::string_view puny_segment_ascii(
9712
0
          out.data() + out.size() - label_view.size() + 4,
9713
0
          label_view.size() - 4);
9714
0
      std::u32string tmp_buffer;
9715
0
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9716
0
      if (!is_ok) {
9717
0
        return error;
9718
0
      }
9719
      // If the input is just ASCII, it should not have been encoded
9720
      // as punycode.
9721
      // https://github.com/whatwg/url/issues/760
9722
0
      if (is_ascii(tmp_buffer)) {
9723
0
        return error;
9724
0
      }
9725
0
      std::u32string post_map = ada::idna::map(tmp_buffer);
9726
0
      if (tmp_buffer != post_map) {
9727
0
        return error;
9728
0
      }
9729
0
      std::u32string pre_normal = post_map;
9730
0
      normalize(post_map);
9731
0
      if (post_map != pre_normal) {
9732
0
        return error;
9733
0
      }
9734
0
      if (post_map.empty()) {
9735
0
        return error;
9736
0
      }
9737
0
      if (!is_label_valid(post_map)) {
9738
0
        return error;
9739
0
      }
9740
0
    } else {
9741
      // The fast path here is an ascii label.
9742
0
      if (is_ascii(label_view)) {
9743
        // no validation needed.
9744
0
        for (char32_t c : label_view) {
9745
0
          out += (unsigned char)(c);
9746
0
        }
9747
0
      } else {
9748
        // slow path.
9749
        // first check validity.
9750
0
        if (!is_label_valid(label_view)) {
9751
0
          return error;
9752
0
        }
9753
        // It is valid! So now we must encode it as punycode...
9754
0
        out.append("xn--");
9755
0
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9756
0
        if (!is_ok) {
9757
0
          return error;
9758
0
        }
9759
0
      }
9760
0
    }
9761
0
    if (!is_last_label) {
9762
0
      out.push_back('.');
9763
0
    }
9764
0
  }
9765
0
  return out;
9766
0
}
9767
}  // namespace ada::idna
9768
/* end file src/to_ascii.cpp */
9769
/* begin file src/to_unicode.cpp */
9770
9771
#include <algorithm>
9772
#include <string>
9773
9774
9775
#ifdef ADA_USE_SIMDUTF
9776
#include "simdutf.h"
9777
#endif
9778
9779
namespace ada::idna {
9780
0
std::string to_unicode(std::string_view input) {
9781
0
  std::string output;
9782
0
  output.reserve(input.size());
9783
9784
0
  size_t label_start = 0;
9785
0
  while (label_start < input.size()) {
9786
0
    size_t loc_dot = input.find('.', label_start);
9787
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9788
0
    size_t label_size =
9789
0
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9790
0
    auto label_view = std::string_view(input.data() + label_start, label_size);
9791
9792
0
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9793
0
      label_view.remove_prefix(4);
9794
0
      if (ada::idna::verify_punycode(label_view)) {
9795
0
        std::u32string tmp_buffer;
9796
0
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9797
#ifdef ADA_USE_SIMDUTF
9798
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9799
                                                           tmp_buffer.size());
9800
          std::string final_utf8(utf8_size, '\0');
9801
          simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9802
                                         final_utf8.data());
9803
#else
9804
0
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9805
0
                                                             tmp_buffer.size());
9806
0
          std::string final_utf8(utf8_size, '\0');
9807
0
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9808
0
                                   final_utf8.data());
9809
0
#endif
9810
0
          output.append(final_utf8);
9811
0
        } else {
9812
          // ToUnicode never fails.  If any step fails, then the original input
9813
          // sequence is returned immediately in that step.
9814
0
          output.append(
9815
0
              std::string_view(input.data() + label_start, label_size));
9816
0
        }
9817
0
      } else {
9818
0
        output.append(std::string_view(input.data() + label_start, label_size));
9819
0
      }
9820
0
    } else {
9821
0
      output.append(label_view);
9822
0
    }
9823
9824
0
    if (!is_last_label) {
9825
0
      output.push_back('.');
9826
0
    }
9827
9828
0
    label_start += label_size + 1;
9829
0
  }
9830
9831
0
  return output;
9832
0
}
9833
}  // namespace ada::idna
9834
/* end file src/to_unicode.cpp */
9835
/* begin file src/identifier.cpp */
9836
9837
#include <algorithm>
9838
#include <array>
9839
#include <string>
9840
9841
/* begin file src/id_tables.cpp */
9842
// IDNA  16.0.0
9843
9844
// clang-format off
9845
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9846
#define ADA_IDNA_IDENTIFIER_TABLES_H
9847
#include <cstdint>
9848
9849
namespace ada::idna {
9850
9851
const uint32_t id_continue[1393][2] =
9852
{
9853
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9854
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9855
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9856
  {444, 447}, {448, 451}, {452, 659}, {660, 660},
9857
  {661, 687}, {688, 705}, {710, 721}, {736, 740},
9858
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9859
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9860
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9861
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9862
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9863
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9864
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9865
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9866
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9867
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9868
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9869
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9870
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9871
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9872
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9873
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9874
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9875
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9876
  {2185, 2190}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9877
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9878
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9879
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9880
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9881
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9882
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
9883
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
9884
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
9885
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
9886
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
9887
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
9888
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
9889
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
9890
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
9891
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
9892
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
9893
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
9894
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
9895
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
9896
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
9897
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
9898
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
9899
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
9900
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
9901
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
9902
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
9903
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
9904
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
9905
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
9906
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
9907
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
9908
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
9909
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
9910
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
9911
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
9912
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
9913
  {3157, 3158}, {3160, 3162}, {3165, 3165}, {3168, 3169},
9914
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
9915
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
9916
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
9917
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
9918
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
9919
  {3293, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
9920
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
9921
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
9922
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
9923
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
9924
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
9925
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
9926
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
9927
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
9928
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
9929
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
9930
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
9931
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
9932
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
9933
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
9934
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
9935
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
9936
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
9937
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
9938
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
9939
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
9940
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
9941
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
9942
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
9943
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
9944
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
9945
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
9946
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
9947
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
9948
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
9949
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
9950
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
9951
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
9952
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
9953
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
9954
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
9955
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
9956
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
9957
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
9958
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
9959
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
9960
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
9961
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
9962
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
9963
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
9964
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
9965
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
9966
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
9967
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
9968
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
9969
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
9970
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
9971
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
9972
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
9973
  {6832, 6845}, {6847, 6862}, {6912, 6915}, {6916, 6916},
9974
  {6917, 6963}, {6964, 6964}, {6965, 6965}, {6966, 6970},
9975
  {6971, 6971}, {6972, 6972}, {6973, 6977}, {6978, 6978},
9976
  {6979, 6980}, {6981, 6988}, {6992, 7001}, {7019, 7027},
9977
  {7040, 7041}, {7042, 7042}, {7043, 7072}, {7073, 7073},
9978
  {7074, 7077}, {7078, 7079}, {7080, 7081}, {7082, 7082},
9979
  {7083, 7085}, {7086, 7087}, {7088, 7097}, {7098, 7141},
9980
  {7142, 7142}, {7143, 7143}, {7144, 7145}, {7146, 7148},
9981
  {7149, 7149}, {7150, 7150}, {7151, 7153}, {7154, 7155},
9982
  {7168, 7203}, {7204, 7211}, {7212, 7219}, {7220, 7221},
9983
  {7222, 7223}, {7232, 7241}, {7245, 7247}, {7248, 7257},
9984
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
9985
  {7357, 7359}, {7376, 7378}, {7380, 7392}, {7393, 7393},
9986
  {7394, 7400}, {7401, 7404}, {7405, 7405}, {7406, 7411},
9987
  {7412, 7412}, {7413, 7414}, {7415, 7415}, {7416, 7417},
9988
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
9989
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7616, 7679},
9990
  {7680, 7957}, {7960, 7965}, {7968, 8005}, {8008, 8013},
9991
  {8016, 8023}, {8025, 8025}, {8027, 8027}, {8029, 8029},
9992
  {8031, 8061}, {8064, 8116}, {8118, 8124}, {8126, 8126},
9993
  {8130, 8132}, {8134, 8140}, {8144, 8147}, {8150, 8155},
9994
  {8160, 8172}, {8178, 8180}, {8182, 8188}, {8204, 8205},
9995
  {8255, 8256}, {8276, 8276}, {8305, 8305}, {8319, 8319},
9996
  {8336, 8348}, {8400, 8412}, {8417, 8417}, {8421, 8432},
9997
  {8450, 8450}, {8455, 8455}, {8458, 8467}, {8469, 8469},
9998
  {8472, 8472}, {8473, 8477}, {8484, 8484}, {8486, 8486},
9999
  {8488, 8488}, {8490, 8493}, {8494, 8494}, {8495, 8500},
10000
  {8501, 8504}, {8505, 8505}, {8508, 8511}, {8517, 8521},
10001
  {8526, 8526}, {8544, 8578}, {8579, 8580}, {8581, 8584},
10002
  {11264, 11387}, {11388, 11389}, {11390, 11492}, {11499, 11502},
10003
  {11503, 11505}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10004
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11647, 11647},
10005
  {11648, 11670}, {11680, 11686}, {11688, 11694}, {11696, 11702},
10006
  {11704, 11710}, {11712, 11718}, {11720, 11726}, {11728, 11734},
10007
  {11736, 11742}, {11744, 11775}, {12293, 12293}, {12294, 12294},
10008
  {12295, 12295}, {12321, 12329}, {12330, 12333}, {12334, 12335},
10009
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10010
  {12353, 12438}, {12441, 12442}, {12443, 12444}, {12445, 12446},
10011
  {12447, 12447}, {12449, 12538}, {12539, 12539}, {12540, 12542},
10012
  {12543, 12543}, {12549, 12591}, {12593, 12686}, {12704, 12735},
10013
  {12784, 12799}, {13312, 19903}, {19968, 40980}, {40981, 40981},
10014
  {40982, 42124}, {42192, 42231}, {42232, 42237}, {42240, 42507},
10015
  {42508, 42508}, {42512, 42527}, {42528, 42537}, {42538, 42539},
10016
  {42560, 42605}, {42606, 42606}, {42607, 42607}, {42612, 42621},
10017
  {42623, 42623}, {42624, 42651}, {42652, 42653}, {42654, 42655},
10018
  {42656, 42725}, {42726, 42735}, {42736, 42737}, {42775, 42783},
10019
  {42786, 42863}, {42864, 42864}, {42865, 42887}, {42888, 42888},
10020
  {42891, 42894}, {42895, 42895}, {42896, 42957}, {42960, 42961},
10021
  {42963, 42963}, {42965, 42972}, {42994, 42996}, {42997, 42998},
10022
  {42999, 42999}, {43000, 43001}, {43002, 43002}, {43003, 43009},
10023
  {43010, 43010}, {43011, 43013}, {43014, 43014}, {43015, 43018},
10024
  {43019, 43019}, {43020, 43042}, {43043, 43044}, {43045, 43046},
10025
  {43047, 43047}, {43052, 43052}, {43072, 43123}, {43136, 43137},
10026
  {43138, 43187}, {43188, 43203}, {43204, 43205}, {43216, 43225},
10027
  {43232, 43249}, {43250, 43255}, {43259, 43259}, {43261, 43262},
10028
  {43263, 43263}, {43264, 43273}, {43274, 43301}, {43302, 43309},
10029
  {43312, 43334}, {43335, 43345}, {43346, 43347}, {43360, 43388},
10030
  {43392, 43394}, {43395, 43395}, {43396, 43442}, {43443, 43443},
10031
  {43444, 43445}, {43446, 43449}, {43450, 43451}, {43452, 43453},
10032
  {43454, 43456}, {43471, 43471}, {43472, 43481}, {43488, 43492},
10033
  {43493, 43493}, {43494, 43494}, {43495, 43503}, {43504, 43513},
10034
  {43514, 43518}, {43520, 43560}, {43561, 43566}, {43567, 43568},
10035
  {43569, 43570}, {43571, 43572}, {43573, 43574}, {43584, 43586},
10036
  {43587, 43587}, {43588, 43595}, {43596, 43596}, {43597, 43597},
10037
  {43600, 43609}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10038
  {43642, 43642}, {43643, 43643}, {43644, 43644}, {43645, 43645},
10039
  {43646, 43695}, {43696, 43696}, {43697, 43697}, {43698, 43700},
10040
  {43701, 43702}, {43703, 43704}, {43705, 43709}, {43710, 43711},
10041
  {43712, 43712}, {43713, 43713}, {43714, 43714}, {43739, 43740},
10042
  {43741, 43741}, {43744, 43754}, {43755, 43755}, {43756, 43757},
10043
  {43758, 43759}, {43762, 43762}, {43763, 43764}, {43765, 43765},
10044
  {43766, 43766}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10045
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10046
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10047
  {44003, 44004}, {44005, 44005}, {44006, 44007}, {44008, 44008},
10048
  {44009, 44010}, {44012, 44012}, {44013, 44013}, {44016, 44025},
10049
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10050
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10051
  {64286, 64286}, {64287, 64296}, {64298, 64310}, {64312, 64316},
10052
  {64318, 64318}, {64320, 64321}, {64323, 64324}, {64326, 64433},
10053
  {64467, 64829}, {64848, 64911}, {64914, 64967}, {65008, 65019},
10054
  {65024, 65039}, {65056, 65071}, {65075, 65076}, {65101, 65103},
10055
  {65136, 65140}, {65142, 65276}, {65296, 65305}, {65313, 65338},
10056
  {65343, 65343}, {65345, 65370}, {65381, 65381}, {65382, 65391},
10057
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10058
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10059
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10060
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10061
  {66045, 66045}, {66176, 66204}, {66208, 66256}, {66272, 66272},
10062
  {66304, 66335}, {66349, 66368}, {66369, 66369}, {66370, 66377},
10063
  {66378, 66378}, {66384, 66421}, {66422, 66426}, {66432, 66461},
10064
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10065
  {66640, 66717}, {66720, 66729}, {66736, 66771}, {66776, 66811},
10066
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10067
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10068
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10069
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10070
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10071
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10072
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10073
  {67872, 67897}, {67968, 68023}, {68030, 68031}, {68096, 68096},
10074
  {68097, 68099}, {68101, 68102}, {68108, 68111}, {68112, 68115},
10075
  {68117, 68119}, {68121, 68149}, {68152, 68154}, {68159, 68159},
10076
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10077
  {68325, 68326}, {68352, 68405}, {68416, 68437}, {68448, 68466},
10078
  {68480, 68497}, {68608, 68680}, {68736, 68786}, {68800, 68850},
10079
  {68864, 68899}, {68900, 68903}, {68912, 68921}, {68928, 68937},
10080
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10081
  {68969, 68973}, {68975, 68975}, {68976, 68997}, {69248, 69289},
10082
  {69291, 69292}, {69296, 69297}, {69314, 69316}, {69372, 69375},
10083
  {69376, 69404}, {69415, 69415}, {69424, 69445}, {69446, 69456},
10084
  {69488, 69505}, {69506, 69509}, {69552, 69572}, {69600, 69622},
10085
  {69632, 69632}, {69633, 69633}, {69634, 69634}, {69635, 69687},
10086
  {69688, 69702}, {69734, 69743}, {69744, 69744}, {69745, 69746},
10087
  {69747, 69748}, {69749, 69749}, {69759, 69761}, {69762, 69762},
10088
  {69763, 69807}, {69808, 69810}, {69811, 69814}, {69815, 69816},
10089
  {69817, 69818}, {69826, 69826}, {69840, 69864}, {69872, 69881},
10090
  {69888, 69890}, {69891, 69926}, {69927, 69931}, {69932, 69932},
10091
  {69933, 69940}, {69942, 69951}, {69956, 69956}, {69957, 69958},
10092
  {69959, 69959}, {69968, 70002}, {70003, 70003}, {70006, 70006},
10093
  {70016, 70017}, {70018, 70018}, {70019, 70066}, {70067, 70069},
10094
  {70070, 70078}, {70079, 70080}, {70081, 70084}, {70089, 70092},
10095
  {70094, 70094}, {70095, 70095}, {70096, 70105}, {70106, 70106},
10096
  {70108, 70108}, {70144, 70161}, {70163, 70187}, {70188, 70190},
10097
  {70191, 70193}, {70194, 70195}, {70196, 70196}, {70197, 70197},
10098
  {70198, 70199}, {70206, 70206}, {70207, 70208}, {70209, 70209},
10099
  {70272, 70278}, {70280, 70280}, {70282, 70285}, {70287, 70301},
10100
  {70303, 70312}, {70320, 70366}, {70367, 70367}, {70368, 70370},
10101
  {70371, 70378}, {70384, 70393}, {70400, 70401}, {70402, 70403},
10102
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10103
  {70450, 70451}, {70453, 70457}, {70459, 70460}, {70461, 70461},
10104
  {70462, 70463}, {70464, 70464}, {70465, 70468}, {70471, 70472},
10105
  {70475, 70477}, {70480, 70480}, {70487, 70487}, {70493, 70497},
10106
  {70498, 70499}, {70502, 70508}, {70512, 70516}, {70528, 70537},
10107
  {70539, 70539}, {70542, 70542}, {70544, 70581}, {70583, 70583},
10108
  {70584, 70586}, {70587, 70592}, {70594, 70594}, {70597, 70597},
10109
  {70599, 70602}, {70604, 70605}, {70606, 70606}, {70607, 70607},
10110
  {70608, 70608}, {70609, 70609}, {70610, 70610}, {70611, 70611},
10111
  {70625, 70626}, {70656, 70708}, {70709, 70711}, {70712, 70719},
10112
  {70720, 70721}, {70722, 70724}, {70725, 70725}, {70726, 70726},
10113
  {70727, 70730}, {70736, 70745}, {70750, 70750}, {70751, 70753},
10114
  {70784, 70831}, {70832, 70834}, {70835, 70840}, {70841, 70841},
10115
  {70842, 70842}, {70843, 70846}, {70847, 70848}, {70849, 70849},
10116
  {70850, 70851}, {70852, 70853}, {70855, 70855}, {70864, 70873},
10117
  {71040, 71086}, {71087, 71089}, {71090, 71093}, {71096, 71099},
10118
  {71100, 71101}, {71102, 71102}, {71103, 71104}, {71128, 71131},
10119
  {71132, 71133}, {71168, 71215}, {71216, 71218}, {71219, 71226},
10120
  {71227, 71228}, {71229, 71229}, {71230, 71230}, {71231, 71232},
10121
  {71236, 71236}, {71248, 71257}, {71296, 71338}, {71339, 71339},
10122
  {71340, 71340}, {71341, 71341}, {71342, 71343}, {71344, 71349},
10123
  {71350, 71350}, {71351, 71351}, {71352, 71352}, {71360, 71369},
10124
  {71376, 71395}, {71424, 71450}, {71453, 71453}, {71454, 71454},
10125
  {71455, 71455}, {71456, 71457}, {71458, 71461}, {71462, 71462},
10126
  {71463, 71467}, {71472, 71481}, {71488, 71494}, {71680, 71723},
10127
  {71724, 71726}, {71727, 71735}, {71736, 71736}, {71737, 71738},
10128
  {71840, 71903}, {71904, 71913}, {71935, 71942}, {71945, 71945},
10129
  {71948, 71955}, {71957, 71958}, {71960, 71983}, {71984, 71989},
10130
  {71991, 71992}, {71995, 71996}, {71997, 71997}, {71998, 71998},
10131
  {71999, 71999}, {72000, 72000}, {72001, 72001}, {72002, 72002},
10132
  {72003, 72003}, {72016, 72025}, {72096, 72103}, {72106, 72144},
10133
  {72145, 72147}, {72148, 72151}, {72154, 72155}, {72156, 72159},
10134
  {72160, 72160}, {72161, 72161}, {72163, 72163}, {72164, 72164},
10135
  {72192, 72192}, {72193, 72202}, {72203, 72242}, {72243, 72248},
10136
  {72249, 72249}, {72250, 72250}, {72251, 72254}, {72263, 72263},
10137
  {72272, 72272}, {72273, 72278}, {72279, 72280}, {72281, 72283},
10138
  {72284, 72329}, {72330, 72342}, {72343, 72343}, {72344, 72345},
10139
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72688, 72697},
10140
  {72704, 72712}, {72714, 72750}, {72751, 72751}, {72752, 72758},
10141
  {72760, 72765}, {72766, 72766}, {72767, 72767}, {72768, 72768},
10142
  {72784, 72793}, {72818, 72847}, {72850, 72871}, {72873, 72873},
10143
  {72874, 72880}, {72881, 72881}, {72882, 72883}, {72884, 72884},
10144
  {72885, 72886}, {72960, 72966}, {72968, 72969}, {72971, 73008},
10145
  {73009, 73014}, {73018, 73018}, {73020, 73021}, {73023, 73029},
10146
  {73030, 73030}, {73031, 73031}, {73040, 73049}, {73056, 73061},
10147
  {73063, 73064}, {73066, 73097}, {73098, 73102}, {73104, 73105},
10148
  {73107, 73108}, {73109, 73109}, {73110, 73110}, {73111, 73111},
10149
  {73112, 73112}, {73120, 73129}, {73440, 73458}, {73459, 73460},
10150
  {73461, 73462}, {73472, 73473}, {73474, 73474}, {73475, 73475},
10151
  {73476, 73488}, {73490, 73523}, {73524, 73525}, {73526, 73530},
10152
  {73534, 73535}, {73536, 73536}, {73537, 73537}, {73538, 73538},
10153
  {73552, 73561}, {73562, 73562}, {73648, 73648}, {73728, 74649},
10154
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10155
  {78912, 78912}, {78913, 78918}, {78919, 78933}, {78944, 82938},
10156
  {82944, 83526}, {90368, 90397}, {90398, 90409}, {90410, 90412},
10157
  {90413, 90415}, {90416, 90425}, {92160, 92728}, {92736, 92766},
10158
  {92768, 92777}, {92784, 92862}, {92864, 92873}, {92880, 92909},
10159
  {92912, 92916}, {92928, 92975}, {92976, 92982}, {92992, 92995},
10160
  {93008, 93017}, {93027, 93047}, {93053, 93071}, {93504, 93506},
10161
  {93507, 93546}, {93547, 93548}, {93552, 93561}, {93760, 93823},
10162
  {93952, 94026}, {94031, 94031}, {94032, 94032}, {94033, 94087},
10163
  {94095, 94098}, {94099, 94111}, {94176, 94177}, {94179, 94179},
10164
  {94180, 94180}, {94192, 94193}, {94208, 100343}, {100352, 101589},
10165
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10166
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10167
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10168
  {113792, 113800}, {113808, 113817}, {113821, 113822}, {118000, 118009},
10169
  {118528, 118573}, {118576, 118598}, {119141, 119142}, {119143, 119145},
10170
  {119149, 119154}, {119163, 119170}, {119173, 119179}, {119210, 119213},
10171
  {119362, 119364}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10172
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10173
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10174
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10175
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10176
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10177
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10178
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {120782, 120831},
10179
  {121344, 121398}, {121403, 121452}, {121461, 121461}, {121476, 121476},
10180
  {121499, 121503}, {121505, 121519}, {122624, 122633}, {122634, 122634},
10181
  {122635, 122654}, {122661, 122666}, {122880, 122886}, {122888, 122904},
10182
  {122907, 122913}, {122915, 122916}, {122918, 122922}, {122928, 122989},
10183
  {123023, 123023}, {123136, 123180}, {123184, 123190}, {123191, 123197},
10184
  {123200, 123209}, {123214, 123214}, {123536, 123565}, {123566, 123566},
10185
  {123584, 123627}, {123628, 123631}, {123632, 123641}, {124112, 124138},
10186
  {124139, 124139}, {124140, 124143}, {124144, 124153}, {124368, 124397},
10187
  {124398, 124399}, {124400, 124400}, {124401, 124410}, {124896, 124902},
10188
  {124904, 124907}, {124909, 124910}, {124912, 124926}, {124928, 125124},
10189
  {125136, 125142}, {125184, 125251}, {125252, 125258}, {125259, 125259},
10190
  {125264, 125273}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10191
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10192
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10193
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10194
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10195
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10196
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10197
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10198
  {126629, 126633}, {126635, 126651}, {130032, 130041}, {131072, 173791},
10199
  {173824, 177977}, {177984, 178205}, {178208, 183969}, {183984, 191456},
10200
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 205743},
10201
  {917760, 917999}
10202
};
10203
const uint32_t id_start[763][2] =
10204
{
10205
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10206
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10207
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10208
  {660, 660}, {661, 687}, {688, 705}, {710, 721},
10209
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10210
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10211
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10212
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10213
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10214
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10215
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10216
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10217
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10218
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10219
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10220
  {2160, 2183}, {2185, 2190}, {2208, 2248}, {2249, 2249},
10221
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10222
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10223
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10224
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10225
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10226
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10227
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10228
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10229
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10230
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10231
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10232
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10233
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10234
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10235
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10236
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10237
  {3160, 3162}, {3165, 3165}, {3168, 3169}, {3200, 3200},
10238
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10239
  {3253, 3257}, {3261, 3261}, {3293, 3294}, {3296, 3297},
10240
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10241
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10242
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10243
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10244
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10245
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10246
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10247
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10248
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10249
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10250
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10251
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10252
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10253
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10254
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10255
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10256
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10257
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10258
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10259
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10260
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10261
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10262
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10263
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10264
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10265
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10266
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10267
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10268
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10269
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10270
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10271
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10272
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10273
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10274
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10275
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10276
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10277
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10278
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10279
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10280
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10281
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10282
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10283
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10284
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10285
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10286
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10287
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10288
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10289
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10290
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10291
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10292
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10293
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10294
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10295
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42957},
10296
  {42960, 42961}, {42963, 42963}, {42965, 42972}, {42994, 42996},
10297
  {42997, 42998}, {42999, 42999}, {43000, 43001}, {43002, 43002},
10298
  {43003, 43009}, {43011, 43013}, {43015, 43018}, {43020, 43042},
10299
  {43072, 43123}, {43138, 43187}, {43250, 43255}, {43259, 43259},
10300
  {43261, 43262}, {43274, 43301}, {43312, 43334}, {43360, 43388},
10301
  {43396, 43442}, {43471, 43471}, {43488, 43492}, {43494, 43494},
10302
  {43495, 43503}, {43514, 43518}, {43520, 43560}, {43584, 43586},
10303
  {43588, 43595}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10304
  {43642, 43642}, {43646, 43695}, {43697, 43697}, {43701, 43702},
10305
  {43705, 43709}, {43712, 43712}, {43714, 43714}, {43739, 43740},
10306
  {43741, 43741}, {43744, 43754}, {43762, 43762}, {43763, 43764},
10307
  {43777, 43782}, {43785, 43790}, {43793, 43798}, {43808, 43814},
10308
  {43816, 43822}, {43824, 43866}, {43868, 43871}, {43872, 43880},
10309
  {43881, 43881}, {43888, 43967}, {43968, 44002}, {44032, 55203},
10310
  {55216, 55238}, {55243, 55291}, {63744, 64109}, {64112, 64217},
10311
  {64256, 64262}, {64275, 64279}, {64285, 64285}, {64287, 64296},
10312
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10313
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10314
  {64914, 64967}, {65008, 65019}, {65136, 65140}, {65142, 65276},
10315
  {65313, 65338}, {65345, 65370}, {65382, 65391}, {65392, 65392},
10316
  {65393, 65437}, {65438, 65439}, {65440, 65470}, {65474, 65479},
10317
  {65482, 65487}, {65490, 65495}, {65498, 65500}, {65536, 65547},
10318
  {65549, 65574}, {65576, 65594}, {65596, 65597}, {65599, 65613},
10319
  {65616, 65629}, {65664, 65786}, {65856, 65908}, {66176, 66204},
10320
  {66208, 66256}, {66304, 66335}, {66349, 66368}, {66369, 66369},
10321
  {66370, 66377}, {66378, 66378}, {66384, 66421}, {66432, 66461},
10322
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10323
  {66640, 66717}, {66736, 66771}, {66776, 66811}, {66816, 66855},
10324
  {66864, 66915}, {66928, 66938}, {66940, 66954}, {66956, 66962},
10325
  {66964, 66965}, {66967, 66977}, {66979, 66993}, {66995, 67001},
10326
  {67003, 67004}, {67008, 67059}, {67072, 67382}, {67392, 67413},
10327
  {67424, 67431}, {67456, 67461}, {67463, 67504}, {67506, 67514},
10328
  {67584, 67589}, {67592, 67592}, {67594, 67637}, {67639, 67640},
10329
  {67644, 67644}, {67647, 67669}, {67680, 67702}, {67712, 67742},
10330
  {67808, 67826}, {67828, 67829}, {67840, 67861}, {67872, 67897},
10331
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68112, 68115},
10332
  {68117, 68119}, {68121, 68149}, {68192, 68220}, {68224, 68252},
10333
  {68288, 68295}, {68297, 68324}, {68352, 68405}, {68416, 68437},
10334
  {68448, 68466}, {68480, 68497}, {68608, 68680}, {68736, 68786},
10335
  {68800, 68850}, {68864, 68899}, {68938, 68941}, {68942, 68942},
10336
  {68943, 68943}, {68944, 68965}, {68975, 68975}, {68976, 68997},
10337
  {69248, 69289}, {69296, 69297}, {69314, 69316}, {69376, 69404},
10338
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10339
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10340
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10341
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10342
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10343
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10344
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10345
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10346
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10347
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10348
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10349
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10350
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10351
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10352
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10353
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10354
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10355
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10356
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10357
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10358
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10359
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10360
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73440, 73458},
10361
  {73474, 73474}, {73476, 73488}, {73490, 73523}, {73648, 73648},
10362
  {73728, 74649}, {74752, 74862}, {74880, 75075}, {77712, 77808},
10363
  {77824, 78895}, {78913, 78918}, {78944, 82938}, {82944, 83526},
10364
  {90368, 90397}, {92160, 92728}, {92736, 92766}, {92784, 92862},
10365
  {92880, 92909}, {92928, 92975}, {92992, 92995}, {93027, 93047},
10366
  {93053, 93071}, {93504, 93506}, {93507, 93546}, {93547, 93548},
10367
  {93760, 93823}, {93952, 94026}, {94032, 94032}, {94099, 94111},
10368
  {94176, 94177}, {94179, 94179}, {94208, 100343}, {100352, 101589},
10369
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10370
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10371
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10372
  {113792, 113800}, {113808, 113817}, {119808, 119892}, {119894, 119964},
10373
  {119966, 119967}, {119970, 119970}, {119973, 119974}, {119977, 119980},
10374
  {119982, 119993}, {119995, 119995}, {119997, 120003}, {120005, 120069},
10375
  {120071, 120074}, {120077, 120084}, {120086, 120092}, {120094, 120121},
10376
  {120123, 120126}, {120128, 120132}, {120134, 120134}, {120138, 120144},
10377
  {120146, 120485}, {120488, 120512}, {120514, 120538}, {120540, 120570},
10378
  {120572, 120596}, {120598, 120628}, {120630, 120654}, {120656, 120686},
10379
  {120688, 120712}, {120714, 120744}, {120746, 120770}, {120772, 120779},
10380
  {122624, 122633}, {122634, 122634}, {122635, 122654}, {122661, 122666},
10381
  {122928, 122989}, {123136, 123180}, {123191, 123197}, {123214, 123214},
10382
  {123536, 123565}, {123584, 123627}, {124112, 124138}, {124139, 124139},
10383
  {124368, 124397}, {124400, 124400}, {124896, 124902}, {124904, 124907},
10384
  {124909, 124910}, {124912, 124926}, {124928, 125124}, {125184, 125251},
10385
  {125259, 125259}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10386
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10387
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10388
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10389
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10390
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10391
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10392
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10393
  {126629, 126633}, {126635, 126651}, {131072, 173791}, {173824, 177977},
10394
  {177984, 178205}, {178208, 183969}, {183984, 191456}, {191472, 192093},
10395
  {194560, 195101}, {196608, 201546}, {201552, 205743}
10396
};
10397
10398
10399
} // namespace ada::idna
10400
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10401
/* end file src/id_tables.cpp */
10402
10403
namespace ada::idna {
10404
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10405
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10406
0
}
10407
10408
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10409
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10410
0
         (c >= '0' && c <= '9');
10411
0
}
10412
10413
0
bool valid_name_code_point(char32_t code_point, bool first) {
10414
  // https://tc39.es/ecma262/#prod-IdentifierStart
10415
  // Fast paths:
10416
0
  if (first &&
10417
0
      (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) {
10418
0
    return true;
10419
0
  }
10420
0
  if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) {
10421
0
    return true;
10422
0
  }
10423
  // Slow path...
10424
0
  if (code_point == 0xffffffff) {
10425
0
    return false;  // minimal error handling
10426
0
  }
10427
0
  if (first) {
10428
0
    auto iter = std::lower_bound(
10429
0
        std::begin(ada::idna::id_start), std::end(ada::idna::id_start),
10430
0
        code_point,
10431
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10432
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10433
0
  } else {
10434
0
    auto iter = std::lower_bound(
10435
0
        std::begin(id_continue), std::end(id_continue), code_point,
10436
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10437
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10438
0
  }
10439
0
}
10440
}  // namespace ada::idna
10441
/* end file src/identifier.cpp */
10442
/* end file src/idna.cpp */
10443
/* end file src/ada_idna.cpp */
10444
ADA_POP_DISABLE_WARNINGS
10445
10446
#include <algorithm>
10447
#if ADA_NEON
10448
#include <arm_neon.h>
10449
#elif ADA_SSE2
10450
#include <emmintrin.h>
10451
#elif ADA_LSX
10452
#include <lsxintrin.h>
10453
#elif ADA_RVV
10454
#include <riscv_vector.h>
10455
#endif
10456
10457
#include <ranges>
10458
10459
namespace ada::unicode {
10460
10461
0
constexpr bool is_tabs_or_newline(char c) noexcept {
10462
0
  return c == '\r' || c == '\n' || c == '\t';
10463
0
}
10464
10465
0
constexpr uint64_t broadcast(uint8_t v) noexcept {
10466
0
  return 0x101010101010101ull * v;
10467
0
}
10468
10469
0
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10470
0
  uint64_t broadcast_80 = broadcast(0x80);
10471
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10472
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10473
0
  uint64_t non_ascii = 0;
10474
0
  size_t i = 0;
10475
10476
0
  for (; i + 7 < length; i += 8) {
10477
0
    uint64_t word{};
10478
0
    memcpy(&word, input + i, sizeof(word));
10479
0
    non_ascii |= (word & broadcast_80);
10480
0
    word ^=
10481
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10482
0
    memcpy(input + i, &word, sizeof(word));
10483
0
  }
10484
0
  if (i < length) {
10485
0
    uint64_t word{};
10486
0
    memcpy(&word, input + i, length - i);
10487
0
    non_ascii |= (word & broadcast_80);
10488
0
    word ^=
10489
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10490
0
    memcpy(input + i, &word, length - i);
10491
0
  }
10492
0
  return non_ascii == 0;
10493
0
}
10494
#if ADA_NEON
10495
ada_really_inline bool has_tabs_or_newline(
10496
    std::string_view user_input) noexcept {
10497
  // first check for short strings in which case we do it naively.
10498
  if (user_input.size() < 16) {  // slow path
10499
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10500
  }
10501
  // fast path for long strings (expected to be common)
10502
  size_t i = 0;
10503
  /**
10504
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10505
   * on table lookup instruction. We notice that these are all unique numbers
10506
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10507
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10508
   * input register. If the input had `\t` in position X then this shuffled
10509
   * register will also have '\t' in that position. Comparing input with this
10510
   * shuffled register will mark us all interesting characters in the input.
10511
   *
10512
   * credit for algorithmic idea: @aqrit, credit for description:
10513
   * @DenisYaroshevskiy
10514
   */
10515
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10516
                                  0, 9, 10, 0, 0, 13, 0, 0};
10517
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10518
  // m['0xd', '0xa', '0x9']
10519
  uint8x16_t running{0};
10520
  for (; i + 15 < user_input.size(); i += 16) {
10521
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10522
10523
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10524
  }
10525
  if (i < user_input.size()) {
10526
    uint8x16_t word =
10527
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10528
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10529
  }
10530
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10531
}
10532
#elif ADA_SSE2
10533
ada_really_inline bool has_tabs_or_newline(
10534
0
    std::string_view user_input) noexcept {
10535
  // first check for short strings in which case we do it naively.
10536
0
  if (user_input.size() < 16) {  // slow path
10537
0
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10538
0
  }
10539
  // fast path for long strings (expected to be common)
10540
0
  size_t i = 0;
10541
0
  const __m128i mask1 = _mm_set1_epi8('\r');
10542
0
  const __m128i mask2 = _mm_set1_epi8('\n');
10543
0
  const __m128i mask3 = _mm_set1_epi8('\t');
10544
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10545
0
  __m128i running{0};
10546
0
  for (; i + 15 < user_input.size(); i += 16) {
10547
0
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10548
0
    running = _mm_or_si128(
10549
0
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10550
0
                                           _mm_cmpeq_epi8(word, mask2))),
10551
0
        _mm_cmpeq_epi8(word, mask3));
10552
0
  }
10553
0
  if (i < user_input.size()) {
10554
0
    __m128i word = _mm_loadu_si128(
10555
0
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10556
0
    running = _mm_or_si128(
10557
0
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10558
0
                                           _mm_cmpeq_epi8(word, mask2))),
10559
0
        _mm_cmpeq_epi8(word, mask3));
10560
0
  }
10561
0
  return _mm_movemask_epi8(running) != 0;
10562
0
}
10563
#elif ADA_LSX
10564
ada_really_inline bool has_tabs_or_newline(
10565
    std::string_view user_input) noexcept {
10566
  // first check for short strings in which case we do it naively.
10567
  if (user_input.size() < 16) {  // slow path
10568
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10569
  }
10570
  // fast path for long strings (expected to be common)
10571
  size_t i = 0;
10572
  const __m128i mask1 = __lsx_vrepli_b('\r');
10573
  const __m128i mask2 = __lsx_vrepli_b('\n');
10574
  const __m128i mask3 = __lsx_vrepli_b('\t');
10575
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10576
  __m128i running{0};
10577
  for (; i + 15 < user_input.size(); i += 16) {
10578
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10579
    running = __lsx_vor_v(
10580
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10581
                                         __lsx_vseq_b(word, mask2))),
10582
        __lsx_vseq_b(word, mask3));
10583
  }
10584
  if (i < user_input.size()) {
10585
    __m128i word = __lsx_vld(
10586
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10587
    running = __lsx_vor_v(
10588
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10589
                                         __lsx_vseq_b(word, mask2))),
10590
        __lsx_vseq_b(word, mask3));
10591
  }
10592
  if (__lsx_bz_v(running)) return false;
10593
  return true;
10594
}
10595
#elif ADA_RVV
10596
ada_really_inline bool has_tabs_or_newline(
10597
    std::string_view user_input) noexcept {
10598
  uint8_t* src = (uint8_t*)user_input.data();
10599
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10600
    vl = __riscv_vsetvl_e8m1(n);
10601
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10602
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10603
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10604
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10605
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10606
    long idx = __riscv_vfirst(m, vl);
10607
    if (idx >= 0) return true;
10608
  }
10609
  return false;
10610
}
10611
#else
10612
ada_really_inline bool has_tabs_or_newline(
10613
    std::string_view user_input) noexcept {
10614
  auto has_zero_byte = [](uint64_t v) {
10615
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10616
  };
10617
  size_t i = 0;
10618
  uint64_t mask1 = broadcast('\r');
10619
  uint64_t mask2 = broadcast('\n');
10620
  uint64_t mask3 = broadcast('\t');
10621
  uint64_t running{0};
10622
  for (; i + 7 < user_input.size(); i += 8) {
10623
    uint64_t word{};
10624
    memcpy(&word, user_input.data() + i, sizeof(word));
10625
    uint64_t xor1 = word ^ mask1;
10626
    uint64_t xor2 = word ^ mask2;
10627
    uint64_t xor3 = word ^ mask3;
10628
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10629
  }
10630
  if (i < user_input.size()) {
10631
    uint64_t word{};
10632
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10633
    uint64_t xor1 = word ^ mask1;
10634
    uint64_t xor2 = word ^ mask2;
10635
    uint64_t xor3 = word ^ mask3;
10636
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10637
  }
10638
  return running;
10639
}
10640
#endif
10641
10642
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10643
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10644
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10645
// U+007C (|).
10646
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10647
    []() consteval {
10648
      std::array<uint8_t, 256> result{};
10649
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10650
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10651
        result[c] = true;
10652
      }
10653
      return result;
10654
    }();
10655
10656
ada_really_inline constexpr bool is_forbidden_host_code_point(
10657
0
    const char c) noexcept {
10658
0
  return is_forbidden_host_code_point_table[uint8_t(c)];
10659
0
}
10660
10661
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10662
    []() consteval {
10663
      std::array<uint8_t, 256> result{};
10664
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10665
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10666
        result[c] = true;
10667
      }
10668
      for (uint8_t c = 0; c <= 32; c++) {
10669
        result[c] = true;
10670
      }
10671
      for (size_t c = 127; c < 255; c++) {
10672
        result[c] = true;
10673
      }
10674
      return result;
10675
    }();
10676
10677
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10678
10679
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10680
0
    const char c) noexcept {
10681
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10682
0
}
10683
10684
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10685
0
    const char* input, size_t length) noexcept {
10686
0
  size_t i = 0;
10687
0
  uint8_t accumulator{};
10688
0
  for (; i + 4 <= length; i += 4) {
10689
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10690
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10691
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10692
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10693
0
  }
10694
0
  for (; i < length; i++) {
10695
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10696
0
  }
10697
0
  return accumulator;
10698
0
}
10699
10700
constexpr static std::array<uint8_t, 256>
10701
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10702
      std::array<uint8_t, 256> result{};
10703
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10704
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10705
        result[c] = 1;
10706
      }
10707
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10708
        result[c] = 2;
10709
      }
10710
      for (uint8_t c = 0; c <= 32; c++) {
10711
        result[c] = 1;
10712
      }
10713
      for (size_t c = 127; c < 255; c++) {
10714
        result[c] = 1;
10715
      }
10716
      return result;
10717
    }();
10718
10719
ada_really_inline constexpr uint8_t
10720
contains_forbidden_domain_code_point_or_upper(const char* input,
10721
0
                                              size_t length) noexcept {
10722
0
  size_t i = 0;
10723
0
  uint8_t accumulator{};
10724
0
  for (; i + 4 <= length; i += 4) {
10725
0
    accumulator |=
10726
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10727
0
    accumulator |=
10728
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10729
0
    accumulator |=
10730
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10731
0
    accumulator |=
10732
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10733
0
  }
10734
0
  for (; i < length; i++) {
10735
0
    accumulator |=
10736
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10737
0
  }
10738
0
  return accumulator;
10739
0
}
10740
10741
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10742
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10743
  std::array<bool, 256> result{};
10744
  for (size_t c = 0; c < 256; c++) {
10745
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10746
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10747
  }
10748
  return result;
10749
}();
10750
10751
0
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10752
0
  return is_alnum_plus_table[uint8_t(c)];
10753
  // A table is almost surely much faster than the
10754
  // following under most compilers: return
10755
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10756
0
}
10757
10758
7.02k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10759
7.02k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10760
4.07k
         (c >= 'a' && c <= 'f');
10761
7.02k
}
10762
10763
0
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10764
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10765
  // inclusive.
10766
0
  return (c >= '0' && c <= '9');
10767
0
}
10768
10769
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10770
  // If code point is between U+0000 and U+007F inclusive, then return true.
10771
0
  return c <= 0x7F;
10772
0
}
10773
10774
0
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10775
0
  return (unsigned char)c <= ' ';
10776
0
}
10777
10778
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10779
0
    const char c) noexcept {
10780
0
  return c == '\t' || c == '\n' || c == '\r';
10781
0
}
10782
10783
constexpr std::string_view table_is_double_dot_path_segment[] = {
10784
    "..", "%2e.", ".%2e", "%2e%2e"};
10785
10786
ada_really_inline constexpr bool is_double_dot_path_segment(
10787
0
    std::string_view input) noexcept {
10788
  // This will catch most cases:
10789
  // The length must be 2,4 or 6.
10790
  // We divide by two and require
10791
  // that the result be between 1 and 3 inclusively.
10792
0
  uint64_t half_length = uint64_t(input.size()) / 2;
10793
0
  if (half_length - 1 > 2) {
10794
0
    return false;
10795
0
  }
10796
  // We have a string of length 2, 4 or 6.
10797
  // We now check the first character:
10798
0
  if ((input[0] != '.') && (input[0] != '%')) {
10799
0
    return false;
10800
0
  }
10801
  // We are unlikely the get beyond this point.
10802
0
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10803
0
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10804
0
  if (target.size() != input.size()) {
10805
0
    return false;
10806
0
  }
10807
  // We almost never get here.
10808
  // Optimizing the rest is relatively unimportant.
10809
0
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10810
0
    uint16_t A, B;
10811
0
    memcpy(&A, a.data(), sizeof(A));
10812
0
    memcpy(&B, b.data(), sizeof(B));
10813
0
    return A == B;
10814
0
  };
10815
0
  if (!prefix_equal_unsafe(input, target)) {
10816
0
    return false;
10817
0
  }
10818
0
  for (size_t i = 2; i < input.size(); i++) {
10819
0
    char c = input[i];
10820
0
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10821
0
      return false;
10822
0
    }
10823
0
  }
10824
0
  return true;
10825
  // The above code might be a bit better than the code below. Compilers
10826
  // are not stupid and may use the fact that these strings have length 2,4 and
10827
  // 6 and other tricks.
10828
  // return input == ".." ||
10829
  //  input == ".%2e" || input == ".%2E" ||
10830
  //  input == "%2e." || input == "%2E." ||
10831
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10832
  //  "%2e%2E";
10833
0
}
10834
10835
ada_really_inline constexpr bool is_single_dot_path_segment(
10836
0
    std::string_view input) noexcept {
10837
0
  return input == "." || input == "%2e" || input == "%2E";
10838
0
}
10839
10840
0
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10841
0
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10842
0
}
10843
10844
constexpr static char hex_to_binary_table[] = {
10845
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10846
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10847
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10848
3.38k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10849
3.38k
  return hex_to_binary_table[c - '0'];
10850
3.38k
}
10851
10852
7.54k
std::string percent_decode(const std::string_view input, size_t first_percent) {
10853
  // next line is for safety only, we expect users to avoid calling
10854
  // percent_decode when first_percent is outside the range.
10855
7.54k
  if (first_percent == std::string_view::npos) {
10856
5.27k
    return std::string(input);
10857
5.27k
  }
10858
2.26k
  std::string dest;
10859
2.26k
  dest.reserve(input.length());
10860
2.26k
  dest.append(input.substr(0, first_percent));
10861
2.26k
  const char* pointer = input.data() + first_percent;
10862
2.26k
  const char* end = input.data() + input.size();
10863
  // Optimization opportunity: if the following code gets
10864
  // called often, it can be optimized quite a bit.
10865
19.9k
  while (pointer < end) {
10866
17.7k
    const char ch = pointer[0];
10867
17.7k
    size_t remaining = end - pointer - 1;
10868
17.7k
    if (ch != '%' || remaining < 2 ||
10869
3.94k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10870
3.94k
            (!is_ascii_hex_digit(pointer[1]) ||
10871
16.0k
             !is_ascii_hex_digit(pointer[2])))) {
10872
16.0k
      dest += ch;
10873
16.0k
      pointer++;
10874
16.0k
    } else {
10875
1.69k
      unsigned a = convert_hex_to_binary(pointer[1]);
10876
1.69k
      unsigned b = convert_hex_to_binary(pointer[2]);
10877
1.69k
      char c = static_cast<char>(a * 16 + b);
10878
1.69k
      dest += c;
10879
1.69k
      pointer += 3;
10880
1.69k
    }
10881
17.7k
  }
10882
2.26k
  return dest;
10883
7.54k
}
10884
10885
std::string percent_encode(const std::string_view input,
10886
2.25k
                           const uint8_t character_set[]) {
10887
5.85k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10888
5.85k
    return character_sets::bit_at(character_set, c);
10889
5.85k
  });
10890
  // Optimization: Don't iterate if percent encode is not required
10891
2.25k
  if (pointer == input.end()) {
10892
1.17k
    return std::string(input);
10893
1.17k
  }
10894
10895
1.08k
  std::string result;
10896
1.08k
  result.reserve(input.length());  // in the worst case, percent encoding might
10897
                                   // produce 3 characters.
10898
1.08k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10899
10900
45.1k
  for (; pointer != input.end(); pointer++) {
10901
44.1k
    if (character_sets::bit_at(character_set, *pointer)) {
10902
35.0k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10903
35.0k
    } else {
10904
9.03k
      result += *pointer;
10905
9.03k
    }
10906
44.1k
  }
10907
10908
1.08k
  return result;
10909
2.25k
}
10910
10911
template <bool append>
10912
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10913
0
                    std::string& out) {
10914
0
  ada_log("percent_encode ", input, " to output string while ",
10915
0
          append ? "appending" : "overwriting");
10916
0
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10917
0
    return character_sets::bit_at(character_set, c);
10918
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
10919
0
  ada_log("percent_encode done checking, moved to ",
10920
0
          std::distance(input.begin(), pointer));
10921
10922
  // Optimization: Don't iterate if percent encode is not required
10923
0
  if (pointer == input.end()) {
10924
0
    ada_log("percent_encode encoding not needed.");
10925
0
    return false;
10926
0
  }
10927
0
  if constexpr (!append) {
10928
0
    out.clear();
10929
0
  }
10930
0
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10931
0
          " bytes");
10932
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10933
0
  out.append(input.data(), std::distance(input.begin(), pointer));
10934
0
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10935
0
          " bytes");
10936
0
  for (; pointer != input.end(); pointer++) {
10937
0
    if (character_sets::bit_at(character_set, *pointer)) {
10938
0
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10939
0
    } else {
10940
0
      out += *pointer;
10941
0
    }
10942
0
  }
10943
0
  return true;
10944
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> >&)
10945
10946
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10947
0
              size_t first_percent) {
10948
0
  std::string percent_decoded_buffer;
10949
0
  std::string_view input = plain;
10950
0
  if (first_percent != std::string_view::npos) {
10951
0
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10952
0
    input = percent_decoded_buffer;
10953
0
  }
10954
  // input is a non-empty UTF-8 string, must be percent decoded
10955
0
  std::string idna_ascii = ada::idna::to_ascii(input);
10956
0
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10957
0
                                idna_ascii.data(), idna_ascii.size())) {
10958
0
    return false;
10959
0
  }
10960
0
  out = std::move(idna_ascii);
10961
0
  return true;
10962
0
}
10963
10964
std::string percent_encode(const std::string_view input,
10965
0
                           const uint8_t character_set[], size_t index) {
10966
0
  std::string out;
10967
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10968
0
  out.append(input.data(), index);
10969
0
  auto pointer = input.begin() + index;
10970
0
  for (; pointer != input.end(); pointer++) {
10971
0
    if (character_sets::bit_at(character_set, *pointer)) {
10972
0
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10973
0
    } else {
10974
0
      out += *pointer;
10975
0
    }
10976
0
  }
10977
0
  return out;
10978
0
}
10979
10980
}  // namespace ada::unicode
10981
/* end file src/unicode.cpp */
10982
/* begin file src/serializers.cpp */
10983
#include <array>
10984
#include <charconv>
10985
#include <string>
10986
10987
namespace ada::serializers {
10988
10989
void find_longest_sequence_of_ipv6_pieces(
10990
    const std::array<uint16_t, 8>& address, size_t& compress,
10991
0
    size_t& compress_length) noexcept {
10992
0
  for (size_t i = 0; i < 8; i++) {
10993
0
    if (address[i] == 0) {
10994
0
      size_t next = i + 1;
10995
0
      while (next != 8 && address[next] == 0) ++next;
10996
0
      const size_t count = next - i;
10997
0
      if (compress_length < count) {
10998
0
        compress_length = count;
10999
0
        compress = i;
11000
0
        if (next == 8) break;
11001
0
        i = next;
11002
0
      }
11003
0
    }
11004
0
  }
11005
0
}
11006
11007
0
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
11008
0
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11009
0
  size_t compress = 0;         // The start of a long sequence of zeros.
11010
0
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11011
11012
0
  if (compress_length <= 1) {
11013
    // Optimization opportunity: Find a faster way then snprintf for imploding
11014
    // and return here.
11015
0
    compress = compress_length = 8;
11016
0
  }
11017
11018
0
  std::string output(4 * 8 + 7 + 2, '\0');
11019
0
  size_t piece_index = 0;
11020
0
  char* point = output.data();
11021
0
  char* point_end = output.data() + output.size();
11022
0
  *point++ = '[';
11023
0
  while (true) {
11024
0
    if (piece_index == compress) {
11025
0
      *point++ = ':';
11026
      // If we skip a value initially, we need to write '::', otherwise
11027
      // a single ':' will do since it follows a previous ':'.
11028
0
      if (piece_index == 0) {
11029
0
        *point++ = ':';
11030
0
      }
11031
0
      piece_index += compress_length;
11032
0
      if (piece_index == 8) {
11033
0
        break;
11034
0
      }
11035
0
    }
11036
0
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11037
0
    piece_index++;
11038
0
    if (piece_index == 8) {
11039
0
      break;
11040
0
    }
11041
0
    *point++ = ':';
11042
0
  }
11043
0
  *point++ = ']';
11044
0
  output.resize(point - output.data());
11045
0
  return output;
11046
0
}
11047
11048
0
std::string ipv4(const uint64_t address) noexcept {
11049
0
  std::string output(15, '\0');
11050
0
  char* point = output.data();
11051
0
  char* point_end = output.data() + output.size();
11052
0
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11053
0
  for (int i = 2; i >= 0; i--) {
11054
0
    *point++ = '.';
11055
0
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11056
0
  }
11057
0
  output.resize(point - output.data());
11058
0
  return output;
11059
0
}
11060
11061
}  // namespace ada::serializers
11062
/* end file src/serializers.cpp */
11063
/* begin file src/implementation.cpp */
11064
11065
#include <string_view>
11066
11067
11068
namespace ada {
11069
11070
template <class result_type>
11071
ada_warn_unused tl::expected<result_type, errors> parse(
11072
0
    std::string_view input, const result_type* base_url) {
11073
0
  result_type u =
11074
0
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11075
0
  if (!u.is_valid) {
11076
0
    return tl::unexpected(errors::type_error);
11077
0
  }
11078
0
  return u;
11079
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*)
11080
11081
template ada::result<url> parse<url>(std::string_view input,
11082
                                     const url* base_url = nullptr);
11083
template ada::result<url_aggregator> parse<url_aggregator>(
11084
    std::string_view input, const url_aggregator* base_url = nullptr);
11085
11086
0
std::string href_from_file(std::string_view input) {
11087
  // This is going to be much faster than constructing a URL.
11088
0
  std::string tmp_buffer;
11089
0
  std::string_view internal_input;
11090
0
  if (unicode::has_tabs_or_newline(input)) {
11091
0
    tmp_buffer = input;
11092
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11093
0
    internal_input = tmp_buffer;
11094
0
  } else {
11095
0
    internal_input = input;
11096
0
  }
11097
0
  std::string path;
11098
0
  if (internal_input.empty()) {
11099
0
    path = "/";
11100
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11101
0
    helpers::parse_prepared_path(internal_input.substr(1),
11102
0
                                 ada::scheme::type::FILE, path);
11103
0
  } else {
11104
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11105
0
  }
11106
0
  return "file://" + path;
11107
0
}
11108
11109
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
11110
0
  ada::url_aggregator base_aggregator;
11111
0
  ada::url_aggregator* base_pointer = nullptr;
11112
11113
0
  if (base_input != nullptr) {
11114
0
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11115
0
        *base_input, nullptr);
11116
0
    if (!base_aggregator.is_valid) {
11117
0
      return false;
11118
0
    }
11119
0
    base_pointer = &base_aggregator;
11120
0
  }
11121
11122
0
  ada::url_aggregator result =
11123
0
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11124
0
                                                              base_pointer);
11125
0
  return result.is_valid;
11126
0
}
11127
11128
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11129
0
  switch (type) {
11130
0
    case ada::encoding_type::UTF8:
11131
0
      return "UTF-8";
11132
0
    case ada::encoding_type::UTF_16LE:
11133
0
      return "UTF-16LE";
11134
0
    case ada::encoding_type::UTF_16BE:
11135
0
      return "UTF-16BE";
11136
0
    default:
11137
0
      unreachable();
11138
0
  }
11139
0
}
11140
11141
}  // namespace ada
11142
/* end file src/implementation.cpp */
11143
/* begin file src/helpers.cpp */
11144
#include <cstring>
11145
#include <sstream>
11146
11147
11148
namespace ada::helpers {
11149
11150
template <typename out_iter>
11151
0
void encode_json(std::string_view view, out_iter out) {
11152
  // trivial implementation. could be faster.
11153
0
  const char* hexvalues =
11154
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11155
0
  for (uint8_t c : view) {
11156
0
    if (c == '\\') {
11157
0
      *out++ = '\\';
11158
0
      *out++ = '\\';
11159
0
    } else if (c == '"') {
11160
0
      *out++ = '\\';
11161
0
      *out++ = '"';
11162
0
    } else if (c <= 0x1f) {
11163
0
      *out++ = '\\';
11164
0
      *out++ = 'u';
11165
0
      *out++ = '0';
11166
0
      *out++ = '0';
11167
0
      *out++ = hexvalues[2 * c];
11168
0
      *out++ = hexvalues[2 * c + 1];
11169
0
    } else {
11170
0
      *out++ = c;
11171
0
    }
11172
0
  }
11173
0
}
11174
11175
0
ada_unused std::string get_state(ada::state s) {
11176
0
  switch (s) {
11177
0
    case ada::state::AUTHORITY:
11178
0
      return "Authority";
11179
0
    case ada::state::SCHEME_START:
11180
0
      return "Scheme Start";
11181
0
    case ada::state::SCHEME:
11182
0
      return "Scheme";
11183
0
    case ada::state::HOST:
11184
0
      return "Host";
11185
0
    case ada::state::NO_SCHEME:
11186
0
      return "No Scheme";
11187
0
    case ada::state::FRAGMENT:
11188
0
      return "Fragment";
11189
0
    case ada::state::RELATIVE_SCHEME:
11190
0
      return "Relative Scheme";
11191
0
    case ada::state::RELATIVE_SLASH:
11192
0
      return "Relative Slash";
11193
0
    case ada::state::FILE:
11194
0
      return "File";
11195
0
    case ada::state::FILE_HOST:
11196
0
      return "File Host";
11197
0
    case ada::state::FILE_SLASH:
11198
0
      return "File Slash";
11199
0
    case ada::state::PATH_OR_AUTHORITY:
11200
0
      return "Path or Authority";
11201
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11202
0
      return "Special Authority Ignore Slashes";
11203
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11204
0
      return "Special Authority Slashes";
11205
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11206
0
      return "Special Relative or Authority";
11207
0
    case ada::state::QUERY:
11208
0
      return "Query";
11209
0
    case ada::state::PATH:
11210
0
      return "Path";
11211
0
    case ada::state::PATH_START:
11212
0
      return "Path Start";
11213
0
    case ada::state::OPAQUE_PATH:
11214
0
      return "Opaque Path";
11215
0
    case ada::state::PORT:
11216
0
      return "Port";
11217
0
    default:
11218
0
      return "unknown state";
11219
0
  }
11220
0
}
11221
11222
ada_really_inline std::optional<std::string_view> prune_hash(
11223
0
    std::string_view& input) noexcept {
11224
  // compiles down to 20--30 instructions including a class to memchr (C
11225
  // function). this function should be quite fast.
11226
0
  size_t location_of_first = input.find('#');
11227
0
  if (location_of_first == std::string_view::npos) {
11228
0
    return std::nullopt;
11229
0
  }
11230
0
  std::string_view hash = input;
11231
0
  hash.remove_prefix(location_of_first + 1);
11232
0
  input.remove_suffix(input.size() - location_of_first);
11233
0
  return hash;
11234
0
}
11235
11236
ada_really_inline bool shorten_path(std::string& path,
11237
0
                                    ada::scheme::type type) noexcept {
11238
  // Let path be url's path.
11239
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11240
  // Windows drive letter, then return.
11241
0
  if (type == ada::scheme::type::FILE &&
11242
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11243
0
    if (checkers::is_normalized_windows_drive_letter(
11244
0
            helpers::substring(path, 1))) {
11245
0
      return false;
11246
0
    }
11247
0
  }
11248
11249
  // Remove path's last item, if any.
11250
0
  size_t last_delimiter = path.rfind('/');
11251
0
  if (last_delimiter != std::string::npos) {
11252
0
    path.erase(last_delimiter);
11253
0
    return true;
11254
0
  }
11255
11256
0
  return false;
11257
0
}
11258
11259
ada_really_inline bool shorten_path(std::string_view& path,
11260
0
                                    ada::scheme::type type) noexcept {
11261
  // Let path be url's path.
11262
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11263
  // Windows drive letter, then return.
11264
0
  if (type == ada::scheme::type::FILE &&
11265
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11266
0
    if (checkers::is_normalized_windows_drive_letter(
11267
0
            helpers::substring(path, 1))) {
11268
0
      return false;
11269
0
    }
11270
0
  }
11271
11272
  // Remove path's last item, if any.
11273
0
  if (!path.empty()) {
11274
0
    size_t slash_loc = path.rfind('/');
11275
0
    if (slash_loc != std::string_view::npos) {
11276
0
      path.remove_suffix(path.size() - slash_loc);
11277
0
      return true;
11278
0
    }
11279
0
  }
11280
11281
0
  return false;
11282
0
}
11283
11284
ada_really_inline void remove_ascii_tab_or_newline(
11285
0
    std::string& input) noexcept {
11286
  // if this ever becomes a performance issue, we could use an approach similar
11287
  // to has_tabs_or_newline
11288
0
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11289
0
}
11290
11291
ada_really_inline constexpr std::string_view substring(std::string_view input,
11292
0
                                                       size_t pos) noexcept {
11293
0
  ADA_ASSERT_TRUE(pos <= input.size());
11294
  // The following is safer but unneeded if we have the above line:
11295
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11296
0
  return input.substr(pos);
11297
0
}
11298
11299
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11300
0
  ADA_ASSERT_TRUE(pos <= input.size());
11301
0
  input.remove_suffix(input.size() - pos);
11302
0
}
11303
11304
// computes the number of trailing zeroes
11305
// this is a private inline function only defined in this source file.
11306
0
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11307
#ifdef ADA_REGULAR_VISUAL_STUDIO
11308
  unsigned long ret;
11309
  // Search the mask data from least significant bit (LSB)
11310
  // to the most significant bit (MSB) for a set bit (1).
11311
  _BitScanForward(&ret, input_num);
11312
  return (int)ret;
11313
#else   // ADA_REGULAR_VISUAL_STUDIO
11314
0
  return __builtin_ctzl(input_num);
11315
0
#endif  // ADA_REGULAR_VISUAL_STUDIO
11316
0
}
11317
11318
// starting at index location, this finds the next location of a character
11319
// :, /, \\, ? or [. If none is found, view.size() is returned.
11320
// For use within get_host_delimiter_location.
11321
#if ADA_NEON
11322
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11323
// support direct initialization of uint8x16_t. See
11324
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11325
#ifndef ada_make_uint8x16_t
11326
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11327
                            x13, x14, x15, x16)                                \
11328
  ([=]() {                                                                     \
11329
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11330
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11331
    return vld1q_u8(array);                                                    \
11332
  }())
11333
#endif
11334
11335
ada_really_inline size_t find_next_host_delimiter_special(
11336
    std::string_view view, size_t location) noexcept {
11337
  // first check for short strings in which case we do it naively.
11338
  if (view.size() - location < 16) {  // slow path
11339
    for (size_t i = location; i < view.size(); i++) {
11340
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11341
          view[i] == '?' || view[i] == '[') {
11342
        return i;
11343
      }
11344
    }
11345
    return size_t(view.size());
11346
  }
11347
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11348
    uint8x16_t bit_mask =
11349
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11350
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11351
    uint8x16_t minput = vandq_u8(input, bit_mask);
11352
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11353
    tmp = vpaddq_u8(tmp, tmp);
11354
    tmp = vpaddq_u8(tmp, tmp);
11355
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11356
  };
11357
11358
  // fast path for long strings (expected to be common)
11359
  size_t i = location;
11360
  uint8x16_t low_mask =
11361
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11362
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11363
  uint8x16_t high_mask =
11364
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11365
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11366
  uint8x16_t fmask = vmovq_n_u8(0xf);
11367
  uint8x16_t zero{0};
11368
  for (; i + 15 < view.size(); i += 16) {
11369
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11370
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11371
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11372
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11373
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11374
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11375
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11376
      return i + trailing_zeroes(is_non_zero);
11377
    }
11378
  }
11379
11380
  if (i < view.size()) {
11381
    uint8x16_t word =
11382
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11383
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11384
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11385
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11386
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11387
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11388
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11389
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11390
    }
11391
  }
11392
  return size_t(view.size());
11393
}
11394
#elif ADA_SSE2
11395
ada_really_inline size_t find_next_host_delimiter_special(
11396
0
    std::string_view view, size_t location) noexcept {
11397
  // first check for short strings in which case we do it naively.
11398
0
  if (view.size() - location < 16) {  // slow path
11399
0
    for (size_t i = location; i < view.size(); i++) {
11400
0
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11401
0
          view[i] == '?' || view[i] == '[') {
11402
0
        return i;
11403
0
      }
11404
0
    }
11405
0
    return size_t(view.size());
11406
0
  }
11407
  // fast path for long strings (expected to be common)
11408
0
  size_t i = location;
11409
0
  const __m128i mask1 = _mm_set1_epi8(':');
11410
0
  const __m128i mask2 = _mm_set1_epi8('/');
11411
0
  const __m128i mask3 = _mm_set1_epi8('\\');
11412
0
  const __m128i mask4 = _mm_set1_epi8('?');
11413
0
  const __m128i mask5 = _mm_set1_epi8('[');
11414
11415
0
  for (; i + 15 < view.size(); i += 16) {
11416
0
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11417
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11418
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11419
0
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11420
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11421
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11422
0
    __m128i m = _mm_or_si128(
11423
0
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11424
0
    int mask = _mm_movemask_epi8(m);
11425
0
    if (mask != 0) {
11426
0
      return i + trailing_zeroes(mask);
11427
0
    }
11428
0
  }
11429
0
  if (i < view.size()) {
11430
0
    __m128i word =
11431
0
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11432
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11433
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11434
0
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11435
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11436
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11437
0
    __m128i m = _mm_or_si128(
11438
0
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11439
0
    int mask = _mm_movemask_epi8(m);
11440
0
    if (mask != 0) {
11441
0
      return view.length() - 16 + trailing_zeroes(mask);
11442
0
    }
11443
0
  }
11444
0
  return size_t(view.length());
11445
0
}
11446
#elif ADA_LSX
11447
ada_really_inline size_t find_next_host_delimiter_special(
11448
    std::string_view view, size_t location) noexcept {
11449
  // first check for short strings in which case we do it naively.
11450
  if (view.size() - location < 16) {  // slow path
11451
    for (size_t i = location; i < view.size(); i++) {
11452
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11453
          view[i] == '?' || view[i] == '[') {
11454
        return i;
11455
      }
11456
    }
11457
    return size_t(view.size());
11458
  }
11459
  // fast path for long strings (expected to be common)
11460
  size_t i = location;
11461
  const __m128i mask1 = __lsx_vrepli_b(':');
11462
  const __m128i mask2 = __lsx_vrepli_b('/');
11463
  const __m128i mask3 = __lsx_vrepli_b('\\');
11464
  const __m128i mask4 = __lsx_vrepli_b('?');
11465
  const __m128i mask5 = __lsx_vrepli_b('[');
11466
11467
  for (; i + 15 < view.size(); i += 16) {
11468
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11469
    __m128i m1 = __lsx_vseq_b(word, mask1);
11470
    __m128i m2 = __lsx_vseq_b(word, mask2);
11471
    __m128i m3 = __lsx_vseq_b(word, mask3);
11472
    __m128i m4 = __lsx_vseq_b(word, mask4);
11473
    __m128i m5 = __lsx_vseq_b(word, mask5);
11474
    __m128i m =
11475
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11476
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11477
    if (mask != 0) {
11478
      return i + trailing_zeroes(mask);
11479
    }
11480
  }
11481
  if (i < view.size()) {
11482
    __m128i word =
11483
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11484
    __m128i m1 = __lsx_vseq_b(word, mask1);
11485
    __m128i m2 = __lsx_vseq_b(word, mask2);
11486
    __m128i m3 = __lsx_vseq_b(word, mask3);
11487
    __m128i m4 = __lsx_vseq_b(word, mask4);
11488
    __m128i m5 = __lsx_vseq_b(word, mask5);
11489
    __m128i m =
11490
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11491
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11492
    if (mask != 0) {
11493
      return view.length() - 16 + trailing_zeroes(mask);
11494
    }
11495
  }
11496
  return size_t(view.length());
11497
}
11498
#elif ADA_RVV
11499
ada_really_inline size_t find_next_host_delimiter_special(
11500
    std::string_view view, size_t location) noexcept {
11501
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
11502
  // beeing faster on future hardware.
11503
#if 0
11504
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
11505
  static const uint8_t tbl[16] = {
11506
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
11507
  };
11508
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
11509
#endif
11510
  uint8_t* src = (uint8_t*)view.data() + location;
11511
  for (size_t vl, n = view.size() - location; n > 0;
11512
       n -= vl, src += vl, location += vl) {
11513
    vl = __riscv_vsetvl_e8m1(n);
11514
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11515
#if 0
11516
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
11517
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
11518
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
11519
#else
11520
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11521
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11522
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11523
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11524
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
11525
    vbool8_t m = __riscv_vmor(
11526
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
11527
        m5, vl);
11528
#endif
11529
    long idx = __riscv_vfirst(m, vl);
11530
    if (idx >= 0) return location + idx;
11531
  }
11532
  return size_t(view.size());
11533
}
11534
#else
11535
// : / [ \\ ?
11536
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11537
    []() consteval {
11538
      std::array<uint8_t, 256> result{};
11539
      for (int i : {':', '/', '[', '\\', '?'}) {
11540
        result[i] = 1;
11541
      }
11542
      return result;
11543
    }();
11544
// credit: @the-moisrex recommended a table-based approach
11545
ada_really_inline size_t find_next_host_delimiter_special(
11546
    std::string_view view, size_t location) noexcept {
11547
  auto const str = view.substr(location);
11548
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11549
    if (special_host_delimiters[(uint8_t)*pos]) {
11550
      return pos - str.begin() + location;
11551
    }
11552
  }
11553
  return size_t(view.size());
11554
}
11555
#endif
11556
11557
// starting at index location, this finds the next location of a character
11558
// :, /, ? or [. If none is found, view.size() is returned.
11559
// For use within get_host_delimiter_location.
11560
#if ADA_NEON
11561
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11562
                                                  size_t location) noexcept {
11563
  // first check for short strings in which case we do it naively.
11564
  if (view.size() - location < 16) {  // slow path
11565
    for (size_t i = location; i < view.size(); i++) {
11566
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11567
          view[i] == '[') {
11568
        return i;
11569
      }
11570
    }
11571
    return size_t(view.size());
11572
  }
11573
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11574
    uint8x16_t bit_mask =
11575
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11576
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11577
    uint8x16_t minput = vandq_u8(input, bit_mask);
11578
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11579
    tmp = vpaddq_u8(tmp, tmp);
11580
    tmp = vpaddq_u8(tmp, tmp);
11581
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11582
  };
11583
11584
  // fast path for long strings (expected to be common)
11585
  size_t i = location;
11586
  uint8x16_t low_mask =
11587
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11588
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11589
  uint8x16_t high_mask =
11590
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11591
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11592
  uint8x16_t fmask = vmovq_n_u8(0xf);
11593
  uint8x16_t zero{0};
11594
  for (; i + 15 < view.size(); i += 16) {
11595
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11596
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11597
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11598
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11599
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11600
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11601
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11602
      return i + trailing_zeroes(is_non_zero);
11603
    }
11604
  }
11605
11606
  if (i < view.size()) {
11607
    uint8x16_t word =
11608
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11609
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11610
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11611
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11612
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11613
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11614
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11615
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11616
    }
11617
  }
11618
  return size_t(view.size());
11619
}
11620
#elif ADA_SSE2
11621
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11622
0
                                                  size_t location) noexcept {
11623
  // first check for short strings in which case we do it naively.
11624
0
  if (view.size() - location < 16) {  // slow path
11625
0
    for (size_t i = location; i < view.size(); i++) {
11626
0
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11627
0
          view[i] == '[') {
11628
0
        return i;
11629
0
      }
11630
0
    }
11631
0
    return size_t(view.size());
11632
0
  }
11633
  // fast path for long strings (expected to be common)
11634
0
  size_t i = location;
11635
0
  const __m128i mask1 = _mm_set1_epi8(':');
11636
0
  const __m128i mask2 = _mm_set1_epi8('/');
11637
0
  const __m128i mask4 = _mm_set1_epi8('?');
11638
0
  const __m128i mask5 = _mm_set1_epi8('[');
11639
11640
0
  for (; i + 15 < view.size(); i += 16) {
11641
0
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11642
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11643
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11644
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11645
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11646
0
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11647
0
    int mask = _mm_movemask_epi8(m);
11648
0
    if (mask != 0) {
11649
0
      return i + trailing_zeroes(mask);
11650
0
    }
11651
0
  }
11652
0
  if (i < view.size()) {
11653
0
    __m128i word =
11654
0
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11655
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11656
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11657
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11658
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11659
0
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11660
0
    int mask = _mm_movemask_epi8(m);
11661
0
    if (mask != 0) {
11662
0
      return view.length() - 16 + trailing_zeroes(mask);
11663
0
    }
11664
0
  }
11665
0
  return size_t(view.length());
11666
0
}
11667
#elif ADA_LSX
11668
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11669
                                                  size_t location) noexcept {
11670
  // first check for short strings in which case we do it naively.
11671
  if (view.size() - location < 16) {  // slow path
11672
    for (size_t i = location; i < view.size(); i++) {
11673
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11674
          view[i] == '[') {
11675
        return i;
11676
      }
11677
    }
11678
    return size_t(view.size());
11679
  }
11680
  // fast path for long strings (expected to be common)
11681
  size_t i = location;
11682
  const __m128i mask1 = __lsx_vrepli_b(':');
11683
  const __m128i mask2 = __lsx_vrepli_b('/');
11684
  const __m128i mask4 = __lsx_vrepli_b('?');
11685
  const __m128i mask5 = __lsx_vrepli_b('[');
11686
11687
  for (; i + 15 < view.size(); i += 16) {
11688
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11689
    __m128i m1 = __lsx_vseq_b(word, mask1);
11690
    __m128i m2 = __lsx_vseq_b(word, mask2);
11691
    __m128i m4 = __lsx_vseq_b(word, mask4);
11692
    __m128i m5 = __lsx_vseq_b(word, mask5);
11693
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11694
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11695
    if (mask != 0) {
11696
      return i + trailing_zeroes(mask);
11697
    }
11698
  }
11699
  if (i < view.size()) {
11700
    __m128i word =
11701
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11702
    __m128i m1 = __lsx_vseq_b(word, mask1);
11703
    __m128i m2 = __lsx_vseq_b(word, mask2);
11704
    __m128i m4 = __lsx_vseq_b(word, mask4);
11705
    __m128i m5 = __lsx_vseq_b(word, mask5);
11706
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11707
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11708
    if (mask != 0) {
11709
      return view.length() - 16 + trailing_zeroes(mask);
11710
    }
11711
  }
11712
  return size_t(view.length());
11713
}
11714
#elif ADA_RVV
11715
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11716
                                                  size_t location) noexcept {
11717
  uint8_t* src = (uint8_t*)view.data() + location;
11718
  for (size_t vl, n = view.size() - location; n > 0;
11719
       n -= vl, src += vl, location += vl) {
11720
    vl = __riscv_vsetvl_e8m1(n);
11721
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
11722
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
11723
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
11724
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
11725
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
11726
    vbool8_t m =
11727
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
11728
    long idx = __riscv_vfirst(m, vl);
11729
    if (idx >= 0) return location + idx;
11730
  }
11731
  return size_t(view.size());
11732
}
11733
#else
11734
// : / [ ?
11735
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11736
  std::array<uint8_t, 256> result{};
11737
  for (int i : {':', '/', '?', '['}) {
11738
    result[i] = 1;
11739
  }
11740
  return result;
11741
}();
11742
// credit: @the-moisrex recommended a table-based approach
11743
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11744
                                                  size_t location) noexcept {
11745
  auto const str = view.substr(location);
11746
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11747
    if (host_delimiters[(uint8_t)*pos]) {
11748
      return pos - str.begin() + location;
11749
    }
11750
  }
11751
  return size_t(view.size());
11752
}
11753
#endif
11754
11755
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11756
0
    const bool is_special, std::string_view& view) noexcept {
11757
  /**
11758
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11759
   * compute a variable called insideBrackets but this variable is only used
11760
   * once, to check whether a ':' character was found outside brackets. Exact
11761
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11762
   * It is conceptually simpler and arguably more efficient to just return a
11763
   * Boolean indicating whether ':' was found outside brackets.
11764
   */
11765
0
  const size_t view_size = view.size();
11766
0
  size_t location = 0;
11767
0
  bool found_colon = false;
11768
  /**
11769
   * Performance analysis:
11770
   *
11771
   * We are basically seeking the end of the hostname which can be indicated
11772
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11773
   * (where '\\' is only applicable for special URLs). However, these must
11774
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11775
   * '?' does not count.
11776
   *
11777
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11778
   * the set of delimiters, and that we handle it first.
11779
   *
11780
   * So the trick is to have a fast function that locates the next delimiter.
11781
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11782
   * function would be provided by the C++ standard library, but it seems that
11783
   * find_first_of is not very fast, so we are forced to roll our own.
11784
   *
11785
   * We do not break into two loops for speed, but for clarity.
11786
   */
11787
0
  if (is_special) {
11788
    // We move to the next delimiter.
11789
0
    location = find_next_host_delimiter_special(view, location);
11790
    // Unless we find '[' then we are going only going to have to call
11791
    // find_next_host_delimiter_special once.
11792
0
    for (; location < view_size;
11793
0
         location = find_next_host_delimiter_special(view, location)) {
11794
0
      if (view[location] == '[') {
11795
0
        location = view.find(']', location);
11796
0
        if (location == std::string_view::npos) {
11797
          // performance: view.find might get translated to a memchr, which
11798
          // has no notion of std::string_view::npos, so the code does not
11799
          // reflect the assembly.
11800
0
          location = view_size;
11801
0
          break;
11802
0
        }
11803
0
      } else {
11804
0
        found_colon = view[location] == ':';
11805
0
        break;
11806
0
      }
11807
0
    }
11808
0
  } else {
11809
    // We move to the next delimiter.
11810
0
    location = find_next_host_delimiter(view, location);
11811
    // Unless we find '[' then we are going only going to have to call
11812
    // find_next_host_delimiter_special once.
11813
0
    for (; location < view_size;
11814
0
         location = find_next_host_delimiter(view, location)) {
11815
0
      if (view[location] == '[') {
11816
0
        location = view.find(']', location);
11817
0
        if (location == std::string_view::npos) {
11818
          // performance: view.find might get translated to a memchr, which
11819
          // has no notion of std::string_view::npos, so the code does not
11820
          // reflect the assembly.
11821
0
          location = view_size;
11822
0
          break;
11823
0
        }
11824
0
      } else {
11825
0
        found_colon = view[location] == ':';
11826
0
        break;
11827
0
      }
11828
0
    }
11829
0
  }
11830
  // performance: remove_suffix may translate into a single instruction.
11831
0
  view.remove_suffix(view_size - location);
11832
0
  return {location, found_colon};
11833
0
}
11834
11835
0
void trim_c0_whitespace(std::string_view& input) noexcept {
11836
0
  while (!input.empty() &&
11837
0
         ada::unicode::is_c0_control_or_space(input.front())) {
11838
0
    input.remove_prefix(1);
11839
0
  }
11840
0
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
11841
0
    input.remove_suffix(1);
11842
0
  }
11843
0
}
11844
11845
ada_really_inline void parse_prepared_path(std::string_view input,
11846
                                           ada::scheme::type type,
11847
0
                                           std::string& path) {
11848
0
  ada_log("parse_prepared_path ", input);
11849
0
  uint8_t accumulator = checkers::path_signature(input);
11850
  // Let us first detect a trivial case.
11851
  // If it is special, we check that we have no dot, no %,  no \ and no
11852
  // character needing percent encoding. Otherwise, we check that we have no %,
11853
  // no dot, and no character needing percent encoding.
11854
0
  constexpr uint8_t need_encoding = 1;
11855
0
  constexpr uint8_t backslash_char = 2;
11856
0
  constexpr uint8_t dot_char = 4;
11857
0
  constexpr uint8_t percent_char = 8;
11858
0
  bool special = type != ada::scheme::NOT_SPECIAL;
11859
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
11860
0
                                      checkers::is_windows_drive_letter(input));
11861
0
  bool trivial_path =
11862
0
      (special ? (accumulator == 0)
11863
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
11864
0
                  0)) &&
11865
0
      (!may_need_slow_file_handling);
11866
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
11867
    // '4' means that we have at least one dot, but nothing that requires
11868
    // percent encoding or decoding. The only part that is not trivial is
11869
    // that we may have single dots and double dots path segments.
11870
    // If we have such segments, then we either have a path that begins
11871
    // with '.' (easy to check), or we have the sequence './'.
11872
    // Note: input cannot be empty, it must at least contain one character ('.')
11873
    // Note: we know that '\' is not present.
11874
0
    if (input[0] != '.') {
11875
0
      size_t slashdot = 0;
11876
0
      bool dot_is_file = true;
11877
0
      for (;;) {
11878
0
        slashdot = input.find("/.", slashdot);
11879
0
        if (slashdot == std::string_view::npos) {  // common case
11880
0
          break;
11881
0
        } else {  // uncommon
11882
          // only three cases matter: /./, /.. or a final /
11883
0
          slashdot += 2;
11884
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
11885
0
                           input[slashdot] == '/');
11886
0
        }
11887
0
      }
11888
0
      trivial_path = dot_is_file;
11889
0
    }
11890
0
  }
11891
0
  if (trivial_path) {
11892
0
    ada_log("parse_path trivial");
11893
0
    path += '/';
11894
0
    path += input;
11895
0
    return;
11896
0
  }
11897
  // We are going to need to look a bit at the path, but let us see if we can
11898
  // ignore percent encoding *and* backslashes *and* percent characters.
11899
  // Except for the trivial case, this is likely to capture 99% of paths out
11900
  // there.
11901
0
  bool fast_path =
11902
0
      (special &&
11903
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
11904
0
      (type != ada::scheme::type::FILE);
11905
0
  if (fast_path) {
11906
0
    ada_log("parse_prepared_path fast");
11907
    // Here we don't need to worry about \ or percent encoding.
11908
    // We also do not have a file protocol. We might have dots, however,
11909
    // but dots must as appear as '.', and they cannot be encoded because
11910
    // the symbol '%' is not present.
11911
0
    size_t previous_location = 0;  // We start at 0.
11912
0
    do {
11913
0
      size_t new_location = input.find('/', previous_location);
11914
      // std::string_view path_view = input;
11915
      //  We process the last segment separately:
11916
0
      if (new_location == std::string_view::npos) {
11917
0
        std::string_view path_view = input.substr(previous_location);
11918
0
        if (path_view == "..") {  // The path ends with ..
11919
          // e.g., if you receive ".." with an empty path, you go to "/".
11920
0
          if (path.empty()) {
11921
0
            path = '/';
11922
0
            return;
11923
0
          }
11924
          // Fast case where we have nothing to do:
11925
0
          if (path.back() == '/') {
11926
0
            return;
11927
0
          }
11928
          // If you have the path "/joe/myfriend",
11929
          // then you delete 'myfriend'.
11930
0
          path.resize(path.rfind('/') + 1);
11931
0
          return;
11932
0
        }
11933
0
        path += '/';
11934
0
        if (path_view != ".") {
11935
0
          path.append(path_view);
11936
0
        }
11937
0
        return;
11938
0
      } else {
11939
        // This is a non-final segment.
11940
0
        std::string_view path_view =
11941
0
            input.substr(previous_location, new_location - previous_location);
11942
0
        previous_location = new_location + 1;
11943
0
        if (path_view == "..") {
11944
0
          size_t last_delimiter = path.rfind('/');
11945
0
          if (last_delimiter != std::string::npos) {
11946
0
            path.erase(last_delimiter);
11947
0
          }
11948
0
        } else if (path_view != ".") {
11949
0
          path += '/';
11950
0
          path.append(path_view);
11951
0
        }
11952
0
      }
11953
0
    } while (true);
11954
0
  } else {
11955
0
    ada_log("parse_path slow");
11956
    // we have reached the general case
11957
0
    bool needs_percent_encoding = (accumulator & 1);
11958
0
    std::string path_buffer_tmp;
11959
0
    do {
11960
0
      size_t location = (special && (accumulator & 2))
11961
0
                            ? input.find_first_of("/\\")
11962
0
                            : input.find('/');
11963
0
      std::string_view path_view = input;
11964
0
      if (location != std::string_view::npos) {
11965
0
        path_view.remove_suffix(path_view.size() - location);
11966
0
        input.remove_prefix(location + 1);
11967
0
      }
11968
      // path_buffer is either path_view or it might point at a percent encoded
11969
      // temporary file.
11970
0
      std::string_view path_buffer =
11971
0
          (needs_percent_encoding &&
11972
0
           ada::unicode::percent_encode<false>(
11973
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
11974
0
              ? path_buffer_tmp
11975
0
              : path_view;
11976
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
11977
0
        helpers::shorten_path(path, type);
11978
0
        if (location == std::string_view::npos) {
11979
0
          path += '/';
11980
0
        }
11981
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
11982
0
                 (location == std::string_view::npos)) {
11983
0
        path += '/';
11984
0
      }
11985
      // Otherwise, if path_buffer is not a single-dot path segment, then:
11986
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
11987
        // If url's scheme is "file", url's path is empty, and path_buffer is a
11988
        // Windows drive letter, then replace the second code point in
11989
        // path_buffer with U+003A (:).
11990
0
        if (type == ada::scheme::type::FILE && path.empty() &&
11991
0
            checkers::is_windows_drive_letter(path_buffer)) {
11992
0
          path += '/';
11993
0
          path += path_buffer[0];
11994
0
          path += ':';
11995
0
          path_buffer.remove_prefix(2);
11996
0
          path.append(path_buffer);
11997
0
        } else {
11998
          // Append path_buffer to url's path.
11999
0
          path += '/';
12000
0
          path.append(path_buffer);
12001
0
        }
12002
0
      }
12003
0
      if (location == std::string_view::npos) {
12004
0
        return;
12005
0
      }
12006
0
    } while (true);
12007
0
  }
12008
0
}
12009
12010
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12011
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12012
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12013
0
          input2.size(), " bytes]");
12014
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12015
0
         input1.data() < input2.data() + input2.size();
12016
0
}
12017
12018
template <class url_type>
12019
ada_really_inline void strip_trailing_spaces_from_opaque_path(
12020
0
    url_type& url) noexcept {
12021
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12022
0
  if (!url.has_opaque_path) return;
12023
0
  if (url.has_hash()) return;
12024
0
  if (url.has_search()) return;
12025
12026
0
  auto path = std::string(url.get_pathname());
12027
0
  while (!path.empty() && path.back() == ' ') {
12028
0
    path.resize(path.size() - 1);
12029
0
  }
12030
0
  url.update_base_pathname(path);
12031
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&)
12032
12033
// @ / \\ ?
12034
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12035
    []() consteval {
12036
      std::array<uint8_t, 256> result{};
12037
      for (uint8_t i : {'@', '/', '\\', '?'}) {
12038
        result[i] = 1;
12039
      }
12040
      return result;
12041
    }();
12042
// credit: @the-moisrex recommended a table-based approach
12043
ada_really_inline size_t
12044
0
find_authority_delimiter_special(std::string_view view) noexcept {
12045
  // performance note: we might be able to gain further performance
12046
  // with SIMD instrinsics.
12047
0
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12048
0
    if (authority_delimiter_special[(uint8_t)*pos]) {
12049
0
      return pos - view.begin();
12050
0
    }
12051
0
  }
12052
0
  return size_t(view.size());
12053
0
}
12054
12055
// @ / ?
12056
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12057
  std::array<uint8_t, 256> result{};
12058
  for (uint8_t i : {'@', '/', '?'}) {
12059
    result[i] = 1;
12060
  }
12061
  return result;
12062
}();
12063
// credit: @the-moisrex recommended a table-based approach
12064
ada_really_inline size_t
12065
0
find_authority_delimiter(std::string_view view) noexcept {
12066
  // performance note: we might be able to gain further performance
12067
  // with SIMD instrinsics.
12068
0
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12069
0
    if (authority_delimiter[(uint8_t)*pos]) {
12070
0
      return pos - view.begin();
12071
0
    }
12072
0
  }
12073
0
  return size_t(view.size());
12074
0
}
12075
12076
}  // namespace ada::helpers
12077
12078
namespace ada {
12079
0
ada_warn_unused std::string to_string(ada::state state) {
12080
0
  return ada::helpers::get_state(state);
12081
0
}
12082
#undef ada_make_uint8x16_t
12083
}  // namespace ada
12084
/* end file src/helpers.cpp */
12085
/* begin file src/url.cpp */
12086
12087
#include <numeric>
12088
#include <algorithm>
12089
#include <iterator>
12090
#include <ranges>
12091
#include <string>
12092
#include <string_view>
12093
12094
namespace ada {
12095
12096
0
bool url::parse_opaque_host(std::string_view input) {
12097
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12098
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12099
0
    return is_valid = false;
12100
0
  }
12101
12102
  // Return the result of running UTF-8 percent-encode on input using the C0
12103
  // control percent-encode set.
12104
0
  host = ada::unicode::percent_encode(
12105
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12106
0
  return true;
12107
0
}
12108
12109
0
bool url::parse_ipv4(std::string_view input) {
12110
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12111
0
  if (input.back() == '.') {
12112
0
    input.remove_suffix(1);
12113
0
  }
12114
0
  size_t digit_count{0};
12115
0
  int pure_decimal_count = 0;  // entries that are decimal
12116
0
  std::string_view original_input =
12117
0
      input;  // we might use this if pure_decimal_count == 4.
12118
0
  uint64_t ipv4{0};
12119
  // we could unroll for better performance?
12120
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12121
0
    uint32_t
12122
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12123
0
    bool is_hex = checkers::has_hex_prefix(input);
12124
0
    if (is_hex && ((input.length() == 2) ||
12125
0
                   ((input.length() > 2) && (input[2] == '.')))) {
12126
      // special case
12127
0
      segment_result = 0;
12128
0
      input.remove_prefix(2);
12129
0
    } else {
12130
0
      std::from_chars_result r{};
12131
0
      if (is_hex) {
12132
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12133
0
                            segment_result, 16);
12134
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
12135
0
                 checkers::is_digit(input[1])) {
12136
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12137
0
                            segment_result, 8);
12138
0
      } else {
12139
0
        pure_decimal_count++;
12140
0
        r = std::from_chars(input.data(), input.data() + input.size(),
12141
0
                            segment_result, 10);
12142
0
      }
12143
0
      if (r.ec != std::errc()) {
12144
0
        return is_valid = false;
12145
0
      }
12146
0
      input.remove_prefix(r.ptr - input.data());
12147
0
    }
12148
0
    if (input.empty()) {
12149
      // We have the last value.
12150
      // At this stage, ipv4 contains digit_count*8 bits.
12151
      // So we have 32-digit_count*8 bits left.
12152
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12153
0
        return is_valid = false;
12154
0
      }
12155
0
      ipv4 <<= (32 - digit_count * 8);
12156
0
      ipv4 |= segment_result;
12157
0
      goto final;
12158
0
    } else {
12159
      // There is more, so that the value must no be larger than 255
12160
      // and we must have a '.'.
12161
0
      if ((segment_result > 255) || (input[0] != '.')) {
12162
0
        return is_valid = false;
12163
0
      }
12164
0
      ipv4 <<= 8;
12165
0
      ipv4 |= segment_result;
12166
0
      input.remove_prefix(1);  // remove '.'
12167
0
    }
12168
0
  }
12169
0
  if ((digit_count != 4) || (!input.empty())) {
12170
0
    return is_valid = false;
12171
0
  }
12172
0
final:
12173
  // We could also check r.ptr to see where the parsing ended.
12174
0
  if (pure_decimal_count == 4) {
12175
0
    host = original_input;  // The original input was already all decimal and we
12176
                            // validated it.
12177
0
  } else {
12178
0
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12179
0
  }
12180
0
  host_type = IPV4;
12181
0
  return true;
12182
0
}
12183
12184
0
bool url::parse_ipv6(std::string_view input) {
12185
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12186
12187
0
  if (input.empty()) {
12188
0
    return is_valid = false;
12189
0
  }
12190
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12191
0
  std::array<uint16_t, 8> address{};
12192
12193
  // Let pieceIndex be 0.
12194
0
  int piece_index = 0;
12195
12196
  // Let compress be null.
12197
0
  std::optional<int> compress{};
12198
12199
  // Let pointer be a pointer for input.
12200
0
  std::string_view::iterator pointer = input.begin();
12201
12202
  // If c is U+003A (:), then:
12203
0
  if (input[0] == ':') {
12204
    // If remaining does not start with U+003A (:), validation error, return
12205
    // failure.
12206
0
    if (input.size() == 1 || input[1] != ':') {
12207
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12208
0
      return is_valid = false;
12209
0
    }
12210
12211
    // Increase pointer by 2.
12212
0
    pointer += 2;
12213
12214
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12215
0
    compress = ++piece_index;
12216
0
  }
12217
12218
  // While c is not the EOF code point:
12219
0
  while (pointer != input.end()) {
12220
    // If pieceIndex is 8, validation error, return failure.
12221
0
    if (piece_index == 8) {
12222
0
      ada_log("parse_ipv6 piece_index == 8");
12223
0
      return is_valid = false;
12224
0
    }
12225
12226
    // If c is U+003A (:), then:
12227
0
    if (*pointer == ':') {
12228
      // If compress is non-null, validation error, return failure.
12229
0
      if (compress.has_value()) {
12230
0
        ada_log("parse_ipv6 compress is non-null");
12231
0
        return is_valid = false;
12232
0
      }
12233
12234
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12235
      // then continue.
12236
0
      pointer++;
12237
0
      compress = ++piece_index;
12238
0
      continue;
12239
0
    }
12240
12241
    // Let value and length be 0.
12242
0
    uint16_t value = 0, length = 0;
12243
12244
    // While length is less than 4 and c is an ASCII hex digit,
12245
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12246
    // increase pointer and length by 1.
12247
0
    while (length < 4 && pointer != input.end() &&
12248
0
           unicode::is_ascii_hex_digit(*pointer)) {
12249
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12250
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12251
0
      pointer++;
12252
0
      length++;
12253
0
    }
12254
12255
    // If c is U+002E (.), then:
12256
0
    if (pointer != input.end() && *pointer == '.') {
12257
      // If length is 0, validation error, return failure.
12258
0
      if (length == 0) {
12259
0
        ada_log("parse_ipv6 length is 0");
12260
0
        return is_valid = false;
12261
0
      }
12262
12263
      // Decrease pointer by length.
12264
0
      pointer -= length;
12265
12266
      // If pieceIndex is greater than 6, validation error, return failure.
12267
0
      if (piece_index > 6) {
12268
0
        ada_log("parse_ipv6 piece_index > 6");
12269
0
        return is_valid = false;
12270
0
      }
12271
12272
      // Let numbersSeen be 0.
12273
0
      int numbers_seen = 0;
12274
12275
      // While c is not the EOF code point:
12276
0
      while (pointer != input.end()) {
12277
        // Let ipv4Piece be null.
12278
0
        std::optional<uint16_t> ipv4_piece{};
12279
12280
        // If numbersSeen is greater than 0, then:
12281
0
        if (numbers_seen > 0) {
12282
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12283
          // pointer by 1.
12284
0
          if (*pointer == '.' && numbers_seen < 4) {
12285
0
            pointer++;
12286
0
          }
12287
          // Otherwise, validation error, return failure.
12288
0
          else {
12289
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12290
0
            return is_valid = false;
12291
0
          }
12292
0
        }
12293
12294
        // If c is not an ASCII digit, validation error, return failure.
12295
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12296
0
          ada_log(
12297
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12298
0
              "failure");
12299
0
          return is_valid = false;
12300
0
        }
12301
12302
        // While c is an ASCII digit:
12303
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12304
          // Let number be c interpreted as decimal number.
12305
0
          int number = *pointer - '0';
12306
12307
          // If ipv4Piece is null, then set ipv4Piece to number.
12308
0
          if (!ipv4_piece.has_value()) {
12309
0
            ipv4_piece = number;
12310
0
          }
12311
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12312
0
          else if (ipv4_piece == 0) {
12313
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12314
0
            return is_valid = false;
12315
0
          }
12316
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12317
0
          else {
12318
0
            ipv4_piece = *ipv4_piece * 10 + number;
12319
0
          }
12320
12321
          // If ipv4Piece is greater than 255, validation error, return failure.
12322
0
          if (ipv4_piece > 255) {
12323
0
            ada_log("parse_ipv6 ipv4_piece > 255");
12324
0
            return is_valid = false;
12325
0
          }
12326
12327
          // Increase pointer by 1.
12328
0
          pointer++;
12329
0
        }
12330
12331
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12332
        // ipv4Piece.
12333
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12334
0
        address[piece_index] =
12335
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12336
12337
        // Increase numbersSeen by 1.
12338
0
        numbers_seen++;
12339
12340
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12341
0
        if (numbers_seen == 2 || numbers_seen == 4) {
12342
0
          piece_index++;
12343
0
        }
12344
0
      }
12345
12346
      // If numbersSeen is not 4, validation error, return failure.
12347
0
      if (numbers_seen != 4) {
12348
0
        return is_valid = false;
12349
0
      }
12350
12351
      // Break.
12352
0
      break;
12353
0
    }
12354
    // Otherwise, if c is U+003A (:):
12355
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
12356
      // Increase pointer by 1.
12357
0
      pointer++;
12358
12359
      // If c is the EOF code point, validation error, return failure.
12360
0
      if (pointer == input.end()) {
12361
0
        ada_log(
12362
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
12363
0
            "failure");
12364
0
        return is_valid = false;
12365
0
      }
12366
0
    }
12367
    // Otherwise, if c is not the EOF code point, validation error, return
12368
    // failure.
12369
0
    else if (pointer != input.end()) {
12370
0
      ada_log(
12371
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12372
0
          "error, return failure");
12373
0
      return is_valid = false;
12374
0
    }
12375
12376
    // Set address[pieceIndex] to value.
12377
0
    address[piece_index] = value;
12378
12379
    // Increase pieceIndex by 1.
12380
0
    piece_index++;
12381
0
  }
12382
12383
  // If compress is non-null, then:
12384
0
  if (compress.has_value()) {
12385
    // Let swaps be pieceIndex - compress.
12386
0
    int swaps = piece_index - *compress;
12387
12388
    // Set pieceIndex to 7.
12389
0
    piece_index = 7;
12390
12391
    // While pieceIndex is not 0 and swaps is greater than 0,
12392
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12393
    // decrease both pieceIndex and swaps by 1.
12394
0
    while (piece_index != 0 && swaps > 0) {
12395
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12396
0
      piece_index--;
12397
0
      swaps--;
12398
0
    }
12399
0
  }
12400
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12401
  // return failure.
12402
0
  else if (piece_index != 8) {
12403
0
    ada_log(
12404
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12405
0
        "error, return failure");
12406
0
    return is_valid = false;
12407
0
  }
12408
0
  host = ada::serializers::ipv6(address);
12409
0
  ada_log("parse_ipv6 ", *host);
12410
0
  host_type = IPV6;
12411
0
  return true;
12412
0
}
12413
12414
template <bool has_state_override>
12415
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12416
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
12417
0
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12418
  /**
12419
   * In the common case, we will immediately recognize a special scheme (e.g.,
12420
   *http, https), in which case, we can go really fast.
12421
   **/
12422
0
  if (is_input_special) {  // fast path!!!
12423
0
    if constexpr (has_state_override) {
12424
      // If url's scheme is not a special scheme and buffer is a special scheme,
12425
      // then return.
12426
0
      if (is_special() != is_input_special) {
12427
0
        return false;
12428
0
      }
12429
12430
      // If url includes credentials or has a non-null port, and buffer is
12431
      // "file", then return.
12432
0
      if ((has_credentials() || port.has_value()) &&
12433
0
          parsed_type == ada::scheme::type::FILE) {
12434
0
        return false;
12435
0
      }
12436
12437
      // If url's scheme is "file" and its host is an empty host, then return.
12438
      // An empty host is the empty string.
12439
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12440
0
          host.value().empty()) {
12441
0
        return false;
12442
0
      }
12443
0
    }
12444
12445
0
    type = parsed_type;
12446
12447
0
    if constexpr (has_state_override) {
12448
      // This is uncommon.
12449
0
      uint16_t urls_scheme_port = get_special_port();
12450
12451
0
      if (urls_scheme_port) {
12452
        // If url's port is url's scheme's default port, then set url's port to
12453
        // null.
12454
0
        if (port.has_value() && *port == urls_scheme_port) {
12455
0
          port = std::nullopt;
12456
0
        }
12457
0
      }
12458
0
    }
12459
0
  } else {  // slow path
12460
0
    std::string _buffer(input);
12461
    // Next function is only valid if the input is ASCII and returns false
12462
    // otherwise, but it seems that we always have ascii content so we do not
12463
    // need to check the return value.
12464
    // bool is_ascii =
12465
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12466
12467
0
    if constexpr (has_state_override) {
12468
      // If url's scheme is a special scheme and buffer is not a special scheme,
12469
      // then return. If url's scheme is not a special scheme and buffer is a
12470
      // special scheme, then return.
12471
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
12472
0
        return true;
12473
0
      }
12474
12475
      // If url includes credentials or has a non-null port, and buffer is
12476
      // "file", then return.
12477
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12478
0
        return true;
12479
0
      }
12480
12481
      // If url's scheme is "file" and its host is an empty host, then return.
12482
      // An empty host is the empty string.
12483
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12484
0
          host.value().empty()) {
12485
0
        return true;
12486
0
      }
12487
0
    }
12488
12489
0
    set_scheme(std::move(_buffer));
12490
12491
0
    if constexpr (has_state_override) {
12492
      // This is uncommon.
12493
0
      uint16_t urls_scheme_port = get_special_port();
12494
12495
0
      if (urls_scheme_port) {
12496
        // If url's port is url's scheme's default port, then set url's port to
12497
        // null.
12498
0
        if (port.has_value() && *port == urls_scheme_port) {
12499
0
          port = std::nullopt;
12500
0
        }
12501
0
      }
12502
0
    }
12503
0
  }
12504
12505
0
  return true;
12506
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> >)
12507
12508
0
ada_really_inline bool url::parse_host(std::string_view input) {
12509
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12510
0
  if (input.empty()) {
12511
0
    return is_valid = false;
12512
0
  }  // technically unnecessary.
12513
  // If input starts with U+005B ([), then:
12514
0
  if (input[0] == '[') {
12515
    // If input does not end with U+005D (]), validation error, return failure.
12516
0
    if (input.back() != ']') {
12517
0
      return is_valid = false;
12518
0
    }
12519
0
    ada_log("parse_host ipv6");
12520
12521
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12522
    // trailing U+005D (]) removed.
12523
0
    input.remove_prefix(1);
12524
0
    input.remove_suffix(1);
12525
0
    return parse_ipv6(input);
12526
0
  }
12527
12528
  // If isNotSpecial is true, then return the result of opaque-host parsing
12529
  // input.
12530
0
  if (!is_special()) {
12531
0
    return parse_opaque_host(input);
12532
0
  }
12533
  // Let domain be the result of running UTF-8 decode without BOM on the
12534
  // percent-decoding of input. Let asciiDomain be the result of running domain
12535
  // to ASCII with domain and false. The most common case is an ASCII input, in
12536
  // which case we do not need to call the expensive 'to_ascii' if a few
12537
  // conditions are met: no '%' and no 'xn-' subsequence.
12538
0
  std::string buffer = std::string(input);
12539
  // This next function checks that the result is ascii, but we are going to
12540
  // to check anyhow with is_forbidden.
12541
  // bool is_ascii =
12542
0
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12543
0
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12544
0
      buffer.data(), buffer.size());
12545
0
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12546
    // fast path
12547
0
    host = std::move(buffer);
12548
0
    if (checkers::is_ipv4(host.value())) {
12549
0
      ada_log("parse_host fast path ipv4");
12550
0
      return parse_ipv4(host.value());
12551
0
    }
12552
0
    ada_log("parse_host fast path ", *host);
12553
0
    return true;
12554
0
  }
12555
0
  ada_log("parse_host calling to_ascii");
12556
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12557
0
  if (!is_valid) {
12558
0
    ada_log("parse_host to_ascii returns false");
12559
0
    return is_valid = false;
12560
0
  }
12561
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12562
0
          " bytes]");
12563
12564
0
  if (std::any_of(host.value().begin(), host.value().end(),
12565
0
                  ada::unicode::is_forbidden_domain_code_point)) {
12566
0
    host = std::nullopt;
12567
0
    return is_valid = false;
12568
0
  }
12569
12570
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12571
  // asciiDomain.
12572
0
  if (checkers::is_ipv4(host.value())) {
12573
0
    ada_log("parse_host got ipv4 ", *host);
12574
0
    return parse_ipv4(host.value());
12575
0
  }
12576
12577
0
  return true;
12578
0
}
12579
12580
0
ada_really_inline void url::parse_path(std::string_view input) {
12581
0
  ada_log("parse_path ", input);
12582
0
  std::string tmp_buffer;
12583
0
  std::string_view internal_input;
12584
0
  if (unicode::has_tabs_or_newline(input)) {
12585
0
    tmp_buffer = input;
12586
    // Optimization opportunity: Instead of copying and then pruning, we could
12587
    // just directly build the string from user_input.
12588
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12589
0
    internal_input = tmp_buffer;
12590
0
  } else {
12591
0
    internal_input = input;
12592
0
  }
12593
12594
  // If url is special, then:
12595
0
  if (is_special()) {
12596
0
    if (internal_input.empty()) {
12597
0
      path = "/";
12598
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12599
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12600
0
    } else {
12601
0
      helpers::parse_prepared_path(internal_input, type, path);
12602
0
    }
12603
0
  } else if (!internal_input.empty()) {
12604
0
    if (internal_input[0] == '/') {
12605
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12606
0
    } else {
12607
0
      helpers::parse_prepared_path(internal_input, type, path);
12608
0
    }
12609
0
  } else {
12610
0
    if (!host.has_value()) {
12611
0
      path = "/";
12612
0
    }
12613
0
  }
12614
0
}
12615
12616
0
[[nodiscard]] std::string url::to_string() const {
12617
0
  if (!is_valid) {
12618
0
    return "null";
12619
0
  }
12620
0
  std::string answer;
12621
0
  auto back = std::back_insert_iterator(answer);
12622
0
  answer.append("{\n");
12623
0
  answer.append("\t\"protocol\":\"");
12624
0
  helpers::encode_json(get_protocol(), back);
12625
0
  answer.append("\",\n");
12626
0
  if (has_credentials()) {
12627
0
    answer.append("\t\"username\":\"");
12628
0
    helpers::encode_json(username, back);
12629
0
    answer.append("\",\n");
12630
0
    answer.append("\t\"password\":\"");
12631
0
    helpers::encode_json(password, back);
12632
0
    answer.append("\",\n");
12633
0
  }
12634
0
  if (host.has_value()) {
12635
0
    answer.append("\t\"host\":\"");
12636
0
    helpers::encode_json(host.value(), back);
12637
0
    answer.append("\",\n");
12638
0
  }
12639
0
  if (port.has_value()) {
12640
0
    answer.append("\t\"port\":\"");
12641
0
    answer.append(std::to_string(port.value()));
12642
0
    answer.append("\",\n");
12643
0
  }
12644
0
  answer.append("\t\"path\":\"");
12645
0
  helpers::encode_json(path, back);
12646
0
  answer.append("\",\n");
12647
0
  answer.append("\t\"opaque path\":");
12648
0
  answer.append((has_opaque_path ? "true" : "false"));
12649
0
  if (has_search()) {
12650
0
    answer.append(",\n");
12651
0
    answer.append("\t\"query\":\"");
12652
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12653
0
    helpers::encode_json(query.value(), back);
12654
0
    answer.append("\"");
12655
0
  }
12656
0
  if (hash.has_value()) {
12657
0
    answer.append(",\n");
12658
0
    answer.append("\t\"hash\":\"");
12659
0
    helpers::encode_json(hash.value(), back);
12660
0
    answer.append("\"");
12661
0
  }
12662
0
  answer.append("\n}");
12663
0
  return answer;
12664
0
}
12665
12666
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12667
0
  if (!host.has_value()) {
12668
0
    return false;
12669
0
  }
12670
0
  return checkers::verify_dns_length(host.value());
12671
0
}
12672
12673
0
[[nodiscard]] std::string url::get_origin() const noexcept {
12674
0
  if (is_special()) {
12675
    // Return a new opaque origin.
12676
0
    if (type == scheme::FILE) {
12677
0
      return "null";
12678
0
    }
12679
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
12680
0
  }
12681
12682
0
  if (non_special_scheme == "blob") {
12683
0
    if (!path.empty()) {
12684
0
      auto result = ada::parse<ada::url>(path);
12685
0
      if (result &&
12686
0
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12687
        // If pathURL's scheme is not "http" and not "https", then return a
12688
        // new opaque origin.
12689
0
        return ada::helpers::concat(result->get_protocol(), "//",
12690
0
                                    result->get_host());
12691
0
      }
12692
0
    }
12693
0
  }
12694
12695
  // Return a new opaque origin.
12696
0
  return "null";
12697
0
}
12698
12699
0
[[nodiscard]] std::string url::get_protocol() const noexcept {
12700
0
  if (is_special()) {
12701
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12702
0
  }
12703
  // We only move the 'scheme' if it is non-special.
12704
0
  return helpers::concat(non_special_scheme, ":");
12705
0
}
12706
12707
0
[[nodiscard]] std::string url::get_host() const noexcept {
12708
  // If url's host is null, then return the empty string.
12709
  // If url's port is null, return url's host, serialized.
12710
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12711
  // serialized.
12712
0
  if (!host.has_value()) {
12713
0
    return "";
12714
0
  }
12715
0
  if (port.has_value()) {
12716
0
    return host.value() + ":" + get_port();
12717
0
  }
12718
0
  return host.value();
12719
0
}
12720
12721
0
[[nodiscard]] std::string url::get_hostname() const noexcept {
12722
0
  return host.value_or("");
12723
0
}
12724
12725
0
[[nodiscard]] std::string url::get_search() const noexcept {
12726
  // If this's URL's query is either null or the empty string, then return the
12727
  // empty string. Return U+003F (?), followed by this's URL's query.
12728
0
  return (!query.has_value() || (query.value().empty())) ? ""
12729
0
                                                         : "?" + query.value();
12730
0
}
12731
12732
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
12733
0
  return username;
12734
0
}
12735
12736
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
12737
0
  return password;
12738
0
}
12739
12740
0
[[nodiscard]] std::string url::get_port() const noexcept {
12741
0
  return port.has_value() ? std::to_string(port.value()) : "";
12742
0
}
12743
12744
0
[[nodiscard]] std::string url::get_hash() const noexcept {
12745
  // If this's URL's fragment is either null or the empty string, then return
12746
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12747
0
  return (!hash.has_value() || (hash.value().empty())) ? ""
12748
0
                                                       : "#" + hash.value();
12749
0
}
12750
12751
template <bool override_hostname>
12752
0
bool url::set_host_or_hostname(const std::string_view input) {
12753
0
  if (has_opaque_path) {
12754
0
    return false;
12755
0
  }
12756
12757
0
  std::optional<std::string> previous_host = host;
12758
0
  std::optional<uint16_t> previous_port = port;
12759
12760
0
  size_t host_end_pos = input.find('#');
12761
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12762
0
                                      ? host_end_pos
12763
0
                                      : input.size());
12764
0
  helpers::remove_ascii_tab_or_newline(_host);
12765
0
  std::string_view new_host(_host);
12766
12767
  // If url's scheme is "file", then set state to file host state, instead of
12768
  // host state.
12769
0
  if (type != ada::scheme::type::FILE) {
12770
0
    std::string_view host_view(_host.data(), _host.length());
12771
0
    auto [location, found_colon] =
12772
0
        helpers::get_host_delimiter_location(is_special(), host_view);
12773
12774
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12775
    // Note: the 'found_colon' value is true if and only if a colon was
12776
    // encountered while not inside brackets.
12777
0
    if (found_colon) {
12778
      // If buffer is the empty string, host-missing validation error, return
12779
      // failure.
12780
0
      std::string_view buffer = host_view.substr(0, location);
12781
0
      if (buffer.empty()) {
12782
0
        return false;
12783
0
      }
12784
12785
      // If state override is given and state override is hostname state, then
12786
      // return failure.
12787
0
      if constexpr (override_hostname) {
12788
0
        return false;
12789
0
      }
12790
12791
      // Let host be the result of host parsing buffer with url is not special.
12792
0
      bool succeeded = parse_host(buffer);
12793
0
      if (!succeeded) {
12794
0
        host = std::move(previous_host);
12795
0
        update_base_port(previous_port);
12796
0
        return false;
12797
0
      }
12798
12799
      // Set url's host to host, buffer to the empty string, and state to port
12800
      // state.
12801
0
      std::string_view port_buffer = new_host.substr(location + 1);
12802
0
      if (!port_buffer.empty()) {
12803
0
        set_port(port_buffer);
12804
0
      }
12805
0
      return true;
12806
0
    }
12807
    // Otherwise, if one of the following is true:
12808
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12809
    // - url is special and c is U+005C (\)
12810
0
    else {
12811
      // If url is special and host_view is the empty string, host-missing
12812
      // validation error, return failure.
12813
0
      if (host_view.empty() && is_special()) {
12814
0
        return false;
12815
0
      }
12816
12817
      // Otherwise, if state override is given, host_view is the empty string,
12818
      // and either url includes credentials or url's port is non-null, then
12819
      // return failure.
12820
0
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12821
0
        return false;
12822
0
      }
12823
12824
      // Let host be the result of host parsing host_view with url is not
12825
      // special.
12826
0
      if (host_view.empty() && !is_special()) {
12827
0
        host = "";
12828
0
        return true;
12829
0
      }
12830
12831
0
      bool succeeded = parse_host(host_view);
12832
0
      if (!succeeded) {
12833
0
        host = std::move(previous_host);
12834
0
        update_base_port(previous_port);
12835
0
        return false;
12836
0
      }
12837
0
      return true;
12838
0
    }
12839
0
  }
12840
12841
0
  size_t location = new_host.find_first_of("/\\?");
12842
0
  if (location != std::string_view::npos) {
12843
0
    new_host.remove_suffix(new_host.length() - location);
12844
0
  }
12845
12846
0
  if (new_host.empty()) {
12847
    // Set url's host to the empty string.
12848
0
    host = "";
12849
0
  } else {
12850
    // Let host be the result of host parsing buffer with url is not special.
12851
0
    if (!parse_host(new_host)) {
12852
0
      host = std::move(previous_host);
12853
0
      update_base_port(previous_port);
12854
0
      return false;
12855
0
    }
12856
12857
    // If host is "localhost", then set host to the empty string.
12858
0
    if (host == "localhost") {
12859
0
      host = "";
12860
0
    }
12861
0
  }
12862
0
  return true;
12863
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> >)
12864
12865
0
bool url::set_host(const std::string_view input) {
12866
0
  return set_host_or_hostname<false>(input);
12867
0
}
12868
12869
0
bool url::set_hostname(const std::string_view input) {
12870
0
  return set_host_or_hostname<true>(input);
12871
0
}
12872
12873
0
bool url::set_username(const std::string_view input) {
12874
0
  if (cannot_have_credentials_or_port()) {
12875
0
    return false;
12876
0
  }
12877
0
  username = ada::unicode::percent_encode(
12878
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
12879
0
  return true;
12880
0
}
12881
12882
0
bool url::set_password(const std::string_view input) {
12883
0
  if (cannot_have_credentials_or_port()) {
12884
0
    return false;
12885
0
  }
12886
0
  password = ada::unicode::percent_encode(
12887
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
12888
0
  return true;
12889
0
}
12890
12891
0
bool url::set_port(const std::string_view input) {
12892
0
  if (cannot_have_credentials_or_port()) {
12893
0
    return false;
12894
0
  }
12895
12896
0
  if (input.empty()) {
12897
0
    port = std::nullopt;
12898
0
    return true;
12899
0
  }
12900
12901
0
  std::string trimmed(input);
12902
0
  helpers::remove_ascii_tab_or_newline(trimmed);
12903
12904
0
  if (trimmed.empty()) {
12905
0
    return true;
12906
0
  }
12907
12908
  // Input should not start with a non-digit character.
12909
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
12910
0
    return false;
12911
0
  }
12912
12913
  // Find the first non-digit character to determine the length of digits
12914
0
  auto first_non_digit =
12915
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
12916
0
  std::string_view digits_to_parse =
12917
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
12918
12919
  // Revert changes if parse_port fails.
12920
0
  std::optional<uint16_t> previous_port = port;
12921
0
  parse_port(digits_to_parse);
12922
0
  if (is_valid) {
12923
0
    return true;
12924
0
  }
12925
0
  port = std::move(previous_port);
12926
0
  is_valid = true;
12927
0
  return false;
12928
0
}
12929
12930
0
void url::set_hash(const std::string_view input) {
12931
0
  if (input.empty()) {
12932
0
    hash = std::nullopt;
12933
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12934
0
    return;
12935
0
  }
12936
12937
0
  std::string new_value;
12938
0
  new_value = input[0] == '#' ? input.substr(1) : input;
12939
0
  helpers::remove_ascii_tab_or_newline(new_value);
12940
0
  hash = unicode::percent_encode(new_value,
12941
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
12942
0
}
12943
12944
0
void url::set_search(const std::string_view input) {
12945
0
  if (input.empty()) {
12946
0
    query = std::nullopt;
12947
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12948
0
    return;
12949
0
  }
12950
12951
0
  std::string new_value;
12952
0
  new_value = input[0] == '?' ? input.substr(1) : input;
12953
0
  helpers::remove_ascii_tab_or_newline(new_value);
12954
12955
0
  auto query_percent_encode_set =
12956
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12957
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
12958
12959
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
12960
0
}
12961
12962
0
bool url::set_pathname(const std::string_view input) {
12963
0
  if (has_opaque_path) {
12964
0
    return false;
12965
0
  }
12966
0
  path.clear();
12967
0
  parse_path(input);
12968
0
  return true;
12969
0
}
12970
12971
0
bool url::set_protocol(const std::string_view input) {
12972
0
  std::string view(input);
12973
0
  helpers::remove_ascii_tab_or_newline(view);
12974
0
  if (view.empty()) {
12975
0
    return true;
12976
0
  }
12977
12978
  // Schemes should start with alpha values.
12979
0
  if (!checkers::is_alpha(view[0])) {
12980
0
    return false;
12981
0
  }
12982
12983
0
  view.append(":");
12984
12985
0
  std::string::iterator pointer =
12986
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
12987
12988
0
  if (pointer != view.end() && *pointer == ':') {
12989
0
    return parse_scheme<true>(
12990
0
        std::string_view(view.data(), pointer - view.begin()));
12991
0
  }
12992
0
  return false;
12993
0
}
12994
12995
0
bool url::set_href(const std::string_view input) {
12996
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
12997
12998
0
  if (out) {
12999
0
    *this = *out;
13000
0
  }
13001
13002
0
  return out.has_value();
13003
0
}
13004
13005
}  // namespace ada
13006
/* end file src/url.cpp */
13007
/* begin file src/parser.cpp */
13008
13009
#include <limits>
13010
#include <ranges>
13011
13012
13013
namespace ada::parser {
13014
13015
template <class result_type, bool store_values>
13016
result_type parse_url_impl(std::string_view user_input,
13017
0
                           const result_type* base_url) {
13018
  // We can specialize the implementation per type.
13019
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13020
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13021
  // something else } is free (at runtime). This means that ada::url_aggregator
13022
  // and ada::url **do not have to support the exact same API**.
13023
0
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13024
0
  constexpr bool result_type_is_ada_url_aggregator =
13025
0
      std::is_same_v<url_aggregator, result_type>;
13026
0
  static_assert(result_type_is_ada_url ||
13027
0
                result_type_is_ada_url_aggregator);  // We don't support
13028
                                                     // anything else for now.
13029
13030
0
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13031
0
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13032
0
          ")");
13033
13034
0
  state state = state::SCHEME_START;
13035
0
  result_type url{};
13036
13037
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
13038
  // surely the result of a bug or are otherwise a security concern.
13039
0
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
13040
0
    url.is_valid = false;
13041
0
  }
13042
  // Going forward, user_input.size() is in [0,
13043
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13044
  // base, or the optional_url was invalid, we must return.
13045
0
  if (base_url != nullptr) {
13046
0
    url.is_valid &= base_url->is_valid;
13047
0
  }
13048
0
  if (!url.is_valid) {
13049
0
    return url;
13050
0
  }
13051
0
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13052
    // Most of the time, we just need user_input.size().
13053
    // In some instances, we may need a bit more.
13054
    ///////////////////////////
13055
    // This is *very* important. This line should *not* be removed
13056
    // hastily. There are principled reasons why reserve is important
13057
    // for performance. If you have a benchmark with small inputs,
13058
    // it may not matter, but in other instances, it could.
13059
    ////
13060
    // This rounds up to the next power of two.
13061
    // We know that user_input.size() is in [0,
13062
    // std::numeric_limits<uint32_t>::max).
13063
0
    uint32_t reserve_capacity =
13064
0
        (0xFFFFFFFF >>
13065
0
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13066
0
        1;
13067
0
    url.reserve(reserve_capacity);
13068
0
  }
13069
0
  std::string tmp_buffer;
13070
0
  std::string_view url_data;
13071
0
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13072
0
    tmp_buffer = user_input;
13073
    // Optimization opportunity: Instead of copying and then pruning, we could
13074
    // just directly build the string from user_input.
13075
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13076
0
    url_data = tmp_buffer;
13077
0
  } else [[likely]] {
13078
0
    url_data = user_input;
13079
0
  }
13080
13081
  // Leading and trailing control characters are uncommon and easy to deal with
13082
  // (no performance concern).
13083
0
  helpers::trim_c0_whitespace(url_data);
13084
13085
  // Optimization opportunity. Most websites do not have fragment.
13086
0
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13087
  // We add it last so that an implementation like ada::url_aggregator
13088
  // can append it last to its internal buffer, thus improving performance.
13089
13090
  // Here url_data no longer has its fragment.
13091
  // We are going to access the data from url_data (it is immutable).
13092
  // At any given time, we are pointing at byte 'input_position' in url_data.
13093
  // The input_position variable should range from 0 to input_size.
13094
  // It is illegal to access url_data at input_size.
13095
0
  size_t input_position = 0;
13096
0
  const size_t input_size = url_data.size();
13097
  // Keep running the following state machine by switching on state.
13098
  // If after a run pointer points to the EOF code point, go to the next step.
13099
  // Otherwise, increase pointer by 1 and continue with the state machine.
13100
  // We never decrement input_position.
13101
0
  while (input_position <= input_size) {
13102
0
    ada_log("In parsing at ", input_position, " out of ", input_size,
13103
0
            " in state ", ada::to_string(state));
13104
0
    switch (state) {
13105
0
      case state::SCHEME_START: {
13106
0
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13107
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13108
        // state to scheme state.
13109
0
        if ((input_position != input_size) &&
13110
0
            checkers::is_alpha(url_data[input_position])) {
13111
0
          state = state::SCHEME;
13112
0
          input_position++;
13113
0
        } else {
13114
          // Otherwise, if state override is not given, set state to no scheme
13115
          // state and decrease pointer by 1.
13116
0
          state = state::NO_SCHEME;
13117
0
        }
13118
0
        break;
13119
0
      }
13120
0
      case state::SCHEME: {
13121
0
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13122
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13123
        // append c, lowercased, to buffer.
13124
0
        while ((input_position != input_size) &&
13125
0
               (unicode::is_alnum_plus(url_data[input_position]))) {
13126
0
          input_position++;
13127
0
        }
13128
        // Otherwise, if c is U+003A (:), then:
13129
0
        if ((input_position != input_size) &&
13130
0
            (url_data[input_position] == ':')) {
13131
0
          ada_log("SCHEME the scheme should be ",
13132
0
                  url_data.substr(0, input_position));
13133
0
          if constexpr (result_type_is_ada_url) {
13134
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13135
0
              return url;
13136
0
            }
13137
0
          } else {
13138
            // we pass the colon along instead of painfully adding it back.
13139
0
            if (!url.parse_scheme_with_colon(
13140
0
                    url_data.substr(0, input_position + 1))) {
13141
0
              return url;
13142
0
            }
13143
0
          }
13144
0
          ada_log("SCHEME the scheme is ", url.get_protocol());
13145
13146
          // If url's scheme is "file", then:
13147
0
          if (url.type == scheme::type::FILE) {
13148
            // Set state to file state.
13149
0
            state = state::FILE;
13150
0
          }
13151
          // Otherwise, if url is special, base is non-null, and base's scheme
13152
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13153
          // != nullptr is false.
13154
0
          else if (url.is_special() && base_url != nullptr &&
13155
0
                   base_url->type == url.type) {
13156
            // Set state to special relative or authority state.
13157
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13158
0
          }
13159
          // Otherwise, if url is special, set state to special authority
13160
          // slashes state.
13161
0
          else if (url.is_special()) {
13162
0
            state = state::SPECIAL_AUTHORITY_SLASHES;
13163
0
          }
13164
          // Otherwise, if remaining starts with an U+002F (/), set state to
13165
          // path or authority state and increase pointer by 1.
13166
0
          else if (input_position + 1 < input_size &&
13167
0
                   url_data[input_position + 1] == '/') {
13168
0
            state = state::PATH_OR_AUTHORITY;
13169
0
            input_position++;
13170
0
          }
13171
          // Otherwise, set url's path to the empty string and set state to
13172
          // opaque path state.
13173
0
          else {
13174
0
            state = state::OPAQUE_PATH;
13175
0
          }
13176
0
        }
13177
        // Otherwise, if state override is not given, set buffer to the empty
13178
        // string, state to no scheme state, and start over (from the first code
13179
        // point in input).
13180
0
        else {
13181
0
          state = state::NO_SCHEME;
13182
0
          input_position = 0;
13183
0
          break;
13184
0
        }
13185
0
        input_position++;
13186
0
        break;
13187
0
      }
13188
0
      case state::NO_SCHEME: {
13189
0
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13190
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13191
        // validation error, return failure.
13192
0
        if (base_url == nullptr ||
13193
0
            (base_url->has_opaque_path && !fragment.has_value())) {
13194
0
          ada_log("NO_SCHEME validation error");
13195
0
          url.is_valid = false;
13196
0
          return url;
13197
0
        }
13198
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13199
        // set url's scheme to base's scheme, url's path to base's path, url's
13200
        // query to base's query, and set state to fragment state.
13201
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13202
0
                 input_position == input_size) {
13203
0
          ada_log("NO_SCHEME opaque base with fragment");
13204
0
          url.copy_scheme(*base_url);
13205
0
          url.has_opaque_path = base_url->has_opaque_path;
13206
13207
0
          if constexpr (result_type_is_ada_url) {
13208
0
            url.path = base_url->path;
13209
0
            url.query = base_url->query;
13210
0
          } else {
13211
0
            url.update_base_pathname(base_url->get_pathname());
13212
0
            url.update_base_search(base_url->get_search());
13213
0
          }
13214
0
          url.update_unencoded_base_hash(*fragment);
13215
0
          return url;
13216
0
        }
13217
        // Otherwise, if base's scheme is not "file", set state to relative
13218
        // state and decrease pointer by 1.
13219
0
        else if (base_url->type != scheme::type::FILE) {
13220
0
          ada_log("NO_SCHEME non-file relative path");
13221
0
          state = state::RELATIVE_SCHEME;
13222
0
        }
13223
        // Otherwise, set state to file state and decrease pointer by 1.
13224
0
        else {
13225
0
          ada_log("NO_SCHEME file base type");
13226
0
          state = state::FILE;
13227
0
        }
13228
0
        break;
13229
0
      }
13230
0
      case state::AUTHORITY: {
13231
0
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13232
        // most URLs have no @. Having no @ tells us that we don't have to worry
13233
        // about AUTHORITY. Of course, we could have @ and still not have to
13234
        // worry about AUTHORITY.
13235
        // TODO: Instead of just collecting a bool, collect the location of the
13236
        // '@' and do something useful with it.
13237
        // TODO: We could do various processing early on, using a single pass
13238
        // over the string to collect information about it, e.g., telling us
13239
        // whether there is a @ and if so, where (or how many).
13240
13241
        // Check if url data contains an @.
13242
0
        if (url_data.find('@', input_position) == std::string_view::npos) {
13243
0
          state = state::HOST;
13244
0
          break;
13245
0
        }
13246
0
        bool at_sign_seen{false};
13247
0
        bool password_token_seen{false};
13248
        /**
13249
         * We expect something of the sort...
13250
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13251
         * --------^
13252
         */
13253
0
        do {
13254
0
          std::string_view view = url_data.substr(input_position);
13255
          // The delimiters are @, /, ? \\.
13256
0
          size_t location =
13257
0
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13258
0
                               : helpers::find_authority_delimiter(view);
13259
0
          std::string_view authority_view = view.substr(0, location);
13260
0
          size_t end_of_authority = input_position + authority_view.size();
13261
          // If c is U+0040 (@), then:
13262
0
          if ((end_of_authority != input_size) &&
13263
0
              (url_data[end_of_authority] == '@')) {
13264
            // If atSignSeen is true, then prepend "%40" to buffer.
13265
0
            if (at_sign_seen) {
13266
0
              if (password_token_seen) {
13267
0
                if constexpr (result_type_is_ada_url) {
13268
0
                  url.password += "%40";
13269
0
                } else {
13270
0
                  url.append_base_password("%40");
13271
0
                }
13272
0
              } else {
13273
0
                if constexpr (result_type_is_ada_url) {
13274
0
                  url.username += "%40";
13275
0
                } else {
13276
0
                  url.append_base_username("%40");
13277
0
                }
13278
0
              }
13279
0
            }
13280
13281
0
            at_sign_seen = true;
13282
13283
0
            if (!password_token_seen) {
13284
0
              size_t password_token_location = authority_view.find(':');
13285
0
              password_token_seen =
13286
0
                  password_token_location != std::string_view::npos;
13287
13288
0
              if constexpr (store_values) {
13289
0
                if (!password_token_seen) {
13290
0
                  if constexpr (result_type_is_ada_url) {
13291
0
                    url.username += unicode::percent_encode(
13292
0
                        authority_view,
13293
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13294
0
                  } else {
13295
0
                    url.append_base_username(unicode::percent_encode(
13296
0
                        authority_view,
13297
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13298
0
                  }
13299
0
                } else {
13300
0
                  if constexpr (result_type_is_ada_url) {
13301
0
                    url.username += unicode::percent_encode(
13302
0
                        authority_view.substr(0, password_token_location),
13303
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13304
0
                    url.password += unicode::percent_encode(
13305
0
                        authority_view.substr(password_token_location + 1),
13306
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13307
0
                  } else {
13308
0
                    url.append_base_username(unicode::percent_encode(
13309
0
                        authority_view.substr(0, password_token_location),
13310
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13311
0
                    url.append_base_password(unicode::percent_encode(
13312
0
                        authority_view.substr(password_token_location + 1),
13313
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13314
0
                  }
13315
0
                }
13316
0
              }
13317
0
            } else if constexpr (store_values) {
13318
0
              if constexpr (result_type_is_ada_url) {
13319
0
                url.password += unicode::percent_encode(
13320
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13321
0
              } else {
13322
0
                url.append_base_password(unicode::percent_encode(
13323
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13324
0
              }
13325
0
            }
13326
0
          }
13327
          // Otherwise, if one of the following is true:
13328
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13329
          // - url is special and c is U+005C (\)
13330
0
          else if (end_of_authority == input_size ||
13331
0
                   url_data[end_of_authority] == '/' ||
13332
0
                   url_data[end_of_authority] == '?' ||
13333
0
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13334
            // If atSignSeen is true and authority_view is the empty string,
13335
            // validation error, return failure.
13336
0
            if (at_sign_seen && authority_view.empty()) {
13337
0
              url.is_valid = false;
13338
0
              return url;
13339
0
            }
13340
0
            state = state::HOST;
13341
0
            break;
13342
0
          }
13343
0
          if (end_of_authority == input_size) {
13344
0
            if constexpr (store_values) {
13345
0
              if (fragment.has_value()) {
13346
0
                url.update_unencoded_base_hash(*fragment);
13347
0
              }
13348
0
            }
13349
0
            return url;
13350
0
          }
13351
0
          input_position = end_of_authority + 1;
13352
0
        } while (true);
13353
13354
0
        break;
13355
0
      }
13356
0
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13357
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13358
0
                helpers::substring(url_data, input_position));
13359
13360
        // If c is U+002F (/) and remaining starts with U+002F (/),
13361
        // then set state to special authority ignore slashes state and increase
13362
        // pointer by 1.
13363
0
        if (url_data.substr(input_position, 2) == "//") {
13364
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13365
0
          input_position += 2;
13366
0
        } else {
13367
          // Otherwise, validation error, set state to relative state and
13368
          // decrease pointer by 1.
13369
0
          state = state::RELATIVE_SCHEME;
13370
0
        }
13371
13372
0
        break;
13373
0
      }
13374
0
      case state::PATH_OR_AUTHORITY: {
13375
0
        ada_log("PATH_OR_AUTHORITY ",
13376
0
                helpers::substring(url_data, input_position));
13377
13378
        // If c is U+002F (/), then set state to authority state.
13379
0
        if ((input_position != input_size) &&
13380
0
            (url_data[input_position] == '/')) {
13381
0
          state = state::AUTHORITY;
13382
0
          input_position++;
13383
0
        } else {
13384
          // Otherwise, set state to path state, and decrease pointer by 1.
13385
0
          state = state::PATH;
13386
0
        }
13387
13388
0
        break;
13389
0
      }
13390
0
      case state::RELATIVE_SCHEME: {
13391
0
        ada_log("RELATIVE_SCHEME ",
13392
0
                helpers::substring(url_data, input_position));
13393
13394
        // Set url's scheme to base's scheme.
13395
0
        url.copy_scheme(*base_url);
13396
13397
        // If c is U+002F (/), then set state to relative slash state.
13398
0
        if ((input_position != input_size) &&
13399
            // NOLINTNEXTLINE(bugprone-branch-clone)
13400
0
            (url_data[input_position] == '/')) {
13401
0
          ada_log(
13402
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13403
0
              "slash state");
13404
0
          state = state::RELATIVE_SLASH;
13405
0
        } else if (url.is_special() && (input_position != input_size) &&
13406
0
                   (url_data[input_position] == '\\')) {
13407
          // Otherwise, if url is special and c is U+005C (\), validation error,
13408
          // set state to relative slash state.
13409
0
          ada_log(
13410
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13411
0
              "error, set state to relative slash state");
13412
0
          state = state::RELATIVE_SLASH;
13413
0
        } else {
13414
0
          ada_log("RELATIVE_SCHEME otherwise");
13415
          // Set url's username to base's username, url's password to base's
13416
          // password, url's host to base's host, url's port to base's port,
13417
          // url's path to a clone of base's path, and url's query to base's
13418
          // query.
13419
0
          if constexpr (result_type_is_ada_url) {
13420
0
            url.username = base_url->username;
13421
0
            url.password = base_url->password;
13422
0
            url.host = base_url->host;
13423
0
            url.port = base_url->port;
13424
            // cloning the base path includes cloning the has_opaque_path flag
13425
0
            url.has_opaque_path = base_url->has_opaque_path;
13426
0
            url.path = base_url->path;
13427
0
            url.query = base_url->query;
13428
0
          } else {
13429
0
            url.update_base_authority(base_url->get_href(),
13430
0
                                      base_url->get_components());
13431
0
            url.update_host_to_base_host(base_url->get_hostname());
13432
0
            url.update_base_port(base_url->retrieve_base_port());
13433
            // cloning the base path includes cloning the has_opaque_path flag
13434
0
            url.has_opaque_path = base_url->has_opaque_path;
13435
0
            url.update_base_pathname(base_url->get_pathname());
13436
0
            url.update_base_search(base_url->get_search());
13437
0
          }
13438
13439
0
          url.has_opaque_path = base_url->has_opaque_path;
13440
13441
          // If c is U+003F (?), then set url's query to the empty string, and
13442
          // state to query state.
13443
0
          if ((input_position != input_size) &&
13444
0
              (url_data[input_position] == '?')) {
13445
0
            state = state::QUERY;
13446
0
          }
13447
          // Otherwise, if c is not the EOF code point:
13448
0
          else if (input_position != input_size) {
13449
            // Set url's query to null.
13450
0
            url.clear_search();
13451
0
            if constexpr (result_type_is_ada_url) {
13452
              // Shorten url's path.
13453
0
              helpers::shorten_path(url.path, url.type);
13454
0
            } else {
13455
0
              std::string_view path = url.get_pathname();
13456
0
              if (helpers::shorten_path(path, url.type)) {
13457
0
                url.update_base_pathname(std::move(std::string(path)));
13458
0
              }
13459
0
            }
13460
            // Set state to path state and decrease pointer by 1.
13461
0
            state = state::PATH;
13462
0
            break;
13463
0
          }
13464
0
        }
13465
0
        input_position++;
13466
0
        break;
13467
0
      }
13468
0
      case state::RELATIVE_SLASH: {
13469
0
        ada_log("RELATIVE_SLASH ",
13470
0
                helpers::substring(url_data, input_position));
13471
13472
        // If url is special and c is U+002F (/) or U+005C (\), then:
13473
0
        if (url.is_special() && (input_position != input_size) &&
13474
0
            (url_data[input_position] == '/' ||
13475
0
             url_data[input_position] == '\\')) {
13476
          // Set state to special authority ignore slashes state.
13477
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13478
0
        }
13479
        // Otherwise, if c is U+002F (/), then set state to authority state.
13480
0
        else if ((input_position != input_size) &&
13481
0
                 (url_data[input_position] == '/')) {
13482
0
          state = state::AUTHORITY;
13483
0
        }
13484
        // Otherwise, set
13485
        // - url's username to base's username,
13486
        // - url's password to base's password,
13487
        // - url's host to base's host,
13488
        // - url's port to base's port,
13489
        // - state to path state, and then, decrease pointer by 1.
13490
0
        else {
13491
0
          if constexpr (result_type_is_ada_url) {
13492
0
            url.username = base_url->username;
13493
0
            url.password = base_url->password;
13494
0
            url.host = base_url->host;
13495
0
            url.port = base_url->port;
13496
0
          } else {
13497
0
            url.update_base_authority(base_url->get_href(),
13498
0
                                      base_url->get_components());
13499
0
            url.update_host_to_base_host(base_url->get_hostname());
13500
0
            url.update_base_port(base_url->retrieve_base_port());
13501
0
          }
13502
0
          state = state::PATH;
13503
0
          break;
13504
0
        }
13505
13506
0
        input_position++;
13507
0
        break;
13508
0
      }
13509
0
      case state::SPECIAL_AUTHORITY_SLASHES: {
13510
0
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13511
0
                helpers::substring(url_data, input_position));
13512
13513
        // If c is U+002F (/) and remaining starts with U+002F (/),
13514
        // then set state to special authority ignore slashes state and increase
13515
        // pointer by 1.
13516
0
        if (url_data.substr(input_position, 2) == "//") {
13517
0
          input_position += 2;
13518
0
        }
13519
13520
0
        [[fallthrough]];
13521
0
      }
13522
0
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13523
0
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13524
0
                helpers::substring(url_data, input_position));
13525
13526
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13527
        // authority state and decrease pointer by 1.
13528
0
        while ((input_position != input_size) &&
13529
0
               ((url_data[input_position] == '/') ||
13530
0
                (url_data[input_position] == '\\'))) {
13531
0
          input_position++;
13532
0
        }
13533
0
        state = state::AUTHORITY;
13534
13535
0
        break;
13536
0
      }
13537
0
      case state::QUERY: {
13538
0
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13539
0
        if constexpr (store_values) {
13540
          // Let queryPercentEncodeSet be the special-query percent-encode set
13541
          // if url is special; otherwise the query percent-encode set.
13542
0
          const uint8_t* query_percent_encode_set =
13543
0
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13544
0
                               : character_sets::QUERY_PERCENT_ENCODE;
13545
13546
          // Percent-encode after encoding, with encoding, buffer, and
13547
          // queryPercentEncodeSet, and append the result to url's query.
13548
0
          url.update_base_search(url_data.substr(input_position),
13549
0
                                 query_percent_encode_set);
13550
0
          ada_log("QUERY update_base_search completed ");
13551
0
          if (fragment.has_value()) {
13552
0
            url.update_unencoded_base_hash(*fragment);
13553
0
          }
13554
0
        }
13555
0
        return url;
13556
0
      }
13557
0
      case state::HOST: {
13558
0
        ada_log("HOST ", helpers::substring(url_data, input_position));
13559
13560
0
        std::string_view host_view = url_data.substr(input_position);
13561
0
        auto [location, found_colon] =
13562
0
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13563
0
        input_position = (location != std::string_view::npos)
13564
0
                             ? input_position + location
13565
0
                             : input_size;
13566
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13567
        // Note: the 'found_colon' value is true if and only if a colon was
13568
        // encountered while not inside brackets.
13569
0
        if (found_colon) {
13570
          // If buffer is the empty string, validation error, return failure.
13571
          // Let host be the result of host parsing buffer with url is not
13572
          // special.
13573
0
          ada_log("HOST parsing ", host_view);
13574
0
          if (!url.parse_host(host_view)) {
13575
0
            return url;
13576
0
          }
13577
0
          ada_log("HOST parsing results in ", url.get_hostname());
13578
          // Set url's host to host, buffer to the empty string, and state to
13579
          // port state.
13580
0
          state = state::PORT;
13581
0
          input_position++;
13582
0
        }
13583
        // Otherwise, if one of the following is true:
13584
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13585
        // - url is special and c is U+005C (\)
13586
        // The get_host_delimiter_location function either brings us to
13587
        // the colon outside of the bracket, or to one of those characters.
13588
0
        else {
13589
          // If url is special and host_view is the empty string, validation
13590
          // error, return failure.
13591
0
          if (host_view.empty() && url.is_special()) {
13592
0
            url.is_valid = false;
13593
0
            return url;
13594
0
          }
13595
0
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13596
          // Let host be the result of host parsing host_view with url is not
13597
          // special.
13598
0
          if (host_view.empty()) {
13599
0
            url.update_base_hostname("");
13600
0
          } else if (!url.parse_host(host_view)) {
13601
0
            return url;
13602
0
          }
13603
0
          ada_log("HOST parsing results in ", url.get_hostname(),
13604
0
                  " href=", url.get_href());
13605
13606
          // Set url's host to host, and state to path start state.
13607
0
          state = state::PATH_START;
13608
0
        }
13609
13610
0
        break;
13611
0
      }
13612
0
      case state::OPAQUE_PATH: {
13613
0
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13614
0
        std::string_view view = url_data.substr(input_position);
13615
        // If c is U+003F (?), then set url's query to the empty string and
13616
        // state to query state.
13617
0
        size_t location = view.find('?');
13618
0
        if (location != std::string_view::npos) {
13619
0
          view.remove_suffix(view.size() - location);
13620
0
          state = state::QUERY;
13621
0
          input_position += location + 1;
13622
0
        } else {
13623
0
          input_position = input_size + 1;
13624
0
        }
13625
0
        url.has_opaque_path = true;
13626
13627
        // This is a really unlikely scenario in real world. We should not seek
13628
        // to optimize it.
13629
0
        if (view.ends_with(' ')) {
13630
0
          std::string modified_view =
13631
0
              std::string(view.substr(0, view.size() - 1)) + "%20";
13632
0
          url.update_base_pathname(unicode::percent_encode(
13633
0
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13634
0
        } else {
13635
0
          url.update_base_pathname(unicode::percent_encode(
13636
0
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13637
0
        }
13638
0
        break;
13639
0
      }
13640
0
      case state::PORT: {
13641
0
        ada_log("PORT ", helpers::substring(url_data, input_position));
13642
0
        std::string_view port_view = url_data.substr(input_position);
13643
0
        input_position += url.parse_port(port_view, true);
13644
0
        if (!url.is_valid) {
13645
0
          return url;
13646
0
        }
13647
0
        state = state::PATH_START;
13648
0
        [[fallthrough]];
13649
0
      }
13650
0
      case state::PATH_START: {
13651
0
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13652
13653
        // If url is special, then:
13654
0
        if (url.is_special()) {
13655
          // Set state to path state.
13656
0
          state = state::PATH;
13657
13658
          // Optimization: Avoiding going into PATH state improves the
13659
          // performance of urls ending with /.
13660
0
          if (input_position == input_size) {
13661
0
            if constexpr (store_values) {
13662
0
              url.update_base_pathname("/");
13663
0
              if (fragment.has_value()) {
13664
0
                url.update_unencoded_base_hash(*fragment);
13665
0
              }
13666
0
            }
13667
0
            return url;
13668
0
          }
13669
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13670
          // by 1. We know that (input_position == input_size) is impossible
13671
          // here, because of the previous if-check.
13672
0
          if ((url_data[input_position] != '/') &&
13673
0
              (url_data[input_position] != '\\')) {
13674
0
            break;
13675
0
          }
13676
0
        }
13677
        // Otherwise, if state override is not given and c is U+003F (?),
13678
        // set url's query to the empty string and state to query state.
13679
0
        else if ((input_position != input_size) &&
13680
0
                 (url_data[input_position] == '?')) {
13681
0
          state = state::QUERY;
13682
0
        }
13683
        // Otherwise, if c is not the EOF code point:
13684
0
        else if (input_position != input_size) {
13685
          // Set state to path state.
13686
0
          state = state::PATH;
13687
13688
          // If c is not U+002F (/), then decrease pointer by 1.
13689
0
          if (url_data[input_position] != '/') {
13690
0
            break;
13691
0
          }
13692
0
        }
13693
13694
0
        input_position++;
13695
0
        break;
13696
0
      }
13697
0
      case state::PATH: {
13698
0
        ada_log("PATH ", helpers::substring(url_data, input_position));
13699
0
        std::string_view view = url_data.substr(input_position);
13700
13701
        // Most time, we do not need percent encoding.
13702
        // Furthermore, we can immediately locate the '?'.
13703
0
        size_t locofquestionmark = view.find('?');
13704
0
        if (locofquestionmark != std::string_view::npos) {
13705
0
          state = state::QUERY;
13706
0
          view.remove_suffix(view.size() - locofquestionmark);
13707
0
          input_position += locofquestionmark + 1;
13708
0
        } else {
13709
0
          input_position = input_size + 1;
13710
0
        }
13711
0
        if constexpr (store_values) {
13712
0
          if constexpr (result_type_is_ada_url) {
13713
0
            helpers::parse_prepared_path(view, url.type, url.path);
13714
0
          } else {
13715
0
            url.consume_prepared_path(view);
13716
0
            ADA_ASSERT_TRUE(url.validate());
13717
0
          }
13718
0
        }
13719
0
        break;
13720
0
      }
13721
0
      case state::FILE_SLASH: {
13722
0
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13723
13724
        // If c is U+002F (/) or U+005C (\), then:
13725
0
        if ((input_position != input_size) &&
13726
0
            (url_data[input_position] == '/' ||
13727
0
             url_data[input_position] == '\\')) {
13728
0
          ada_log("FILE_SLASH c is U+002F or U+005C");
13729
          // Set state to file host state.
13730
0
          state = state::FILE_HOST;
13731
0
          input_position++;
13732
0
        } else {
13733
0
          ada_log("FILE_SLASH otherwise");
13734
          // If base is non-null and base's scheme is "file", then:
13735
          // Note: it is unsafe to do base_url->scheme unless you know that
13736
          // base_url_has_value() is true.
13737
0
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13738
            // Set url's host to base's host.
13739
0
            if constexpr (result_type_is_ada_url) {
13740
0
              url.host = base_url->host;
13741
0
            } else {
13742
0
              url.update_host_to_base_host(base_url->get_host());
13743
0
            }
13744
            // If the code point substring from pointer to the end of input does
13745
            // not start with a Windows drive letter and base's path[0] is a
13746
            // normalized Windows drive letter, then append base's path[0] to
13747
            // url's path.
13748
0
            if (!base_url->get_pathname().empty()) {
13749
0
              if (!checkers::is_windows_drive_letter(
13750
0
                      url_data.substr(input_position))) {
13751
0
                std::string_view first_base_url_path =
13752
0
                    base_url->get_pathname().substr(1);
13753
0
                size_t loc = first_base_url_path.find('/');
13754
0
                if (loc != std::string_view::npos) {
13755
0
                  helpers::resize(first_base_url_path, loc);
13756
0
                }
13757
0
                if (checkers::is_normalized_windows_drive_letter(
13758
0
                        first_base_url_path)) {
13759
0
                  if constexpr (result_type_is_ada_url) {
13760
0
                    url.path += '/';
13761
0
                    url.path += first_base_url_path;
13762
0
                  } else {
13763
0
                    url.append_base_pathname(
13764
0
                        helpers::concat("/", first_base_url_path));
13765
0
                  }
13766
0
                }
13767
0
              }
13768
0
            }
13769
0
          }
13770
13771
          // Set state to path state, and decrease pointer by 1.
13772
0
          state = state::PATH;
13773
0
        }
13774
13775
0
        break;
13776
0
      }
13777
0
      case state::FILE_HOST: {
13778
0
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13779
0
        std::string_view view = url_data.substr(input_position);
13780
13781
0
        size_t location = view.find_first_of("/\\?");
13782
0
        std::string_view file_host_buffer(
13783
0
            view.data(),
13784
0
            (location != std::string_view::npos) ? location : view.size());
13785
13786
0
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13787
0
          state = state::PATH;
13788
0
        } else if (file_host_buffer.empty()) {
13789
          // Set url's host to the empty string.
13790
0
          if constexpr (result_type_is_ada_url) {
13791
0
            url.host = "";
13792
0
          } else {
13793
0
            url.update_base_hostname("");
13794
0
          }
13795
          // Set state to path start state.
13796
0
          state = state::PATH_START;
13797
0
        } else {
13798
0
          size_t consumed_bytes = file_host_buffer.size();
13799
0
          input_position += consumed_bytes;
13800
          // Let host be the result of host parsing buffer with url is not
13801
          // special.
13802
0
          if (!url.parse_host(file_host_buffer)) {
13803
0
            return url;
13804
0
          }
13805
13806
0
          if constexpr (result_type_is_ada_url) {
13807
            // If host is "localhost", then set host to the empty string.
13808
0
            if (url.host.has_value() && url.host.value() == "localhost") {
13809
0
              url.host = "";
13810
0
            }
13811
0
          } else {
13812
0
            if (url.get_hostname() == "localhost") {
13813
0
              url.update_base_hostname("");
13814
0
            }
13815
0
          }
13816
13817
          // Set buffer to the empty string and state to path start state.
13818
0
          state = state::PATH_START;
13819
0
        }
13820
13821
0
        break;
13822
0
      }
13823
0
      case state::FILE: {
13824
0
        ada_log("FILE ", helpers::substring(url_data, input_position));
13825
0
        std::string_view file_view = url_data.substr(input_position);
13826
13827
0
        url.set_protocol_as_file();
13828
0
        if constexpr (result_type_is_ada_url) {
13829
          // Set url's host to the empty string.
13830
0
          url.host = "";
13831
0
        } else {
13832
0
          url.update_base_hostname("");
13833
0
        }
13834
        // If c is U+002F (/) or U+005C (\), then:
13835
0
        if (input_position != input_size &&
13836
0
            (url_data[input_position] == '/' ||
13837
0
             url_data[input_position] == '\\')) {
13838
0
          ada_log("FILE c is U+002F or U+005C");
13839
          // Set state to file slash state.
13840
0
          state = state::FILE_SLASH;
13841
0
        }
13842
        // Otherwise, if base is non-null and base's scheme is "file":
13843
0
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13844
          // Set url's host to base's host, url's path to a clone of base's
13845
          // path, and url's query to base's query.
13846
0
          ada_log("FILE base non-null");
13847
0
          if constexpr (result_type_is_ada_url) {
13848
0
            url.host = base_url->host;
13849
0
            url.path = base_url->path;
13850
0
            url.query = base_url->query;
13851
0
          } else {
13852
0
            url.update_host_to_base_host(base_url->get_hostname());
13853
0
            url.update_base_pathname(base_url->get_pathname());
13854
0
            url.update_base_search(base_url->get_search());
13855
0
          }
13856
0
          url.has_opaque_path = base_url->has_opaque_path;
13857
13858
          // If c is U+003F (?), then set url's query to the empty string and
13859
          // state to query state.
13860
0
          if (input_position != input_size && url_data[input_position] == '?') {
13861
0
            state = state::QUERY;
13862
0
          }
13863
          // Otherwise, if c is not the EOF code point:
13864
0
          else if (input_position != input_size) {
13865
            // Set url's query to null.
13866
0
            url.clear_search();
13867
            // If the code point substring from pointer to the end of input does
13868
            // not start with a Windows drive letter, then shorten url's path.
13869
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13870
0
              if constexpr (result_type_is_ada_url) {
13871
0
                helpers::shorten_path(url.path, url.type);
13872
0
              } else {
13873
0
                std::string_view path = url.get_pathname();
13874
0
                if (helpers::shorten_path(path, url.type)) {
13875
0
                  url.update_base_pathname(std::move(std::string(path)));
13876
0
                }
13877
0
              }
13878
0
            }
13879
            // Otherwise:
13880
0
            else {
13881
              // Set url's path to an empty list.
13882
0
              url.clear_pathname();
13883
0
              url.has_opaque_path = true;
13884
0
            }
13885
13886
            // Set state to path state and decrease pointer by 1.
13887
0
            state = state::PATH;
13888
0
            break;
13889
0
          }
13890
0
        }
13891
        // Otherwise, set state to path state, and decrease pointer by 1.
13892
0
        else {
13893
0
          ada_log("FILE go to path");
13894
0
          state = state::PATH;
13895
0
          break;
13896
0
        }
13897
13898
0
        input_position++;
13899
0
        break;
13900
0
      }
13901
0
      default:
13902
0
        unreachable();
13903
0
    }
13904
0
  }
13905
0
  if constexpr (store_values) {
13906
0
    if (fragment.has_value()) {
13907
0
      url.update_unencoded_base_hash(*fragment);
13908
0
    }
13909
0
  }
13910
0
  return url;
13911
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*)
13912
13913
template url parse_url_impl(std::string_view user_input,
13914
                            const url* base_url = nullptr);
13915
template url_aggregator parse_url_impl(
13916
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13917
13918
template <class result_type>
13919
result_type parse_url(std::string_view user_input,
13920
0
                      const result_type* base_url) {
13921
0
  return parse_url_impl<result_type, true>(user_input, base_url);
13922
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*)
13923
13924
template url parse_url<url>(std::string_view user_input,
13925
                            const url* base_url = nullptr);
13926
template url_aggregator parse_url<url_aggregator>(
13927
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13928
}  // namespace ada::parser
13929
/* end file src/parser.cpp */
13930
/* begin file src/url_components.cpp */
13931
13932
#include <iterator>
13933
#include <string>
13934
13935
namespace ada {
13936
13937
0
[[nodiscard]] std::string url_components::to_string() const {
13938
0
  std::string answer;
13939
0
  auto back = std::back_insert_iterator(answer);
13940
0
  answer.append("{\n");
13941
13942
0
  answer.append("\t\"protocol_end\":\"");
13943
0
  helpers::encode_json(std::to_string(protocol_end), back);
13944
0
  answer.append("\",\n");
13945
13946
0
  answer.append("\t\"username_end\":\"");
13947
0
  helpers::encode_json(std::to_string(username_end), back);
13948
0
  answer.append("\",\n");
13949
13950
0
  answer.append("\t\"host_start\":\"");
13951
0
  helpers::encode_json(std::to_string(host_start), back);
13952
0
  answer.append("\",\n");
13953
13954
0
  answer.append("\t\"host_end\":\"");
13955
0
  helpers::encode_json(std::to_string(host_end), back);
13956
0
  answer.append("\",\n");
13957
13958
0
  answer.append("\t\"port\":\"");
13959
0
  helpers::encode_json(std::to_string(port), back);
13960
0
  answer.append("\",\n");
13961
13962
0
  answer.append("\t\"pathname_start\":\"");
13963
0
  helpers::encode_json(std::to_string(pathname_start), back);
13964
0
  answer.append("\",\n");
13965
13966
0
  answer.append("\t\"search_start\":\"");
13967
0
  helpers::encode_json(std::to_string(search_start), back);
13968
0
  answer.append("\",\n");
13969
13970
0
  answer.append("\t\"hash_start\":\"");
13971
0
  helpers::encode_json(std::to_string(hash_start), back);
13972
0
  answer.append("\",\n");
13973
13974
0
  answer.append("\n}");
13975
0
  return answer;
13976
0
}
13977
13978
}  // namespace ada
13979
/* end file src/url_components.cpp */
13980
/* begin file src/url_aggregator.cpp */
13981
13982
#include <iterator>
13983
#include <ranges>
13984
#include <string>
13985
#include <string_view>
13986
13987
namespace ada {
13988
template <bool has_state_override>
13989
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13990
0
    const std::string_view input_with_colon) {
13991
0
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13992
0
  ADA_ASSERT_TRUE(validate());
13993
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13994
0
  std::string_view input{input_with_colon};
13995
0
  input.remove_suffix(1);
13996
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
13997
0
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13998
  /**
13999
   * In the common case, we will immediately recognize a special scheme (e.g.,
14000
   *http, https), in which case, we can go really fast.
14001
   **/
14002
0
  if (is_input_special) {  // fast path!!!
14003
0
    if constexpr (has_state_override) {
14004
      // If url's scheme is not a special scheme and buffer is a special scheme,
14005
      // then return.
14006
0
      if (is_special() != is_input_special) {
14007
0
        return false;
14008
0
      }
14009
14010
      // If url includes credentials or has a non-null port, and buffer is
14011
      // "file", then return.
14012
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14013
0
          parsed_type == ada::scheme::type::FILE) {
14014
0
        return false;
14015
0
      }
14016
14017
      // If url's scheme is "file" and its host is an empty host, then return.
14018
      // An empty host is the empty string.
14019
0
      if (type == ada::scheme::type::FILE &&
14020
0
          components.host_start == components.host_end) {
14021
0
        return false;
14022
0
      }
14023
0
    }
14024
14025
0
    type = parsed_type;
14026
0
    set_scheme_from_view_with_colon(input_with_colon);
14027
14028
0
    if constexpr (has_state_override) {
14029
      // This is uncommon.
14030
0
      uint16_t urls_scheme_port = get_special_port();
14031
14032
      // If url's port is url's scheme's default port, then set url's port to
14033
      // null.
14034
0
      if (components.port == urls_scheme_port) {
14035
0
        clear_port();
14036
0
      }
14037
0
    }
14038
0
  } else {  // slow path
14039
0
    std::string _buffer(input);
14040
    // Next function is only valid if the input is ASCII and returns false
14041
    // otherwise, but it seems that we always have ascii content so we do not
14042
    // need to check the return value.
14043
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14044
14045
0
    if constexpr (has_state_override) {
14046
      // If url's scheme is a special scheme and buffer is not a special scheme,
14047
      // then return. If url's scheme is not a special scheme and buffer is a
14048
      // special scheme, then return.
14049
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
14050
0
        return true;
14051
0
      }
14052
14053
      // If url includes credentials or has a non-null port, and buffer is
14054
      // "file", then return.
14055
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14056
0
          _buffer == "file") {
14057
0
        return true;
14058
0
      }
14059
14060
      // If url's scheme is "file" and its host is an empty host, then return.
14061
      // An empty host is the empty string.
14062
0
      if (type == ada::scheme::type::FILE &&
14063
0
          components.host_start == components.host_end) {
14064
0
        return true;
14065
0
      }
14066
0
    }
14067
14068
0
    set_scheme(_buffer);
14069
14070
0
    if constexpr (has_state_override) {
14071
      // This is uncommon.
14072
0
      uint16_t urls_scheme_port = get_special_port();
14073
14074
      // If url's port is url's scheme's default port, then set url's port to
14075
      // null.
14076
0
      if (components.port == urls_scheme_port) {
14077
0
        clear_port();
14078
0
      }
14079
0
    }
14080
0
  }
14081
0
  ADA_ASSERT_TRUE(validate());
14082
0
  return true;
14083
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> >)
14084
14085
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
14086
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14087
0
  ADA_ASSERT_TRUE(validate());
14088
  // next line could overflow but unsigned arithmetic has well-defined
14089
  // overflows.
14090
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14091
0
  type = u.type;
14092
0
  buffer.erase(0, components.protocol_end);
14093
0
  buffer.insert(0, u.get_protocol());
14094
0
  components.protocol_end = u.components.protocol_end;
14095
14096
  // No need to update the components
14097
0
  if (new_difference == 0) {
14098
0
    return;
14099
0
  }
14100
14101
  // Update the rest of the components.
14102
0
  components.username_end += new_difference;
14103
0
  components.host_start += new_difference;
14104
0
  components.host_end += new_difference;
14105
0
  components.pathname_start += new_difference;
14106
0
  if (components.search_start != url_components::omitted) {
14107
0
    components.search_start += new_difference;
14108
0
  }
14109
0
  if (components.hash_start != url_components::omitted) {
14110
0
    components.hash_start += new_difference;
14111
0
  }
14112
0
  ADA_ASSERT_TRUE(validate());
14113
0
}
14114
14115
inline void url_aggregator::set_scheme_from_view_with_colon(
14116
0
    std::string_view new_scheme_with_colon) noexcept {
14117
0
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14118
0
          new_scheme_with_colon);
14119
0
  ADA_ASSERT_TRUE(validate());
14120
0
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14121
0
                  new_scheme_with_colon.back() == ':');
14122
  // next line could overflow but unsigned arithmetic has well-defined
14123
  // overflows.
14124
0
  uint32_t new_difference =
14125
0
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14126
14127
0
  if (buffer.empty()) {
14128
0
    buffer.append(new_scheme_with_colon);
14129
0
  } else {
14130
0
    buffer.erase(0, components.protocol_end);
14131
0
    buffer.insert(0, new_scheme_with_colon);
14132
0
  }
14133
0
  components.protocol_end += new_difference;
14134
14135
  // Update the rest of the components.
14136
0
  components.username_end += new_difference;
14137
0
  components.host_start += new_difference;
14138
0
  components.host_end += new_difference;
14139
0
  components.pathname_start += new_difference;
14140
0
  if (components.search_start != url_components::omitted) {
14141
0
    components.search_start += new_difference;
14142
0
  }
14143
0
  if (components.hash_start != url_components::omitted) {
14144
0
    components.hash_start += new_difference;
14145
0
  }
14146
0
  ADA_ASSERT_TRUE(validate());
14147
0
}
14148
14149
0
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
14150
0
  ada_log("url_aggregator::set_scheme ", new_scheme);
14151
0
  ADA_ASSERT_TRUE(validate());
14152
0
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14153
  // next line could overflow but unsigned arithmetic has well-defined
14154
  // overflows.
14155
0
  uint32_t new_difference =
14156
0
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14157
14158
0
  type = ada::scheme::get_scheme_type(new_scheme);
14159
0
  if (buffer.empty()) {
14160
0
    buffer.append(helpers::concat(new_scheme, ":"));
14161
0
  } else {
14162
0
    buffer.erase(0, components.protocol_end);
14163
0
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14164
0
  }
14165
0
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14166
14167
  // Update the rest of the components.
14168
0
  components.username_end += new_difference;
14169
0
  components.host_start += new_difference;
14170
0
  components.host_end += new_difference;
14171
0
  components.pathname_start += new_difference;
14172
0
  if (components.search_start != url_components::omitted) {
14173
0
    components.search_start += new_difference;
14174
0
  }
14175
0
  if (components.hash_start != url_components::omitted) {
14176
0
    components.hash_start += new_difference;
14177
0
  }
14178
0
  ADA_ASSERT_TRUE(validate());
14179
0
}
14180
14181
0
bool url_aggregator::set_protocol(const std::string_view input) {
14182
0
  ada_log("url_aggregator::set_protocol ", input);
14183
0
  ADA_ASSERT_TRUE(validate());
14184
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14185
0
  std::string view(input);
14186
0
  helpers::remove_ascii_tab_or_newline(view);
14187
0
  if (view.empty()) {
14188
0
    return true;
14189
0
  }
14190
14191
  // Schemes should start with alpha values.
14192
0
  if (!checkers::is_alpha(view[0])) {
14193
0
    return false;
14194
0
  }
14195
14196
0
  view.append(":");
14197
14198
0
  std::string::iterator pointer =
14199
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14200
14201
0
  if (pointer != view.end() && *pointer == ':') {
14202
0
    return parse_scheme_with_colon<true>(
14203
0
        view.substr(0, pointer - view.begin() + 1));
14204
0
  }
14205
0
  return false;
14206
0
}
14207
14208
0
bool url_aggregator::set_username(const std::string_view input) {
14209
0
  ada_log("url_aggregator::set_username '", input, "' ");
14210
0
  ADA_ASSERT_TRUE(validate());
14211
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14212
0
  if (cannot_have_credentials_or_port()) {
14213
0
    return false;
14214
0
  }
14215
0
  size_t idx = ada::unicode::percent_encode_index(
14216
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14217
0
  if (idx == input.size()) {
14218
0
    update_base_username(input);
14219
0
  } else {
14220
    // We only create a temporary string if we have to!
14221
0
    update_base_username(ada::unicode::percent_encode(
14222
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14223
0
  }
14224
0
  ADA_ASSERT_TRUE(validate());
14225
0
  return true;
14226
0
}
14227
14228
0
bool url_aggregator::set_password(const std::string_view input) {
14229
0
  ada_log("url_aggregator::set_password '", input, "'");
14230
0
  ADA_ASSERT_TRUE(validate());
14231
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14232
0
  if (cannot_have_credentials_or_port()) {
14233
0
    return false;
14234
0
  }
14235
0
  size_t idx = ada::unicode::percent_encode_index(
14236
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14237
0
  if (idx == input.size()) {
14238
0
    update_base_password(input);
14239
0
  } else {
14240
    // We only create a temporary string if we have to!
14241
0
    update_base_password(ada::unicode::percent_encode(
14242
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14243
0
  }
14244
0
  ADA_ASSERT_TRUE(validate());
14245
0
  return true;
14246
0
}
14247
14248
0
bool url_aggregator::set_port(const std::string_view input) {
14249
0
  ada_log("url_aggregator::set_port ", input);
14250
0
  ADA_ASSERT_TRUE(validate());
14251
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14252
0
  if (cannot_have_credentials_or_port()) {
14253
0
    return false;
14254
0
  }
14255
14256
0
  if (input.empty()) {
14257
0
    clear_port();
14258
0
    return true;
14259
0
  }
14260
14261
0
  std::string trimmed(input);
14262
0
  helpers::remove_ascii_tab_or_newline(trimmed);
14263
14264
0
  if (trimmed.empty()) {
14265
0
    return true;
14266
0
  }
14267
14268
  // Input should not start with a non-digit character.
14269
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14270
0
    return false;
14271
0
  }
14272
14273
  // Find the first non-digit character to determine the length of digits
14274
0
  auto first_non_digit =
14275
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14276
0
  std::string_view digits_to_parse =
14277
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14278
14279
  // Revert changes if parse_port fails.
14280
0
  uint32_t previous_port = components.port;
14281
0
  parse_port(digits_to_parse);
14282
0
  if (is_valid) {
14283
0
    return true;
14284
0
  }
14285
0
  update_base_port(previous_port);
14286
0
  is_valid = true;
14287
0
  ADA_ASSERT_TRUE(validate());
14288
0
  return false;
14289
0
}
14290
14291
0
bool url_aggregator::set_pathname(const std::string_view input) {
14292
0
  ada_log("url_aggregator::set_pathname ", input);
14293
0
  ADA_ASSERT_TRUE(validate());
14294
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14295
0
  if (has_opaque_path) {
14296
0
    return false;
14297
0
  }
14298
0
  clear_pathname();
14299
0
  parse_path(input);
14300
0
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14301
0
    buffer.insert(components.pathname_start, "/.");
14302
0
    components.pathname_start += 2;
14303
0
  }
14304
0
  ADA_ASSERT_TRUE(validate());
14305
0
  return true;
14306
0
}
14307
14308
0
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14309
0
  ada_log("url_aggregator::parse_path ", input);
14310
0
  ADA_ASSERT_TRUE(validate());
14311
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14312
0
  std::string tmp_buffer;
14313
0
  std::string_view internal_input;
14314
0
  if (unicode::has_tabs_or_newline(input)) {
14315
0
    tmp_buffer = input;
14316
    // Optimization opportunity: Instead of copying and then pruning, we could
14317
    // just directly build the string from user_input.
14318
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14319
0
    internal_input = tmp_buffer;
14320
0
  } else {
14321
0
    internal_input = input;
14322
0
  }
14323
14324
  // If url is special, then:
14325
0
  if (is_special()) {
14326
0
    if (internal_input.empty()) {
14327
0
      update_base_pathname("/");
14328
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14329
0
      consume_prepared_path(internal_input.substr(1));
14330
0
    } else {
14331
0
      consume_prepared_path(internal_input);
14332
0
    }
14333
0
  } else if (!internal_input.empty()) {
14334
0
    if (internal_input[0] == '/') {
14335
0
      consume_prepared_path(internal_input.substr(1));
14336
0
    } else {
14337
0
      consume_prepared_path(internal_input);
14338
0
    }
14339
0
  } else {
14340
    // Non-special URLs with an empty host can have their paths erased
14341
    // Path-only URLs cannot have their paths erased
14342
0
    if (components.host_start == components.host_end && !has_authority()) {
14343
0
      update_base_pathname("/");
14344
0
    }
14345
0
  }
14346
0
  ADA_ASSERT_TRUE(validate());
14347
0
}
14348
14349
0
void url_aggregator::set_search(const std::string_view input) {
14350
0
  ada_log("url_aggregator::set_search ", input);
14351
0
  ADA_ASSERT_TRUE(validate());
14352
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14353
0
  if (input.empty()) {
14354
0
    clear_search();
14355
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14356
0
    return;
14357
0
  }
14358
14359
0
  std::string new_value;
14360
0
  new_value = input[0] == '?' ? input.substr(1) : input;
14361
0
  helpers::remove_ascii_tab_or_newline(new_value);
14362
14363
0
  auto query_percent_encode_set =
14364
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14365
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14366
14367
0
  update_base_search(new_value, query_percent_encode_set);
14368
0
  ADA_ASSERT_TRUE(validate());
14369
0
}
14370
14371
0
void url_aggregator::set_hash(const std::string_view input) {
14372
0
  ada_log("url_aggregator::set_hash ", input);
14373
0
  ADA_ASSERT_TRUE(validate());
14374
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14375
0
  if (input.empty()) {
14376
0
    if (components.hash_start != url_components::omitted) {
14377
0
      buffer.resize(components.hash_start);
14378
0
      components.hash_start = url_components::omitted;
14379
0
    }
14380
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14381
0
    return;
14382
0
  }
14383
14384
0
  std::string new_value;
14385
0
  new_value = input[0] == '#' ? input.substr(1) : input;
14386
0
  helpers::remove_ascii_tab_or_newline(new_value);
14387
0
  update_unencoded_base_hash(new_value);
14388
0
  ADA_ASSERT_TRUE(validate());
14389
0
}
14390
14391
0
bool url_aggregator::set_href(const std::string_view input) {
14392
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14393
0
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14394
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14395
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
14396
14397
0
  if (out) {
14398
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14399
    // TODO: Figure out why the following line puts test to never finish.
14400
0
    *this = *out;
14401
0
  }
14402
14403
0
  return out.has_value();
14404
0
}
14405
14406
0
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14407
0
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14408
0
          " bytes]");
14409
0
  ADA_ASSERT_TRUE(validate());
14410
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14411
0
  if (input.empty()) {
14412
0
    return is_valid = false;
14413
0
  }  // technically unnecessary.
14414
  // If input starts with U+005B ([), then:
14415
0
  if (input[0] == '[') {
14416
    // If input does not end with U+005D (]), validation error, return failure.
14417
0
    if (input.back() != ']') {
14418
0
      return is_valid = false;
14419
0
    }
14420
0
    ada_log("parse_host ipv6");
14421
14422
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14423
    // trailing U+005D (]) removed.
14424
0
    input.remove_prefix(1);
14425
0
    input.remove_suffix(1);
14426
0
    return parse_ipv6(input);
14427
0
  }
14428
14429
  // If isNotSpecial is true, then return the result of opaque-host parsing
14430
  // input.
14431
0
  if (!is_special()) {
14432
0
    return parse_opaque_host(input);
14433
0
  }
14434
  // Let domain be the result of running UTF-8 decode without BOM on the
14435
  // percent-decoding of input. Let asciiDomain be the result of running domain
14436
  // to ASCII with domain and false. The most common case is an ASCII input, in
14437
  // which case we do not need to call the expensive 'to_ascii' if a few
14438
  // conditions are met: no '%' and no 'xn-' subsequence.
14439
14440
  // Often, the input does not contain any forbidden code points, and no upper
14441
  // case ASCII letter, then we can just copy it to the buffer. We want to
14442
  // optimize for such a common case.
14443
0
  uint8_t is_forbidden_or_upper =
14444
0
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14445
0
                                                             input.size());
14446
  // Minor optimization opportunity:
14447
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14448
  // the presence of characters that cannot appear in the ipv4 address and we
14449
  // could also check whether x and n and - are present, and so we could skip
14450
  // some of the checks below. However, the gains are likely to be small, and
14451
  // the code would be more complex.
14452
0
  if (is_forbidden_or_upper == 0 &&
14453
0
      input.find("xn-") == std::string_view::npos) {
14454
    // fast path
14455
0
    update_base_hostname(input);
14456
0
    if (checkers::is_ipv4(get_hostname())) {
14457
0
      ada_log("parse_host fast path ipv4");
14458
0
      return parse_ipv4(get_hostname(), true);
14459
0
    }
14460
0
    ada_log("parse_host fast path ", get_hostname());
14461
0
    return true;
14462
0
  }
14463
  // We have encountered at least one forbidden code point or the input contains
14464
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14465
  // conversion.
14466
14467
0
  ada_log("parse_host calling to_ascii");
14468
0
  std::optional<std::string> host = std::string(get_hostname());
14469
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14470
0
  if (!is_valid) {
14471
0
    ada_log("parse_host to_ascii returns false");
14472
0
    return is_valid = false;
14473
0
  }
14474
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14475
0
          " bytes]");
14476
14477
0
  if (std::ranges::any_of(host.value(),
14478
0
                          ada::unicode::is_forbidden_domain_code_point)) {
14479
0
    return is_valid = false;
14480
0
  }
14481
14482
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14483
  // asciiDomain.
14484
0
  if (checkers::is_ipv4(host.value())) {
14485
0
    ada_log("parse_host got ipv4 ", *host);
14486
0
    return parse_ipv4(host.value(), false);
14487
0
  }
14488
14489
0
  update_base_hostname(host.value());
14490
0
  ADA_ASSERT_TRUE(validate());
14491
0
  return true;
14492
0
}
14493
14494
template <bool override_hostname>
14495
0
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14496
0
  ada_log("url_aggregator::set_host_or_hostname ", input);
14497
0
  ADA_ASSERT_TRUE(validate());
14498
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14499
0
  if (has_opaque_path) {
14500
0
    return false;
14501
0
  }
14502
14503
0
  std::string previous_host(get_hostname());
14504
0
  uint32_t previous_port = components.port;
14505
14506
0
  size_t host_end_pos = input.find('#');
14507
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14508
0
                                      ? host_end_pos
14509
0
                                      : input.size());
14510
0
  helpers::remove_ascii_tab_or_newline(_host);
14511
0
  std::string_view new_host(_host);
14512
14513
  // If url's scheme is "file", then set state to file host state, instead of
14514
  // host state.
14515
0
  if (type != ada::scheme::type::FILE) {
14516
0
    std::string_view host_view(_host.data(), _host.length());
14517
0
    auto [location, found_colon] =
14518
0
        helpers::get_host_delimiter_location(is_special(), host_view);
14519
14520
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14521
    // Note: the 'found_colon' value is true if and only if a colon was
14522
    // encountered while not inside brackets.
14523
0
    if (found_colon) {
14524
      // If buffer is the empty string, host-missing validation error, return
14525
      // failure.
14526
0
      std::string_view host_buffer = host_view.substr(0, location);
14527
0
      if (host_buffer.empty()) {
14528
0
        return false;
14529
0
      }
14530
14531
      // If state override is given and state override is hostname state, then
14532
      // return failure.
14533
0
      if constexpr (override_hostname) {
14534
0
        return false;
14535
0
      }
14536
14537
      // Let host be the result of host parsing buffer with url is not special.
14538
0
      bool succeeded = parse_host(host_buffer);
14539
0
      if (!succeeded) {
14540
0
        update_base_hostname(previous_host);
14541
0
        update_base_port(previous_port);
14542
0
        return false;
14543
0
      }
14544
14545
      // Set url's host to host, buffer to the empty string, and state to port
14546
      // state.
14547
0
      std::string_view port_buffer = new_host.substr(location + 1);
14548
0
      if (!port_buffer.empty()) {
14549
0
        set_port(port_buffer);
14550
0
      }
14551
0
      return true;
14552
0
    }
14553
    // Otherwise, if one of the following is true:
14554
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14555
    // - url is special and c is U+005C (\)
14556
0
    else {
14557
      // If url is special and host_view is the empty string, host-missing
14558
      // validation error, return failure.
14559
0
      if (host_view.empty() && is_special()) {
14560
0
        return false;
14561
0
      }
14562
14563
      // Otherwise, if state override is given, host_view is the empty string,
14564
      // and either url includes credentials or url's port is non-null, then
14565
      // return failure.
14566
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14567
0
        return false;
14568
0
      }
14569
14570
      // Let host be the result of host parsing host_view with url is not
14571
      // special.
14572
0
      if (host_view.empty() && !is_special()) {
14573
0
        if (has_hostname()) {
14574
0
          clear_hostname();  // easy!
14575
0
        } else if (has_dash_dot()) {
14576
0
          add_authority_slashes_if_needed();
14577
0
          delete_dash_dot();
14578
0
        }
14579
0
        return true;
14580
0
      }
14581
14582
0
      bool succeeded = parse_host(host_view);
14583
0
      if (!succeeded) {
14584
0
        update_base_hostname(previous_host);
14585
0
        update_base_port(previous_port);
14586
0
        return false;
14587
0
      } else if (has_dash_dot()) {
14588
        // Should remove dash_dot from pathname
14589
0
        delete_dash_dot();
14590
0
      }
14591
0
      return true;
14592
0
    }
14593
0
  }
14594
14595
0
  size_t location = new_host.find_first_of("/\\?");
14596
0
  if (location != std::string_view::npos) {
14597
0
    new_host.remove_suffix(new_host.length() - location);
14598
0
  }
14599
14600
0
  if (new_host.empty()) {
14601
    // Set url's host to the empty string.
14602
0
    clear_hostname();
14603
0
  } else {
14604
    // Let host be the result of host parsing buffer with url is not special.
14605
0
    if (!parse_host(new_host)) {
14606
0
      update_base_hostname(previous_host);
14607
0
      update_base_port(previous_port);
14608
0
      return false;
14609
0
    }
14610
14611
    // If host is "localhost", then set host to the empty string.
14612
0
    if (helpers::substring(buffer, components.host_start,
14613
0
                           components.host_end) == "localhost") {
14614
0
      clear_hostname();
14615
0
    }
14616
0
  }
14617
0
  ADA_ASSERT_TRUE(validate());
14618
0
  return true;
14619
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> >)
14620
14621
0
bool url_aggregator::set_host(const std::string_view input) {
14622
0
  ada_log("url_aggregator::set_host '", input, "'");
14623
0
  ADA_ASSERT_TRUE(validate());
14624
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14625
0
  return set_host_or_hostname<false>(input);
14626
0
}
14627
14628
0
bool url_aggregator::set_hostname(const std::string_view input) {
14629
0
  ada_log("url_aggregator::set_hostname '", input, "'");
14630
0
  ADA_ASSERT_TRUE(validate());
14631
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14632
0
  return set_host_or_hostname<true>(input);
14633
0
}
14634
14635
0
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
14636
0
  ada_log("url_aggregator::get_origin");
14637
0
  if (is_special()) {
14638
    // Return a new opaque origin.
14639
0
    if (type == scheme::FILE) {
14640
0
      return "null";
14641
0
    }
14642
14643
0
    return helpers::concat(get_protocol(), "//", get_host());
14644
0
  }
14645
14646
0
  if (get_protocol() == "blob:") {
14647
0
    std::string_view path = get_pathname();
14648
0
    if (!path.empty()) {
14649
0
      auto out = ada::parse<ada::url_aggregator>(path);
14650
0
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14651
        // If pathURL's scheme is not "http" and not "https", then return a
14652
        // new opaque origin.
14653
0
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14654
0
      }
14655
0
    }
14656
0
  }
14657
14658
  // Return a new opaque origin.
14659
0
  return "null";
14660
0
}
14661
14662
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept
14663
0
    ada_lifetime_bound {
14664
0
  ada_log("url_aggregator::get_username");
14665
0
  if (has_non_empty_username()) {
14666
0
    return helpers::substring(buffer, components.protocol_end + 2,
14667
0
                              components.username_end);
14668
0
  }
14669
0
  return "";
14670
0
}
14671
14672
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept
14673
0
    ada_lifetime_bound {
14674
0
  ada_log("url_aggregator::get_password");
14675
0
  if (has_non_empty_password()) {
14676
0
    return helpers::substring(buffer, components.username_end + 1,
14677
0
                              components.host_start);
14678
0
  }
14679
0
  return "";
14680
0
}
14681
14682
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept
14683
0
    ada_lifetime_bound {
14684
0
  ada_log("url_aggregator::get_port");
14685
0
  if (components.port == url_components::omitted) {
14686
0
    return "";
14687
0
  }
14688
0
  return helpers::substring(buffer, components.host_end + 1,
14689
0
                            components.pathname_start);
14690
0
}
14691
14692
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept
14693
0
    ada_lifetime_bound {
14694
0
  ada_log("url_aggregator::get_hash");
14695
  // If this's URL's fragment is either null or the empty string, then return
14696
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14697
0
  if (components.hash_start == url_components::omitted) {
14698
0
    return "";
14699
0
  }
14700
0
  if (buffer.size() - components.hash_start <= 1) {
14701
0
    return "";
14702
0
  }
14703
0
  return helpers::substring(buffer, components.hash_start);
14704
0
}
14705
14706
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept
14707
0
    ada_lifetime_bound {
14708
0
  ada_log("url_aggregator::get_host");
14709
  // Technically, we should check if there is a hostname, but
14710
  // the code below works even if there isn't.
14711
  // if(!has_hostname()) { return ""; }
14712
0
  size_t start = components.host_start;
14713
0
  if (components.host_end > components.host_start &&
14714
0
      buffer[components.host_start] == '@') {
14715
0
    start++;
14716
0
  }
14717
  // if we have an empty host, then the space between components.host_end and
14718
  // components.pathname_start may be occupied by /.
14719
0
  if (start == components.host_end) {
14720
0
    return {};
14721
0
  }
14722
0
  return helpers::substring(buffer, start, components.pathname_start);
14723
0
}
14724
14725
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept
14726
0
    ada_lifetime_bound {
14727
0
  ada_log("url_aggregator::get_hostname");
14728
  // Technically, we should check if there is a hostname, but
14729
  // the code below works even if there isn't.
14730
  // if(!has_hostname()) { return ""; }
14731
0
  size_t start = components.host_start;
14732
  // So host_start is not where the host begins.
14733
0
  if (components.host_end > components.host_start &&
14734
0
      buffer[components.host_start] == '@') {
14735
0
    start++;
14736
0
  }
14737
0
  return helpers::substring(buffer, start, components.host_end);
14738
0
}
14739
14740
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept
14741
0
    ada_lifetime_bound {
14742
0
  ada_log("url_aggregator::get_search");
14743
  // If this's URL's query is either null or the empty string, then return the
14744
  // empty string. Return U+003F (?), followed by this's URL's query.
14745
0
  if (components.search_start == url_components::omitted) {
14746
0
    return "";
14747
0
  }
14748
0
  auto ending_index = uint32_t(buffer.size());
14749
0
  if (components.hash_start != url_components::omitted) {
14750
0
    ending_index = components.hash_start;
14751
0
  }
14752
0
  if (ending_index - components.search_start <= 1) {
14753
0
    return "";
14754
0
  }
14755
0
  return helpers::substring(buffer, components.search_start, ending_index);
14756
0
}
14757
14758
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept
14759
0
    ada_lifetime_bound {
14760
0
  ada_log("url_aggregator::get_protocol");
14761
0
  return helpers::substring(buffer, 0, components.protocol_end);
14762
0
}
14763
14764
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14765
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14766
0
          " bytes]");
14767
0
  if (!is_valid) {
14768
0
    return "null";
14769
0
  }
14770
14771
0
  std::string answer;
14772
0
  auto back = std::back_insert_iterator(answer);
14773
0
  answer.append("{\n");
14774
14775
0
  answer.append("\t\"buffer\":\"");
14776
0
  helpers::encode_json(buffer, back);
14777
0
  answer.append("\",\n");
14778
14779
0
  answer.append("\t\"protocol\":\"");
14780
0
  helpers::encode_json(get_protocol(), back);
14781
0
  answer.append("\",\n");
14782
14783
0
  if (has_credentials()) {
14784
0
    answer.append("\t\"username\":\"");
14785
0
    helpers::encode_json(get_username(), back);
14786
0
    answer.append("\",\n");
14787
0
    answer.append("\t\"password\":\"");
14788
0
    helpers::encode_json(get_password(), back);
14789
0
    answer.append("\",\n");
14790
0
  }
14791
14792
0
  answer.append("\t\"host\":\"");
14793
0
  helpers::encode_json(get_host(), back);
14794
0
  answer.append("\",\n");
14795
14796
0
  answer.append("\t\"path\":\"");
14797
0
  helpers::encode_json(get_pathname(), back);
14798
0
  answer.append("\",\n");
14799
0
  answer.append("\t\"opaque path\":");
14800
0
  answer.append((has_opaque_path ? "true" : "false"));
14801
0
  answer.append(",\n");
14802
14803
0
  if (components.search_start != url_components::omitted) {
14804
0
    answer.append("\t\"query\":\"");
14805
0
    helpers::encode_json(get_search(), back);
14806
0
    answer.append("\",\n");
14807
0
  }
14808
0
  if (components.hash_start != url_components::omitted) {
14809
0
    answer.append("\t\"fragment\":\"");
14810
0
    helpers::encode_json(get_hash(), back);
14811
0
    answer.append("\",\n");
14812
0
  }
14813
14814
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
14815
0
    if (offset == url_components::omitted) {
14816
0
      return "null";
14817
0
    } else {
14818
0
      return std::to_string(offset);
14819
0
    }
14820
0
  };
14821
14822
0
  answer.append("\t\"protocol_end\":");
14823
0
  answer.append(convert_offset_to_string(components.protocol_end));
14824
0
  answer.append(",\n");
14825
14826
0
  answer.append("\t\"username_end\":");
14827
0
  answer.append(convert_offset_to_string(components.username_end));
14828
0
  answer.append(",\n");
14829
14830
0
  answer.append("\t\"host_start\":");
14831
0
  answer.append(convert_offset_to_string(components.host_start));
14832
0
  answer.append(",\n");
14833
14834
0
  answer.append("\t\"host_end\":");
14835
0
  answer.append(convert_offset_to_string(components.host_end));
14836
0
  answer.append(",\n");
14837
14838
0
  answer.append("\t\"port\":");
14839
0
  answer.append(convert_offset_to_string(components.port));
14840
0
  answer.append(",\n");
14841
14842
0
  answer.append("\t\"pathname_start\":");
14843
0
  answer.append(convert_offset_to_string(components.pathname_start));
14844
0
  answer.append(",\n");
14845
14846
0
  answer.append("\t\"search_start\":");
14847
0
  answer.append(convert_offset_to_string(components.search_start));
14848
0
  answer.append(",\n");
14849
14850
0
  answer.append("\t\"hash_start\":");
14851
0
  answer.append(convert_offset_to_string(components.hash_start));
14852
0
  answer.append("\n}");
14853
14854
0
  return answer;
14855
0
}
14856
14857
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
14858
0
  if (components.host_start == components.host_end) {
14859
0
    return false;
14860
0
  }
14861
0
  return checkers::verify_dns_length(get_hostname());
14862
0
}
14863
14864
0
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
14865
0
  ada_log("parse_ipv4 ", input, " [", input.size(),
14866
0
          " bytes], overlaps with buffer: ",
14867
0
          helpers::overlaps(input, buffer) ? "yes" : "no");
14868
0
  ADA_ASSERT_TRUE(validate());
14869
0
  const bool trailing_dot = (input.back() == '.');
14870
0
  if (trailing_dot) {
14871
0
    input.remove_suffix(1);
14872
0
  }
14873
0
  size_t digit_count{0};
14874
0
  int pure_decimal_count = 0;  // entries that are decimal
14875
0
  uint64_t ipv4{0};
14876
  // we could unroll for better performance?
14877
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
14878
0
    uint32_t
14879
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
14880
0
    bool is_hex = checkers::has_hex_prefix(input);
14881
0
    if (is_hex && ((input.length() == 2) ||
14882
0
                   ((input.length() > 2) && (input[2] == '.')))) {
14883
      // special case
14884
0
      segment_result = 0;
14885
0
      input.remove_prefix(2);
14886
0
    } else {
14887
0
      std::from_chars_result r{};
14888
0
      if (is_hex) {
14889
0
        ada_log("parse_ipv4 trying to parse hex number");
14890
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
14891
0
                            segment_result, 16);
14892
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
14893
0
                 checkers::is_digit(input[1])) {
14894
0
        ada_log("parse_ipv4 trying to parse octal number");
14895
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
14896
0
                            segment_result, 8);
14897
0
      } else {
14898
0
        ada_log("parse_ipv4 trying to parse decimal number");
14899
0
        pure_decimal_count++;
14900
0
        r = std::from_chars(input.data(), input.data() + input.size(),
14901
0
                            segment_result, 10);
14902
0
      }
14903
0
      if (r.ec != std::errc()) {
14904
0
        ada_log("parse_ipv4 parsing failed");
14905
0
        return is_valid = false;
14906
0
      }
14907
0
      ada_log("parse_ipv4 parsed ", segment_result);
14908
0
      input.remove_prefix(r.ptr - input.data());
14909
0
    }
14910
0
    if (input.empty()) {
14911
      // We have the last value.
14912
      // At this stage, ipv4 contains digit_count*8 bits.
14913
      // So we have 32-digit_count*8 bits left.
14914
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
14915
0
        return is_valid = false;
14916
0
      }
14917
0
      ipv4 <<= (32 - digit_count * 8);
14918
0
      ipv4 |= segment_result;
14919
0
      goto final;
14920
0
    } else {
14921
      // There is more, so that the value must no be larger than 255
14922
      // and we must have a '.'.
14923
0
      if ((segment_result > 255) || (input[0] != '.')) {
14924
0
        return is_valid = false;
14925
0
      }
14926
0
      ipv4 <<= 8;
14927
0
      ipv4 |= segment_result;
14928
0
      input.remove_prefix(1);  // remove '.'
14929
0
    }
14930
0
  }
14931
0
  if ((digit_count != 4) || (!input.empty())) {
14932
0
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
14933
0
    return is_valid = false;
14934
0
  }
14935
0
final:
14936
0
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14937
0
          " host: ", get_host());
14938
14939
  // We could also check r.ptr to see where the parsing ended.
14940
0
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
14941
0
    ada_log(
14942
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
14943
0
        "buffer");
14944
    // The original input was already all decimal and we validated it. So we
14945
    // don't need to do anything.
14946
0
  } else {
14947
0
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
14948
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
14949
    // serializer.
14950
    // TODO: This is likely a bug because it goes back update_base_hostname, not
14951
    // what we want to do.
14952
0
    update_base_hostname(
14953
0
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14954
0
  }
14955
0
  host_type = IPV4;
14956
0
  ADA_ASSERT_TRUE(validate());
14957
0
  return true;
14958
0
}
14959
14960
0
bool url_aggregator::parse_ipv6(std::string_view input) {
14961
  // TODO: Implement in_place optimization: we know that input points
14962
  // in the buffer, so we can just check whether the buffer is already
14963
  // well formatted.
14964
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14965
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
14966
0
  ADA_ASSERT_TRUE(validate());
14967
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14968
0
  if (input.empty()) {
14969
0
    return is_valid = false;
14970
0
  }
14971
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14972
0
  std::array<uint16_t, 8> address{};
14973
14974
  // Let pieceIndex be 0.
14975
0
  int piece_index = 0;
14976
14977
  // Let compress be null.
14978
0
  std::optional<int> compress{};
14979
14980
  // Let pointer be a pointer for input.
14981
0
  std::string_view::iterator pointer = input.begin();
14982
14983
  // If c is U+003A (:), then:
14984
0
  if (input[0] == ':') {
14985
    // If remaining does not start with U+003A (:), validation error, return
14986
    // failure.
14987
0
    if (input.size() == 1 || input[1] != ':') {
14988
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
14989
0
      return is_valid = false;
14990
0
    }
14991
14992
    // Increase pointer by 2.
14993
0
    pointer += 2;
14994
14995
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
14996
0
    compress = ++piece_index;
14997
0
  }
14998
14999
  // While c is not the EOF code point:
15000
0
  while (pointer != input.end()) {
15001
    // If pieceIndex is 8, validation error, return failure.
15002
0
    if (piece_index == 8) {
15003
0
      ada_log("parse_ipv6 piece_index == 8");
15004
0
      return is_valid = false;
15005
0
    }
15006
15007
    // If c is U+003A (:), then:
15008
0
    if (*pointer == ':') {
15009
      // If compress is non-null, validation error, return failure.
15010
0
      if (compress.has_value()) {
15011
0
        ada_log("parse_ipv6 compress is non-null");
15012
0
        return is_valid = false;
15013
0
      }
15014
15015
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15016
      // then continue.
15017
0
      pointer++;
15018
0
      compress = ++piece_index;
15019
0
      continue;
15020
0
    }
15021
15022
    // Let value and length be 0.
15023
0
    uint16_t value = 0, length = 0;
15024
15025
    // While length is less than 4 and c is an ASCII hex digit,
15026
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15027
    // increase pointer and length by 1.
15028
0
    while (length < 4 && pointer != input.end() &&
15029
0
           unicode::is_ascii_hex_digit(*pointer)) {
15030
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15031
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15032
0
      pointer++;
15033
0
      length++;
15034
0
    }
15035
15036
    // If c is U+002E (.), then:
15037
0
    if (pointer != input.end() && *pointer == '.') {
15038
      // If length is 0, validation error, return failure.
15039
0
      if (length == 0) {
15040
0
        ada_log("parse_ipv6 length is 0");
15041
0
        return is_valid = false;
15042
0
      }
15043
15044
      // Decrease pointer by length.
15045
0
      pointer -= length;
15046
15047
      // If pieceIndex is greater than 6, validation error, return failure.
15048
0
      if (piece_index > 6) {
15049
0
        ada_log("parse_ipv6 piece_index > 6");
15050
0
        return is_valid = false;
15051
0
      }
15052
15053
      // Let numbersSeen be 0.
15054
0
      int numbers_seen = 0;
15055
15056
      // While c is not the EOF code point:
15057
0
      while (pointer != input.end()) {
15058
        // Let ipv4Piece be null.
15059
0
        std::optional<uint16_t> ipv4_piece{};
15060
15061
        // If numbersSeen is greater than 0, then:
15062
0
        if (numbers_seen > 0) {
15063
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15064
          // pointer by 1.
15065
0
          if (*pointer == '.' && numbers_seen < 4) {
15066
0
            pointer++;
15067
0
          } else {
15068
            // Otherwise, validation error, return failure.
15069
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15070
0
            return is_valid = false;
15071
0
          }
15072
0
        }
15073
15074
        // If c is not an ASCII digit, validation error, return failure.
15075
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15076
0
          ada_log(
15077
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15078
0
              "failure");
15079
0
          return is_valid = false;
15080
0
        }
15081
15082
        // While c is an ASCII digit:
15083
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15084
          // Let number be c interpreted as decimal number.
15085
0
          int number = *pointer - '0';
15086
15087
          // If ipv4Piece is null, then set ipv4Piece to number.
15088
0
          if (!ipv4_piece.has_value()) {
15089
0
            ipv4_piece = number;
15090
0
          }
15091
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15092
0
          else if (ipv4_piece == 0) {
15093
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15094
0
            return is_valid = false;
15095
0
          }
15096
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15097
0
          else {
15098
0
            ipv4_piece = *ipv4_piece * 10 + number;
15099
0
          }
15100
15101
          // If ipv4Piece is greater than 255, validation error, return failure.
15102
0
          if (ipv4_piece > 255) {
15103
0
            ada_log("parse_ipv6 ipv4_piece > 255");
15104
0
            return is_valid = false;
15105
0
          }
15106
15107
          // Increase pointer by 1.
15108
0
          pointer++;
15109
0
        }
15110
15111
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15112
        // ipv4Piece.
15113
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15114
0
        address[piece_index] =
15115
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15116
15117
        // Increase numbersSeen by 1.
15118
0
        numbers_seen++;
15119
15120
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15121
0
        if (numbers_seen == 2 || numbers_seen == 4) {
15122
0
          piece_index++;
15123
0
        }
15124
0
      }
15125
15126
      // If numbersSeen is not 4, validation error, return failure.
15127
0
      if (numbers_seen != 4) {
15128
0
        return is_valid = false;
15129
0
      }
15130
15131
      // Break.
15132
0
      break;
15133
0
    }
15134
    // Otherwise, if c is U+003A (:):
15135
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
15136
      // Increase pointer by 1.
15137
0
      pointer++;
15138
15139
      // If c is the EOF code point, validation error, return failure.
15140
0
      if (pointer == input.end()) {
15141
0
        ada_log(
15142
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
15143
0
            "failure");
15144
0
        return is_valid = false;
15145
0
      }
15146
0
    }
15147
    // Otherwise, if c is not the EOF code point, validation error, return
15148
    // failure.
15149
0
    else if (pointer != input.end()) {
15150
0
      ada_log(
15151
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15152
0
          "error, return failure");
15153
0
      return is_valid = false;
15154
0
    }
15155
15156
    // Set address[pieceIndex] to value.
15157
0
    address[piece_index] = value;
15158
15159
    // Increase pieceIndex by 1.
15160
0
    piece_index++;
15161
0
  }
15162
15163
  // If compress is non-null, then:
15164
0
  if (compress.has_value()) {
15165
    // Let swaps be pieceIndex - compress.
15166
0
    int swaps = piece_index - *compress;
15167
15168
    // Set pieceIndex to 7.
15169
0
    piece_index = 7;
15170
15171
    // While pieceIndex is not 0 and swaps is greater than 0,
15172
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15173
    // decrease both pieceIndex and swaps by 1.
15174
0
    while (piece_index != 0 && swaps > 0) {
15175
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15176
0
      piece_index--;
15177
0
      swaps--;
15178
0
    }
15179
0
  }
15180
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15181
  // return failure.
15182
0
  else if (piece_index != 8) {
15183
0
    ada_log(
15184
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15185
0
        "error, return failure");
15186
0
    return is_valid = false;
15187
0
  }
15188
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15189
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15190
  // what we want to do.
15191
0
  update_base_hostname(ada::serializers::ipv6(address));
15192
0
  ada_log("parse_ipv6 ", get_hostname());
15193
0
  ADA_ASSERT_TRUE(validate());
15194
0
  host_type = IPV6;
15195
0
  return true;
15196
0
}
15197
15198
0
bool url_aggregator::parse_opaque_host(std::string_view input) {
15199
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15200
0
  ADA_ASSERT_TRUE(validate());
15201
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15202
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15203
0
    return is_valid = false;
15204
0
  }
15205
15206
  // Return the result of running UTF-8 percent-encode on input using the C0
15207
  // control percent-encode set.
15208
0
  size_t idx = ada::unicode::percent_encode_index(
15209
0
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15210
0
  if (idx == input.size()) {
15211
0
    update_base_hostname(input);
15212
0
  } else {
15213
    // We only create a temporary string if we need to.
15214
0
    update_base_hostname(ada::unicode::percent_encode(
15215
0
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15216
0
  }
15217
0
  ADA_ASSERT_TRUE(validate());
15218
0
  return true;
15219
0
}
15220
15221
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15222
0
  if (!is_valid) {
15223
0
    return "invalid";
15224
0
  }
15225
0
  std::string answer;
15226
0
  answer.append(buffer);
15227
0
  answer.append(" [");
15228
0
  answer.append(std::to_string(buffer.size()));
15229
0
  answer.append(" bytes]");
15230
0
  answer.append("\n");
15231
  // first line
15232
0
  std::string line1;
15233
0
  line1.resize(buffer.size(), ' ');
15234
0
  if (components.hash_start != url_components::omitted) {
15235
0
    line1[components.hash_start] = '|';
15236
0
  }
15237
0
  if (components.search_start != url_components::omitted) {
15238
0
    line1[components.search_start] = '|';
15239
0
  }
15240
0
  if (components.pathname_start != buffer.size()) {
15241
0
    line1[components.pathname_start] = '|';
15242
0
  }
15243
0
  if (components.host_end != buffer.size()) {
15244
0
    line1[components.host_end] = '|';
15245
0
  }
15246
0
  if (components.host_start != buffer.size()) {
15247
0
    line1[components.host_start] = '|';
15248
0
  }
15249
0
  if (components.username_end != buffer.size()) {
15250
0
    line1[components.username_end] = '|';
15251
0
  }
15252
0
  if (components.protocol_end != buffer.size()) {
15253
0
    line1[components.protocol_end] = '|';
15254
0
  }
15255
0
  answer.append(line1);
15256
0
  answer.append("\n");
15257
15258
0
  std::string line2 = line1;
15259
0
  if (components.hash_start != url_components::omitted) {
15260
0
    line2[components.hash_start] = '`';
15261
0
    line1[components.hash_start] = ' ';
15262
15263
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15264
0
      line2[i] = '-';
15265
0
    }
15266
0
    line2.append(" hash_start");
15267
0
    answer.append(line2);
15268
0
    answer.append("\n");
15269
0
  }
15270
15271
0
  std::string line3 = line1;
15272
0
  if (components.search_start != url_components::omitted) {
15273
0
    line3[components.search_start] = '`';
15274
0
    line1[components.search_start] = ' ';
15275
15276
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15277
0
      line3[i] = '-';
15278
0
    }
15279
0
    line3.append(" search_start ");
15280
0
    line3.append(std::to_string(components.search_start));
15281
0
    answer.append(line3);
15282
0
    answer.append("\n");
15283
0
  }
15284
15285
0
  std::string line4 = line1;
15286
0
  if (components.pathname_start != buffer.size()) {
15287
0
    line4[components.pathname_start] = '`';
15288
0
    line1[components.pathname_start] = ' ';
15289
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15290
0
      line4[i] = '-';
15291
0
    }
15292
0
    line4.append(" pathname_start ");
15293
0
    line4.append(std::to_string(components.pathname_start));
15294
0
    answer.append(line4);
15295
0
    answer.append("\n");
15296
0
  }
15297
15298
0
  std::string line5 = line1;
15299
0
  if (components.host_end != buffer.size()) {
15300
0
    line5[components.host_end] = '`';
15301
0
    line1[components.host_end] = ' ';
15302
15303
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15304
0
      line5[i] = '-';
15305
0
    }
15306
0
    line5.append(" host_end ");
15307
0
    line5.append(std::to_string(components.host_end));
15308
0
    answer.append(line5);
15309
0
    answer.append("\n");
15310
0
  }
15311
15312
0
  std::string line6 = line1;
15313
0
  if (components.host_start != buffer.size()) {
15314
0
    line6[components.host_start] = '`';
15315
0
    line1[components.host_start] = ' ';
15316
15317
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15318
0
      line6[i] = '-';
15319
0
    }
15320
0
    line6.append(" host_start ");
15321
0
    line6.append(std::to_string(components.host_start));
15322
0
    answer.append(line6);
15323
0
    answer.append("\n");
15324
0
  }
15325
15326
0
  std::string line7 = line1;
15327
0
  if (components.username_end != buffer.size()) {
15328
0
    line7[components.username_end] = '`';
15329
0
    line1[components.username_end] = ' ';
15330
15331
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15332
0
      line7[i] = '-';
15333
0
    }
15334
0
    line7.append(" username_end ");
15335
0
    line7.append(std::to_string(components.username_end));
15336
0
    answer.append(line7);
15337
0
    answer.append("\n");
15338
0
  }
15339
15340
0
  std::string line8 = line1;
15341
0
  if (components.protocol_end != buffer.size()) {
15342
0
    line8[components.protocol_end] = '`';
15343
0
    line1[components.protocol_end] = ' ';
15344
15345
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15346
0
      line8[i] = '-';
15347
0
    }
15348
0
    line8.append(" protocol_end ");
15349
0
    line8.append(std::to_string(components.protocol_end));
15350
0
    answer.append(line8);
15351
0
    answer.append("\n");
15352
0
  }
15353
15354
0
  if (components.hash_start == url_components::omitted) {
15355
0
    answer.append("note: hash omitted\n");
15356
0
  }
15357
0
  if (components.search_start == url_components::omitted) {
15358
0
    answer.append("note: search omitted\n");
15359
0
  }
15360
0
  if (components.protocol_end > buffer.size()) {
15361
0
    answer.append("warning: protocol_end overflows\n");
15362
0
  }
15363
0
  if (components.username_end > buffer.size()) {
15364
0
    answer.append("warning: username_end overflows\n");
15365
0
  }
15366
0
  if (components.host_start > buffer.size()) {
15367
0
    answer.append("warning: host_start overflows\n");
15368
0
  }
15369
0
  if (components.host_end > buffer.size()) {
15370
0
    answer.append("warning: host_end overflows\n");
15371
0
  }
15372
0
  if (components.pathname_start > buffer.size()) {
15373
0
    answer.append("warning: pathname_start overflows\n");
15374
0
  }
15375
0
  return answer;
15376
0
}
15377
15378
0
void url_aggregator::delete_dash_dot() {
15379
0
  ada_log("url_aggregator::delete_dash_dot");
15380
0
  ADA_ASSERT_TRUE(validate());
15381
0
  ADA_ASSERT_TRUE(has_dash_dot());
15382
0
  buffer.erase(components.host_end, 2);
15383
0
  components.pathname_start -= 2;
15384
0
  if (components.search_start != url_components::omitted) {
15385
0
    components.search_start -= 2;
15386
0
  }
15387
0
  if (components.hash_start != url_components::omitted) {
15388
0
    components.hash_start -= 2;
15389
0
  }
15390
0
  ADA_ASSERT_TRUE(validate());
15391
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15392
0
}
15393
15394
0
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15395
0
  ada_log("url_aggregator::consume_prepared_path ", input);
15396
  /***
15397
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15398
   * unfortunate. This particular function is nearly identical, except that it
15399
   * is a method on url_aggregator. The idea is that the trivial path (which is
15400
   * very common) merely appends to the buffer. This is the same trivial path as
15401
   * with helpers::parse_prepared_path, except that we have the additional check
15402
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15403
   * modify it, and then insert it back into the buffer.
15404
   */
15405
0
  uint8_t accumulator = checkers::path_signature(input);
15406
  // Let us first detect a trivial case.
15407
  // If it is special, we check that we have no dot, no %,  no \ and no
15408
  // character needing percent encoding. Otherwise, we check that we have no %,
15409
  // no dot, and no character needing percent encoding.
15410
0
  constexpr uint8_t need_encoding = 1;
15411
0
  constexpr uint8_t backslash_char = 2;
15412
0
  constexpr uint8_t dot_char = 4;
15413
0
  constexpr uint8_t percent_char = 8;
15414
0
  bool special = type != ada::scheme::NOT_SPECIAL;
15415
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15416
0
                                      checkers::is_windows_drive_letter(input));
15417
0
  bool trivial_path =
15418
0
      (special ? (accumulator == 0)
15419
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15420
0
                  0)) &&
15421
0
      (!may_need_slow_file_handling);
15422
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15423
    // '4' means that we have at least one dot, but nothing that requires
15424
    // percent encoding or decoding. The only part that is not trivial is
15425
    // that we may have single dots and double dots path segments.
15426
    // If we have such segments, then we either have a path that begins
15427
    // with '.' (easy to check), or we have the sequence './'.
15428
    // Note: input cannot be empty, it must at least contain one character ('.')
15429
    // Note: we know that '\' is not present.
15430
0
    if (input[0] != '.') {
15431
0
      size_t slashdot = 0;
15432
0
      bool dot_is_file = true;
15433
0
      for (;;) {
15434
0
        slashdot = input.find("/.", slashdot);
15435
0
        if (slashdot == std::string_view::npos) {  // common case
15436
0
          break;
15437
0
        } else {  // uncommon
15438
          // only three cases matter: /./, /.. or a final /
15439
0
          slashdot += 2;
15440
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15441
0
                           input[slashdot] == '/');
15442
0
        }
15443
0
      }
15444
0
      trivial_path = dot_is_file;
15445
0
    }
15446
0
  }
15447
0
  if (trivial_path && is_at_path()) {
15448
0
    ada_log("parse_path trivial");
15449
0
    buffer += '/';
15450
0
    buffer += input;
15451
0
    return;
15452
0
  }
15453
0
  std::string path = std::string(get_pathname());
15454
  // We are going to need to look a bit at the path, but let us see if we can
15455
  // ignore percent encoding *and* backslashes *and* percent characters.
15456
  // Except for the trivial case, this is likely to capture 99% of paths out
15457
  // there.
15458
0
  bool fast_path =
15459
0
      (special &&
15460
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15461
0
      (type != ada::scheme::type::FILE);
15462
0
  if (fast_path) {
15463
0
    ada_log("parse_prepared_path fast");
15464
    // Here we don't need to worry about \ or percent encoding.
15465
    // We also do not have a file protocol. We might have dots, however,
15466
    // but dots must as appear as '.', and they cannot be encoded because
15467
    // the symbol '%' is not present.
15468
0
    size_t previous_location = 0;  // We start at 0.
15469
0
    do {
15470
0
      size_t new_location = input.find('/', previous_location);
15471
      // std::string_view path_view = input;
15472
      //  We process the last segment separately:
15473
0
      if (new_location == std::string_view::npos) {
15474
0
        std::string_view path_view = input.substr(previous_location);
15475
0
        if (path_view == "..") {  // The path ends with ..
15476
          // e.g., if you receive ".." with an empty path, you go to "/".
15477
0
          if (path.empty()) {
15478
0
            path = '/';
15479
0
            update_base_pathname(path);
15480
0
            return;
15481
0
          }
15482
          // Fast case where we have nothing to do:
15483
0
          if (path.back() == '/') {
15484
0
            update_base_pathname(path);
15485
0
            return;
15486
0
          }
15487
          // If you have the path "/joe/myfriend",
15488
          // then you delete 'myfriend'.
15489
0
          path.resize(path.rfind('/') + 1);
15490
0
          update_base_pathname(path);
15491
0
          return;
15492
0
        }
15493
0
        path += '/';
15494
0
        if (path_view != ".") {
15495
0
          path.append(path_view);
15496
0
        }
15497
0
        update_base_pathname(path);
15498
0
        return;
15499
0
      } else {
15500
        // This is a non-final segment.
15501
0
        std::string_view path_view =
15502
0
            input.substr(previous_location, new_location - previous_location);
15503
0
        previous_location = new_location + 1;
15504
0
        if (path_view == "..") {
15505
0
          size_t last_delimiter = path.rfind('/');
15506
0
          if (last_delimiter != std::string::npos) {
15507
0
            path.erase(last_delimiter);
15508
0
          }
15509
0
        } else if (path_view != ".") {
15510
0
          path += '/';
15511
0
          path.append(path_view);
15512
0
        }
15513
0
      }
15514
0
    } while (true);
15515
0
  } else {
15516
0
    ada_log("parse_path slow");
15517
    // we have reached the general case
15518
0
    bool needs_percent_encoding = (accumulator & 1);
15519
0
    std::string path_buffer_tmp;
15520
0
    do {
15521
0
      size_t location = (special && (accumulator & 2))
15522
0
                            ? input.find_first_of("/\\")
15523
0
                            : input.find('/');
15524
0
      std::string_view path_view = input;
15525
0
      if (location != std::string_view::npos) {
15526
0
        path_view.remove_suffix(path_view.size() - location);
15527
0
        input.remove_prefix(location + 1);
15528
0
      }
15529
      // path_buffer is either path_view or it might point at a percent encoded
15530
      // temporary string.
15531
0
      std::string_view path_buffer =
15532
0
          (needs_percent_encoding &&
15533
0
           ada::unicode::percent_encode<false>(
15534
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15535
0
              ? path_buffer_tmp
15536
0
              : path_view;
15537
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15538
0
        helpers::shorten_path(path, type);
15539
0
        if (location == std::string_view::npos) {
15540
0
          path += '/';
15541
0
        }
15542
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15543
0
                 (location == std::string_view::npos)) {
15544
0
        path += '/';
15545
0
      }
15546
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15547
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15548
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15549
        // Windows drive letter, then replace the second code point in
15550
        // path_buffer with U+003A (:).
15551
0
        if (type == ada::scheme::type::FILE && path.empty() &&
15552
0
            checkers::is_windows_drive_letter(path_buffer)) {
15553
0
          path += '/';
15554
0
          path += path_buffer[0];
15555
0
          path += ':';
15556
0
          path_buffer.remove_prefix(2);
15557
0
          path.append(path_buffer);
15558
0
        } else {
15559
          // Append path_buffer to url's path.
15560
0
          path += '/';
15561
0
          path.append(path_buffer);
15562
0
        }
15563
0
      }
15564
0
      if (location == std::string_view::npos) {
15565
0
        update_base_pathname(path);
15566
0
        return;
15567
0
      }
15568
0
    } while (true);
15569
0
  }
15570
0
}
15571
}  // namespace ada
15572
/* end file src/url_aggregator.cpp */
15573
15574
#if ADA_INCLUDE_URL_PATTERN
15575
/* begin file src/url_pattern.cpp */
15576
#if ADA_INCLUDE_URL_PATTERN
15577
15578
15579
#include <algorithm>
15580
#include <optional>
15581
#include <string>
15582
15583
namespace ada {
15584
15585
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15586
    const url_pattern_init& init, url_pattern_init::process_type type,
15587
    std::optional<std::string_view> protocol,
15588
    std::optional<std::string_view> username,
15589
    std::optional<std::string_view> password,
15590
    std::optional<std::string_view> hostname,
15591
    std::optional<std::string_view> port,
15592
    std::optional<std::string_view> pathname,
15593
    std::optional<std::string_view> search,
15594
0
    std::optional<std::string_view> hash) {
15595
  // Let result be the result of creating a new URLPatternInit.
15596
0
  auto result = url_pattern_init{};
15597
15598
  // If protocol is not null, set result["protocol"] to protocol.
15599
0
  if (protocol.has_value()) result.protocol = *protocol;
15600
15601
  // If username is not null, set result["username"] to username.
15602
0
  if (username.has_value()) result.username = *username;
15603
15604
  // If password is not null, set result["password"] to password.
15605
0
  if (password.has_value()) result.password = *password;
15606
15607
  // If hostname is not null, set result["hostname"] to hostname.
15608
0
  if (hostname.has_value()) result.hostname = *hostname;
15609
15610
  // If port is not null, set result["port"] to port.
15611
0
  if (port.has_value()) result.port = *port;
15612
15613
  // If pathname is not null, set result["pathname"] to pathname.
15614
0
  if (pathname.has_value()) result.pathname = *pathname;
15615
15616
  // If search is not null, set result["search"] to search.
15617
0
  if (search.has_value()) result.search = *search;
15618
15619
  // If hash is not null, set result["hash"] to hash.
15620
0
  if (hash.has_value()) result.hash = *hash;
15621
15622
  // Let baseURL be null.
15623
0
  std::optional<url_aggregator> base_url{};
15624
15625
  // If init["baseURL"] exists:
15626
0
  if (init.base_url.has_value()) {
15627
    // Set baseURL to the result of parsing init["baseURL"].
15628
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15629
    // If baseURL is failure, then throw a TypeError.
15630
0
    if (!parsing_result) {
15631
0
      return tl::unexpected(errors::type_error);
15632
0
    }
15633
0
    base_url = std::move(*parsing_result);
15634
15635
    // If init["protocol"] does not exist, then set result["protocol"] to the
15636
    // result of processing a base URL string given baseURL's scheme and type.
15637
0
    if (!init.protocol.has_value()) {
15638
0
      ADA_ASSERT_TRUE(base_url.has_value());
15639
0
      std::string_view base_url_protocol = base_url->get_protocol();
15640
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15641
0
      result.protocol =
15642
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15643
0
    }
15644
15645
    // If type is not "pattern" and init contains none of "protocol",
15646
    // "hostname", "port" and "username", then set result["username"] to the
15647
    // result of processing a base URL string given baseURL's username and type.
15648
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15649
0
        !init.port && !init.username) {
15650
0
      result.username = url_pattern_helpers::process_base_url_string(
15651
0
          base_url->get_username(), type);
15652
0
    }
15653
15654
    // TODO: Optimization opportunity: Merge this with the previous check.
15655
    // If type is not "pattern" and init contains none of "protocol",
15656
    // "hostname", "port", "username" and "password", then set
15657
    // result["password"] to the result of processing a base URL string given
15658
    // baseURL's password and type.
15659
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15660
0
        !init.port && !init.username && !init.password) {
15661
0
      result.password = url_pattern_helpers::process_base_url_string(
15662
0
          base_url->get_password(), type);
15663
0
    }
15664
15665
    // If init contains neither "protocol" nor "hostname", then:
15666
0
    if (!init.protocol && !init.hostname) {
15667
      // Let baseHost be baseURL's host.
15668
      // If baseHost is null, then set baseHost to the empty string.
15669
0
      auto base_host = base_url->get_hostname();
15670
      // Set result["hostname"] to the result of processing a base URL string
15671
      // given baseHost and type.
15672
0
      result.hostname =
15673
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15674
0
    }
15675
15676
    // If init contains none of "protocol", "hostname", and "port", then:
15677
0
    if (!init.protocol && !init.hostname && !init.port) {
15678
      // If baseURL's port is null, then set result["port"] to the empty string.
15679
      // Otherwise, set result["port"] to baseURL's port, serialized.
15680
0
      result.port = base_url->get_port();
15681
0
    }
15682
15683
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15684
    // then set result["pathname"] to the result of processing a base URL string
15685
    // given the result of URL path serializing baseURL and type.
15686
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15687
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15688
0
          base_url->get_pathname(), type);
15689
0
    }
15690
15691
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15692
    // "search", then:
15693
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15694
0
        !init.search) {
15695
      // Let baseQuery be baseURL's query.
15696
      // Set result["search"] to the result of processing a base URL string
15697
      // given baseQuery and type.
15698
0
      result.search = url_pattern_helpers::process_base_url_string(
15699
0
          base_url->get_search(), type);
15700
0
    }
15701
15702
    // If init contains none of "protocol", "hostname", "port", "pathname",
15703
    // "search", and "hash", then:
15704
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15705
0
        !init.search && !init.hash) {
15706
      // Let baseFragment be baseURL's fragment.
15707
      // Set result["hash"] to the result of processing a base URL string given
15708
      // baseFragment and type.
15709
0
      result.hash = url_pattern_helpers::process_base_url_string(
15710
0
          base_url->get_hash(), type);
15711
0
    }
15712
0
  }
15713
15714
  // If init["protocol"] exists, then set result["protocol"] to the result of
15715
  // process protocol for init given init["protocol"] and type.
15716
0
  if (init.protocol) {
15717
0
    auto process_result = process_protocol(*init.protocol, type);
15718
0
    if (!process_result) {
15719
0
      return tl::unexpected(process_result.error());
15720
0
    }
15721
0
    result.protocol = std::move(*process_result);
15722
0
  }
15723
15724
  // If init["username"] exists, then set result["username"] to the result of
15725
  // process username for init given init["username"] and type.
15726
0
  if (init.username.has_value()) {
15727
0
    auto process_result = process_username(*init.username, type);
15728
0
    if (!process_result) {
15729
0
      return tl::unexpected(process_result.error());
15730
0
    }
15731
0
    result.username = std::move(*process_result);
15732
0
  }
15733
15734
  // If init["password"] exists, then set result["password"] to the result of
15735
  // process password for init given init["password"] and type.
15736
0
  if (init.password.has_value()) {
15737
0
    auto process_result = process_password(*init.password, type);
15738
0
    if (!process_result) {
15739
0
      return tl::unexpected(process_result.error());
15740
0
    }
15741
0
    result.password = std::move(*process_result);
15742
0
  }
15743
15744
  // If init["hostname"] exists, then set result["hostname"] to the result of
15745
  // process hostname for init given init["hostname"] and type.
15746
0
  if (init.hostname.has_value()) {
15747
0
    auto process_result = process_hostname(*init.hostname, type);
15748
0
    if (!process_result) {
15749
0
      return tl::unexpected(process_result.error());
15750
0
    }
15751
0
    result.hostname = std::move(*process_result);
15752
0
  }
15753
15754
  // If init["port"] exists, then set result["port"] to the result of process
15755
  // port for init given init["port"], result["protocol"], and type.
15756
0
  if (init.port) {
15757
0
    auto process_result =
15758
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15759
0
    if (!process_result) {
15760
0
      return tl::unexpected(process_result.error());
15761
0
    }
15762
0
    result.port = std::move(*process_result);
15763
0
  }
15764
15765
  // If init["pathname"] exists:
15766
0
  if (init.pathname.has_value()) {
15767
    // Set result["pathname"] to init["pathname"].
15768
0
    result.pathname = init.pathname;
15769
15770
    // If the following are all true:
15771
    // - baseURL is not null;
15772
    // - baseURL has an opaque path; and
15773
    // - the result of running is an absolute pathname given result["pathname"]
15774
    // and type is false,
15775
0
    if (base_url && !base_url->has_opaque_path &&
15776
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15777
      // Let baseURLPath be the result of running process a base URL string
15778
      // given the result of URL path serializing baseURL and type.
15779
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15780
      // exist.
15781
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
15782
0
          base_url->get_pathname(), type);
15783
15784
      // Let slash index be the index of the last U+002F (/) code point found in
15785
      // baseURLPath, interpreted as a sequence of code points, or null if there
15786
      // are no instances of the code point.
15787
0
      auto slash_index = base_url_path.find_last_of('/');
15788
15789
      // If slash index is not null:
15790
0
      if (slash_index != std::string::npos) {
15791
        // Let new pathname be the code point substring from 0 to slash index +
15792
        // 1 within baseURLPath.
15793
0
        base_url_path.resize(slash_index + 1);
15794
        // Append result["pathname"] to the end of new pathname.
15795
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
15796
0
        base_url_path.append(std::move(*result.pathname));
15797
        // Set result["pathname"] to new pathname.
15798
0
        result.pathname = std::move(base_url_path);
15799
0
      }
15800
0
    }
15801
15802
    // Set result["pathname"] to the result of process pathname for init given
15803
    // result["pathname"], result["protocol"], and type.
15804
0
    auto pathname_processing_result =
15805
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
15806
0
    if (!pathname_processing_result) {
15807
0
      return tl::unexpected(pathname_processing_result.error());
15808
0
    }
15809
0
    result.pathname = std::move(*pathname_processing_result);
15810
0
  }
15811
15812
  // If init["search"] exists then set result["search"] to the result of process
15813
  // search for init given init["search"] and type.
15814
0
  if (init.search) {
15815
0
    auto process_result = process_search(*init.search, type);
15816
0
    if (!process_result) {
15817
0
      return tl::unexpected(process_result.error());
15818
0
    }
15819
0
    result.search = std::move(*process_result);
15820
0
  }
15821
15822
  // If init["hash"] exists then set result["hash"] to the result of process
15823
  // hash for init given init["hash"] and type.
15824
0
  if (init.hash) {
15825
0
    auto process_result = process_hash(*init.hash, type);
15826
0
    if (!process_result) {
15827
0
      return tl::unexpected(process_result.error());
15828
0
    }
15829
0
    result.hash = std::move(*process_result);
15830
0
  }
15831
  // Return result.
15832
0
  return result;
15833
0
}
15834
15835
tl::expected<std::string, errors> url_pattern_init::process_protocol(
15836
0
    std::string_view value, process_type type) {
15837
0
  ada_log("process_protocol=", value, " [", type, "]");
15838
  // Let strippedValue be the given value with a single trailing U+003A (:)
15839
  // removed, if any.
15840
0
  if (value.ends_with(":")) {
15841
0
    value.remove_suffix(1);
15842
0
  }
15843
  // If type is "pattern" then return strippedValue.
15844
0
  if (type == process_type::pattern) {
15845
0
    return std::string(value);
15846
0
  }
15847
  // Return the result of running canonicalize a protocol given strippedValue.
15848
0
  return url_pattern_helpers::canonicalize_protocol(value);
15849
0
}
15850
15851
tl::expected<std::string, errors> url_pattern_init::process_username(
15852
0
    std::string_view value, process_type type) {
15853
  // If type is "pattern" then return value.
15854
0
  if (type == process_type::pattern) {
15855
0
    return std::string(value);
15856
0
  }
15857
  // Return the result of running canonicalize a username given value.
15858
0
  return url_pattern_helpers::canonicalize_username(value);
15859
0
}
15860
15861
tl::expected<std::string, errors> url_pattern_init::process_password(
15862
0
    std::string_view value, process_type type) {
15863
  // If type is "pattern" then return value.
15864
0
  if (type == process_type::pattern) {
15865
0
    return std::string(value);
15866
0
  }
15867
  // Return the result of running canonicalize a password given value.
15868
0
  return url_pattern_helpers::canonicalize_password(value);
15869
0
}
15870
15871
tl::expected<std::string, errors> url_pattern_init::process_hostname(
15872
0
    std::string_view value, process_type type) {
15873
0
  ada_log("process_hostname value=", value, " type=", type);
15874
  // If type is "pattern" then return value.
15875
0
  if (type == process_type::pattern) {
15876
0
    return std::string(value);
15877
0
  }
15878
  // Return the result of running canonicalize a hostname given value.
15879
0
  return url_pattern_helpers::canonicalize_hostname(value);
15880
0
}
15881
15882
tl::expected<std::string, errors> url_pattern_init::process_port(
15883
0
    std::string_view port, std::string_view protocol, process_type type) {
15884
  // If type is "pattern" then return portValue.
15885
0
  if (type == process_type::pattern) {
15886
0
    return std::string(port);
15887
0
  }
15888
  // Return the result of running canonicalize a port given portValue and
15889
  // protocolValue.
15890
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
15891
0
}
15892
15893
tl::expected<std::string, errors> url_pattern_init::process_pathname(
15894
0
    std::string_view value, std::string_view protocol, process_type type) {
15895
  // If type is "pattern" then return pathnameValue.
15896
0
  if (type == process_type::pattern) {
15897
0
    return std::string(value);
15898
0
  }
15899
15900
  // If protocolValue is a special scheme or the empty string, then return the
15901
  // result of running canonicalize a pathname given pathnameValue.
15902
0
  if (protocol.empty() || scheme::is_special(protocol)) {
15903
0
    return url_pattern_helpers::canonicalize_pathname(value);
15904
0
  }
15905
15906
  // Return the result of running canonicalize an opaque pathname given
15907
  // pathnameValue.
15908
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
15909
0
}
15910
15911
tl::expected<std::string, errors> url_pattern_init::process_search(
15912
0
    std::string_view value, process_type type) {
15913
  // Let strippedValue be the given value with a single leading U+003F (?)
15914
  // removed, if any.
15915
0
  if (value.starts_with("?")) {
15916
0
    value.remove_prefix(1);
15917
0
  }
15918
  // We cannot assert that the value is no longer starting with a single
15919
  // question mark because technically it can start. The question is whether or
15920
  // not we should remove the first question mark. Ref:
15921
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
15922
15923
  // If type is "pattern" then return strippedValue.
15924
0
  if (type == process_type::pattern) {
15925
0
    return std::string(value);
15926
0
  }
15927
  // Return the result of running canonicalize a search given strippedValue.
15928
0
  return url_pattern_helpers::canonicalize_search(value);
15929
0
}
15930
15931
tl::expected<std::string, errors> url_pattern_init::process_hash(
15932
0
    std::string_view value, process_type type) {
15933
  // Let strippedValue be the given value with a single leading U+0023 (#)
15934
  // removed, if any.
15935
0
  if (value.starts_with("#")) {
15936
0
    value.remove_prefix(1);
15937
0
  }
15938
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
15939
  // If type is "pattern" then return strippedValue.
15940
0
  if (type == process_type::pattern) {
15941
0
    return std::string(value);
15942
0
  }
15943
  // Return the result of running canonicalize a hash given strippedValue.
15944
0
  return url_pattern_helpers::canonicalize_hash(value);
15945
0
}
15946
15947
}  // namespace ada
15948
15949
#endif  // ADA_INCLUDE_URL_PATTERN
15950
/* end file src/url_pattern.cpp */
15951
/* begin file src/url_pattern_helpers.cpp */
15952
#if ADA_INCLUDE_URL_PATTERN
15953
15954
#include <algorithm>
15955
#include <optional>
15956
#include <string>
15957
15958
namespace ada::url_pattern_helpers {
15959
15960
std::tuple<std::string, std::vector<std::string>>
15961
generate_regular_expression_and_name_list(
15962
    const std::vector<url_pattern_part>& part_list,
15963
0
    url_pattern_compile_component_options options) {
15964
  // Let result be "^"
15965
0
  std::string result = "^";
15966
15967
  // Let name list be a new list
15968
0
  std::vector<std::string> name_list{};
15969
15970
  // For each part of part list:
15971
0
  for (const url_pattern_part& part : part_list) {
15972
    // If part's type is "fixed-text":
15973
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
15974
      // If part's modifier is "none"
15975
0
      if (part.modifier == url_pattern_part_modifier::none) {
15976
        // Append the result of running escape a regexp string given part's
15977
        // value
15978
0
        result += escape_regexp_string(part.value);
15979
0
      } else {
15980
        // A "fixed-text" part with a modifier uses a non capturing group
15981
        // (?:<fixed text>)<modifier>
15982
        // Append "(?:" to the end of result.
15983
0
        result.append("(?:");
15984
        // Append the result of running escape a regexp string given part's
15985
        // value to the end of result.
15986
0
        result.append(escape_regexp_string(part.value));
15987
        // Append ")" to the end of result.
15988
0
        result.append(")");
15989
        // Append the result of running convert a modifier to a string given
15990
        // part's modifier to the end of result.
15991
0
        result.append(convert_modifier_to_string(part.modifier));
15992
0
      }
15993
0
      continue;
15994
0
    }
15995
15996
    // Assert: part's name is not the empty string
15997
0
    ADA_ASSERT_TRUE(!part.name.empty());
15998
15999
    // Append part's name to name list
16000
0
    name_list.push_back(part.name);
16001
16002
    // Let regexp value be part's value
16003
0
    std::string regexp_value = part.value;
16004
16005
    // If part's type is "segment-wildcard"
16006
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16007
      // then set regexp value to the result of running generate a segment
16008
      // wildcard regexp given options.
16009
0
      regexp_value = generate_segment_wildcard_regexp(options);
16010
0
    }
16011
    // Otherwise if part's type is "full-wildcard"
16012
0
    else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16013
      // then set regexp value to full wildcard regexp value.
16014
0
      regexp_value = ".*";
16015
0
    }
16016
16017
    // If part's prefix is the empty string and part's suffix is the empty
16018
    // string
16019
0
    if (part.prefix.empty() && part.suffix.empty()) {
16020
      // If part's modifier is "none" or "optional"
16021
0
      if (part.modifier == url_pattern_part_modifier::none ||
16022
0
          part.modifier == url_pattern_part_modifier::optional) {
16023
        // (<regexp value>)<modifier>
16024
0
        result += "(" + regexp_value + ")" +
16025
0
                  convert_modifier_to_string(part.modifier);
16026
0
      } else {
16027
        // ((?:<regexp value>)<modifier>)
16028
0
        result += "((?:" + regexp_value + ")" +
16029
0
                  convert_modifier_to_string(part.modifier) + ")";
16030
0
      }
16031
0
      continue;
16032
0
    }
16033
16034
    // If part's modifier is "none" or "optional"
16035
0
    if (part.modifier == url_pattern_part_modifier::none ||
16036
0
        part.modifier == url_pattern_part_modifier::optional) {
16037
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16038
0
      result += "(?:" + escape_regexp_string(part.prefix) + "(" + regexp_value +
16039
0
                ")" + escape_regexp_string(part.suffix) + ")" +
16040
0
                convert_modifier_to_string(part.modifier);
16041
0
      continue;
16042
0
    }
16043
16044
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16045
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16046
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
16047
16048
    // Assert: part's prefix is not the empty string or part's suffix is not the
16049
    // empty string
16050
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16051
16052
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16053
    // value>))*)<suffix>)?
16054
    // Append "(?:" to the end of result.
16055
0
    result.append("(?:");
16056
    // Append the result of running escape a regexp string given part's prefix
16057
    // to the end of result.
16058
0
    result.append(escape_regexp_string(part.prefix));
16059
    // Append "((?:" to the end of result.
16060
0
    result.append("((?:");
16061
    // Append regexp value to the end of result.
16062
0
    result.append(regexp_value);
16063
    // Append ")(?:" to the end of result.
16064
0
    result.append(")(?:");
16065
    // Append the result of running escape a regexp string given part's suffix
16066
    // to the end of result.
16067
0
    result.append(escape_regexp_string(part.suffix));
16068
    // Append the result of running escape a regexp string given part's prefix
16069
    // to the end of result.
16070
0
    result.append(escape_regexp_string(part.prefix));
16071
    // Append "(?:" to the end of result.
16072
0
    result.append("(?:");
16073
    // Append regexp value to the end of result.
16074
0
    result.append(regexp_value);
16075
    // Append "))*)" to the end of result.
16076
0
    result.append("))*)");
16077
    // Append the result of running escape a regexp string given part's suffix
16078
    // to the end of result.
16079
0
    result.append(escape_regexp_string(part.suffix));
16080
    // Append ")" to the end of result.
16081
0
    result.append(")");
16082
16083
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16084
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16085
0
      result += "?";
16086
0
    }
16087
0
  }
16088
16089
  // Append "$" to the end of result
16090
0
  result += "$";
16091
16092
  // Return (result, name list)
16093
0
  return {std::move(result), std::move(name_list)};
16094
0
}
16095
16096
0
bool is_ipv6_address(std::string_view input) noexcept {
16097
  // If input's code point length is less than 2, then return false.
16098
0
  if (input.size() < 2) return false;
16099
16100
  // Let input code points be input interpreted as a list of code points.
16101
  // If input code points[0] is U+005B ([), then return true.
16102
0
  if (input.front() == '[') return true;
16103
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16104
  // ([), then return true.
16105
0
  if (input.starts_with("{[")) return true;
16106
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16107
  // ([), then return true.
16108
0
  return input.starts_with("\\[");
16109
0
}
16110
16111
0
std::string convert_modifier_to_string(url_pattern_part_modifier modifier) {
16112
  // TODO: Optimize this.
16113
0
  switch (modifier) {
16114
      // If modifier is "zero-or-more", then return "*".
16115
0
    case url_pattern_part_modifier::zero_or_more:
16116
0
      return "*";
16117
    // If modifier is "optional", then return "?".
16118
0
    case url_pattern_part_modifier::optional:
16119
0
      return "?";
16120
    // If modifier is "one-or-more", then return "+".
16121
0
    case url_pattern_part_modifier::one_or_more:
16122
0
      return "+";
16123
    // Return the empty string.
16124
0
    default:
16125
0
      return "";
16126
0
  }
16127
0
}
16128
16129
std::string generate_segment_wildcard_regexp(
16130
0
    url_pattern_compile_component_options options) {
16131
  // Let result be "[^".
16132
0
  std::string result = "[^";
16133
  // Append the result of running escape a regexp string given options's
16134
  // delimiter code point to the end of result.
16135
0
  result.append(escape_regexp_string(options.get_delimiter()));
16136
  // Append "]+?" to the end of result.
16137
0
  result.append("]+?");
16138
  // Return result.
16139
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16140
0
  return result;
16141
0
}
16142
16143
tl::expected<std::string, errors> canonicalize_protocol(
16144
0
    std::string_view input) {
16145
0
  ada_log("canonicalize_protocol called with input=", input);
16146
  // If value is the empty string, return value.
16147
0
  if (input.empty()) [[unlikely]] {
16148
0
    return "";
16149
0
  }
16150
16151
  // IMPORTANT: Deviation from the spec. We remove the trailing ':' here.
16152
0
  if (input.ends_with(":")) {
16153
0
    input.remove_suffix(1);
16154
0
  }
16155
16156
  // Let dummyURL be a new URL record.
16157
  // Let parseResult be the result of running the basic URL parser given value
16158
  // followed by "://dummy.test", with dummyURL as url.
16159
0
  if (auto dummy_url = ada::parse<url_aggregator>(
16160
0
          std::string(input) + "://dummy.test", nullptr)) {
16161
    // IMPORTANT: Deviation from the spec. We remove the trailing ':' here.
16162
    // Since URL parser always return protocols ending with `:`
16163
0
    auto protocol = dummy_url->get_protocol();
16164
0
    protocol.remove_suffix(1);
16165
0
    return std::string(protocol);
16166
0
  }
16167
  // If parseResult is failure, then throw a TypeError.
16168
0
  return tl::unexpected(errors::type_error);
16169
0
}
16170
16171
tl::expected<std::string, errors> canonicalize_username(
16172
0
    std::string_view input) {
16173
  // If value is the empty string, return value.
16174
0
  if (input.empty()) [[unlikely]] {
16175
0
    return "";
16176
0
  }
16177
  // Let dummyURL be a new URL record.
16178
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16179
0
  ADA_ASSERT_TRUE(url.has_value());
16180
  // Set the username given dummyURL and value.
16181
0
  if (!url->set_username(input)) {
16182
0
    return tl::unexpected(errors::type_error);
16183
0
  }
16184
  // Return dummyURL's username.
16185
0
  return std::string(url->get_username());
16186
0
}
16187
16188
tl::expected<std::string, errors> canonicalize_password(
16189
0
    std::string_view input) {
16190
  // If value is the empty string, return value.
16191
0
  if (input.empty()) [[unlikely]] {
16192
0
    return "";
16193
0
  }
16194
  // Let dummyURL be a new URL record.
16195
  // Set the password given dummyURL and value.
16196
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16197
16198
0
  ADA_ASSERT_TRUE(url.has_value());
16199
0
  if (!url->set_password(input)) {
16200
0
    return tl::unexpected(errors::type_error);
16201
0
  }
16202
  // Return dummyURL's password.
16203
0
  return std::string(url->get_password());
16204
0
}
16205
16206
tl::expected<std::string, errors> canonicalize_hostname(
16207
0
    std::string_view input) {
16208
0
  ada_log("canonicalize_hostname input=", input);
16209
  // If value is the empty string, return value.
16210
0
  if (input.empty()) [[unlikely]] {
16211
0
    return "";
16212
0
  }
16213
  // Let dummyURL be a new URL record.
16214
  // Let parseResult be the result of running the basic URL parser given value
16215
  // with dummyURL as url and hostname state as state override.
16216
16217
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16218
  // hostname will not be converted using IDNA.
16219
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16220
0
  ADA_ASSERT_TRUE(url);
16221
  // if (!isValidHostnameInput(hostname)) return kj::none;
16222
0
  if (!url->set_hostname(input)) {
16223
    // If parseResult is failure, then throw a TypeError.
16224
0
    return tl::unexpected(errors::type_error);
16225
0
  }
16226
  // Return dummyURL's host, serialized, or empty string if it is null.
16227
0
  return std::string(url->get_hostname());
16228
0
}
16229
16230
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16231
0
    std::string_view input) {
16232
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16233
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16234
0
  if (std::ranges::any_of(input, [](char c) {
16235
0
        return c != '[' && c != ']' && c != ':' &&
16236
0
               !unicode::is_ascii_hex_digit(c);
16237
0
      })) {
16238
0
    return tl::unexpected(errors::type_error);
16239
0
  }
16240
  // Append the result of running ASCII lowercase given code point to the end of
16241
  // result.
16242
0
  auto hostname = std::string(input);
16243
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16244
0
  return hostname;
16245
0
}
16246
16247
tl::expected<std::string, errors> canonicalize_port(
16248
0
    std::string_view port_value) {
16249
  // If portValue is the empty string, return portValue.
16250
0
  if (port_value.empty()) [[unlikely]] {
16251
0
    return "";
16252
0
  }
16253
  // Let dummyURL be a new URL record.
16254
  // If protocolValue was given, then set dummyURL's scheme to protocolValue.
16255
  // Let parseResult be the result of running basic URL parser given portValue
16256
  // with dummyURL as url and port state as state override.
16257
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16258
0
  ADA_ASSERT_TRUE(url);
16259
0
  if (url->set_port(port_value)) {
16260
    // Return dummyURL's port, serialized, or empty string if it is null.
16261
0
    return std::string(url->get_port());
16262
0
  }
16263
  // If parseResult is failure, then throw a TypeError.
16264
0
  return tl::unexpected(errors::type_error);
16265
0
}
16266
16267
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16268
0
    std::string_view port_value, std::string_view protocol) {
16269
  // If portValue is the empty string, return portValue.
16270
0
  if (port_value.empty()) [[unlikely]] {
16271
0
    return "";
16272
0
  }
16273
16274
  // TODO: Remove this
16275
  // We have an empty protocol because get_protocol() returns an empty string
16276
  // We should handle this in the caller rather than here.
16277
0
  if (protocol.empty()) {
16278
0
    protocol = "fake";
16279
0
  } else if (protocol.ends_with(":")) {
16280
0
    protocol.remove_suffix(1);
16281
0
  }
16282
  // Let dummyURL be a new URL record.
16283
  // If protocolValue was given, then set dummyURL's scheme to protocolValue.
16284
  // Let parseResult be the result of running basic URL parser given portValue
16285
  // with dummyURL as url and port state as state override.
16286
0
  auto url = ada::parse<url_aggregator>(std::string(protocol) + "://dummy.test",
16287
0
                                        nullptr);
16288
  // TODO: Remove has_port() check.
16289
  // This is actually a bug with url parser where set_port() returns true for
16290
  // "invalid80" port value.
16291
0
  if (url && url->set_port(port_value) && url->has_port()) {
16292
    // Return dummyURL's port, serialized, or empty string if it is null.
16293
0
    return std::string(url->get_port());
16294
0
  }
16295
  // TODO: Remove this once the previous has_port() check is removed.
16296
0
  if (url) {
16297
0
    if (scheme::is_special(protocol) && url->get_port().empty()) {
16298
0
      return "";
16299
0
    }
16300
0
  }
16301
  // If parseResult is failure, then throw a TypeError.
16302
0
  return tl::unexpected(errors::type_error);
16303
0
}
16304
16305
tl::expected<std::string, errors> canonicalize_pathname(
16306
0
    std::string_view input) {
16307
  // If value is the empty string, then return value.
16308
0
  if (input.empty()) [[unlikely]] {
16309
0
    return "";
16310
0
  }
16311
  // Let leading slash be true if the first code point in value is U+002F (/)
16312
  // and otherwise false.
16313
0
  const bool leading_slash = input.starts_with("/");
16314
  // Let modified value be "/-" if leading slash is false and otherwise the
16315
  // empty string.
16316
0
  const auto modified_value = leading_slash ? "" : "/-";
16317
0
  const auto full_url =
16318
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16319
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16320
0
    const auto pathname = url->get_pathname();
16321
    // If leading slash is false, then set result to the code point substring
16322
    // from 2 to the end of the string within result.
16323
0
    return leading_slash ? std::string(pathname)
16324
0
                         : std::string(pathname.substr(2));
16325
0
  }
16326
  // If parseResult is failure, then throw a TypeError.
16327
0
  return tl::unexpected(errors::type_error);
16328
0
}
16329
16330
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16331
0
    std::string_view input) {
16332
  // If value is the empty string, return value.
16333
0
  if (input.empty()) [[unlikely]] {
16334
0
    return "";
16335
0
  }
16336
  // Let dummyURL be a new URL record.
16337
  // Set dummyURL's path to the empty string.
16338
  // Let parseResult be the result of running URL parsing given value with
16339
  // dummyURL as url and opaque path state as state override.
16340
0
  if (auto url =
16341
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16342
    // Return the result of URL path serializing dummyURL.
16343
0
    return std::string(url->get_pathname());
16344
0
  }
16345
  // If parseResult is failure, then throw a TypeError.
16346
0
  return tl::unexpected(errors::type_error);
16347
0
}
16348
16349
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16350
  // If value is the empty string, return value.
16351
0
  if (input.empty()) [[unlikely]] {
16352
0
    return "";
16353
0
  }
16354
  // Let dummyURL be a new URL record.
16355
  // Set dummyURL's query to the empty string.
16356
  // Let parseResult be the result of running basic URL parser given value with
16357
  // dummyURL as url and query state as state override.
16358
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16359
0
  ADA_ASSERT_TRUE(url.has_value());
16360
0
  url->set_search(input);
16361
0
  if (url->has_search()) {
16362
0
    const auto search = url->get_search();
16363
0
    if (!search.empty()) {
16364
0
      return std::string(search.substr(1));
16365
0
    }
16366
0
    return "";
16367
0
  }
16368
0
  return tl::unexpected(errors::type_error);
16369
0
}
16370
16371
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16372
  // If value is the empty string, return value.
16373
0
  if (input.empty()) [[unlikely]] {
16374
0
    return "";
16375
0
  }
16376
  // Let dummyURL be a new URL record.
16377
  // Set dummyURL's fragment to the empty string.
16378
  // Let parseResult be the result of running basic URL parser given value with
16379
  // dummyURL as url and fragment state as state override.
16380
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16381
0
  ADA_ASSERT_TRUE(url.has_value());
16382
0
  url->set_hash(input);
16383
  // Return dummyURL's fragment.
16384
0
  if (url->has_hash()) {
16385
0
    const auto hash = url->get_hash();
16386
0
    if (!hash.empty()) {
16387
0
      return std::string(hash.substr(1));
16388
0
    }
16389
0
    return "";
16390
0
  }
16391
0
  return tl::unexpected(errors::type_error);
16392
0
}
16393
16394
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16395
0
                                                  token_policy policy) {
16396
0
  ada_log("tokenize input: ", input);
16397
  // Let tokenizer be a new tokenizer.
16398
  // Set tokenizer's input to input.
16399
  // Set tokenizer's policy to policy.
16400
0
  auto tokenizer = Tokenizer(input, policy);
16401
  // While tokenizer's index is less than tokenizer's input's code point length:
16402
0
  while (tokenizer.index < tokenizer.input.size()) {
16403
    // Run seek and get the next code point given tokenizer and tokenizer's
16404
    // index.
16405
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16406
16407
    // If tokenizer's code point is U+002A (*):
16408
0
    if (tokenizer.code_point == '*') {
16409
      // Run add a token with default position and length given tokenizer and
16410
      // "asterisk".
16411
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16412
0
      ada_log("add ASTERISK token");
16413
      // Continue.
16414
0
      continue;
16415
0
    }
16416
16417
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16418
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16419
      // Run add a token with default position and length given tokenizer and
16420
      // "other-modifier".
16421
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16422
      // Continue.
16423
0
      continue;
16424
0
    }
16425
16426
    // If tokenizer's code point is U+005C (\):
16427
0
    if (tokenizer.code_point == '\\') {
16428
      // If tokenizer's index is equal to tokenizer's input's code point length
16429
      // - 1:
16430
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16431
        // Run process a tokenizing error given tokenizer, tokenizer's next
16432
        // index, and tokenizer's index.
16433
0
        if (auto error = tokenizer.process_tokenizing_error(
16434
0
                tokenizer.next_index, tokenizer.index)) {
16435
0
          ada_log("process_tokenizing_error failed");
16436
0
          return tl::unexpected(*error);
16437
0
        }
16438
0
        continue;
16439
0
      }
16440
16441
      // Let escaped index be tokenizer's next index.
16442
0
      auto escaped_index = tokenizer.next_index;
16443
      // Run get the next code point given tokenizer.
16444
0
      tokenizer.get_next_code_point();
16445
      // Run add a token with default length given tokenizer, "escaped-char",
16446
      // tokenizer's next index, and escaped index.
16447
0
      tokenizer.add_token_with_default_length(
16448
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16449
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16450
0
              " with escaped index ", escaped_index);
16451
      // Continue.
16452
0
      continue;
16453
0
    }
16454
16455
    // If tokenizer's code point is U+007B ({):
16456
0
    if (tokenizer.code_point == '{') {
16457
      // Run add a token with default position and length given tokenizer and
16458
      // "open".
16459
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16460
0
      ada_log("add OPEN token");
16461
0
      continue;
16462
0
    }
16463
16464
    // If tokenizer's code point is U+007D (}):
16465
0
    if (tokenizer.code_point == '}') {
16466
      // Run add a token with default position and length given tokenizer and
16467
      // "close".
16468
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16469
0
      ada_log("add CLOSE token");
16470
0
      continue;
16471
0
    }
16472
16473
    // If tokenizer's code point is U+003A (:):
16474
0
    if (tokenizer.code_point == ':') {
16475
      // Let name position be tokenizer's next index.
16476
0
      auto name_position = tokenizer.next_index;
16477
      // Let name start be name position.
16478
0
      auto name_start = name_position;
16479
      // While name position is less than tokenizer's input's code point length:
16480
0
      while (name_position < tokenizer.input.size()) {
16481
        // Run seek and get the next code point given tokenizer and name
16482
        // position.
16483
0
        tokenizer.seek_and_get_next_code_point(name_position);
16484
        // Let first code point be true if name position equals name start and
16485
        // false otherwise.
16486
0
        bool first_code_point = name_position == name_start;
16487
        // Let valid code point be the result of running is a valid name code
16488
        // point given tokenizer's code point and first code point.
16489
0
        auto valid_code_point =
16490
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16491
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16492
0
                " first_code_point=", first_code_point,
16493
0
                " valid_code_point=", valid_code_point);
16494
        // If valid code point is false break.
16495
0
        if (!valid_code_point) break;
16496
        // Set name position to tokenizer's next index.
16497
0
        name_position = tokenizer.next_index;
16498
0
      }
16499
16500
      // If name position is less than or equal to name start:
16501
0
      if (name_position <= name_start) {
16502
        // Run process a tokenizing error given tokenizer, name start, and
16503
        // tokenizer's index.
16504
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16505
0
                                                            tokenizer.index)) {
16506
0
          ada_log("process_tokenizing_error failed");
16507
0
          return tl::unexpected(*error);
16508
0
        }
16509
        // Continue
16510
0
        continue;
16511
0
      }
16512
16513
      // Run add a token with default length given tokenizer, "name", name
16514
      // position, and name start.
16515
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16516
0
                                              name_start);
16517
0
      continue;
16518
0
    }
16519
16520
    // If tokenizer's code point is U+0028 (():
16521
0
    if (tokenizer.code_point == '(') {
16522
      // Let depth be 1.
16523
0
      size_t depth = 1;
16524
      // Let regexp position be tokenizer's next index.
16525
0
      auto regexp_position = tokenizer.next_index;
16526
      // Let regexp start be regexp position.
16527
0
      auto regexp_start = regexp_position;
16528
      // Let error be false.
16529
0
      bool error = false;
16530
16531
      // While regexp position is less than tokenizer's input's code point
16532
      // length:
16533
0
      while (regexp_position < tokenizer.input.size()) {
16534
        // Run seek and get the next code point given tokenizer and regexp
16535
        // position.
16536
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16537
16538
        // TODO: Optimization opportunity: The next 2 if statements can be
16539
        // merged. If the result of running is ASCII given tokenizer's code
16540
        // point is false:
16541
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16542
          // Run process a tokenizing error given tokenizer, regexp start, and
16543
          // tokenizer's index.
16544
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16545
0
                  regexp_start, tokenizer.index)) {
16546
0
            return tl::unexpected(*process_error);
16547
0
          }
16548
          // Set error to true.
16549
0
          error = true;
16550
0
          break;
16551
0
        }
16552
16553
        // If regexp position equals regexp start and tokenizer's code point is
16554
        // U+003F (?):
16555
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16556
          // Run process a tokenizing error given tokenizer, regexp start, and
16557
          // tokenizer's index.
16558
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16559
0
                  regexp_start, tokenizer.index)) {
16560
0
            return tl::unexpected(*process_error);
16561
0
          }
16562
          // Set error to true;
16563
0
          error = true;
16564
0
          break;
16565
0
        }
16566
16567
        // If tokenizer's code point is U+005C (\):
16568
0
        if (tokenizer.code_point == '\\') {
16569
          // If regexp position equals tokenizer's input's code point length - 1
16570
0
          if (regexp_position == tokenizer.input.size() - 1) {
16571
            // Run process a tokenizing error given tokenizer, regexp start, and
16572
            // tokenizer's index.
16573
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16574
0
                    regexp_start, tokenizer.index)) {
16575
0
              return tl::unexpected(*process_error);
16576
0
            }
16577
            // Set error to true.
16578
0
            error = true;
16579
0
            break;
16580
0
          }
16581
          // Run get the next code point given tokenizer.
16582
0
          tokenizer.get_next_code_point();
16583
          // If the result of running is ASCII given tokenizer's code point is
16584
          // false:
16585
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16586
            // Run process a tokenizing error given tokenizer, regexp start, and
16587
            // tokenizer's index.
16588
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16589
0
                    regexp_start, tokenizer.index);
16590
0
                process_error.has_value()) {
16591
0
              return tl::unexpected(*process_error);
16592
0
            }
16593
            // Set error to true.
16594
0
            error = true;
16595
0
            break;
16596
0
          }
16597
          // Set regexp position to tokenizer's next index.
16598
0
          regexp_position = tokenizer.next_index;
16599
0
          continue;
16600
0
        }
16601
16602
        // If tokenizer's code point is U+0029 ()):
16603
0
        if (tokenizer.code_point == ')') {
16604
          // Decrement depth by 1.
16605
0
          depth--;
16606
          // If depth is 0:
16607
0
          if (depth == 0) {
16608
            // Set regexp position to tokenizer's next index.
16609
0
            regexp_position = tokenizer.next_index;
16610
            // Break.
16611
0
            break;
16612
0
          }
16613
0
        } else if (tokenizer.code_point == '(') {
16614
          // Otherwise if tokenizer's code point is U+0028 (():
16615
          // Increment depth by 1.
16616
0
          depth++;
16617
          // If regexp position equals tokenizer's input's code point length -
16618
          // 1:
16619
0
          if (regexp_position == tokenizer.input.size() - 1) {
16620
            // Run process a tokenizing error given tokenizer, regexp start, and
16621
            // tokenizer's index.
16622
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16623
0
                    regexp_start, tokenizer.index)) {
16624
0
              return tl::unexpected(*process_error);
16625
0
            }
16626
            // Set error to true.
16627
0
            error = true;
16628
0
            break;
16629
0
          }
16630
          // Let temporary position be tokenizer's next index.
16631
0
          auto temporary_position = tokenizer.next_index;
16632
          // Run get the next code point given tokenizer.
16633
0
          tokenizer.get_next_code_point();
16634
          // If tokenizer's code point is not U+003F (?):
16635
0
          if (tokenizer.code_point != '?') {
16636
            // Run process a tokenizing error given tokenizer, regexp start, and
16637
            // tokenizer's index.
16638
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16639
0
                    regexp_start, tokenizer.index)) {
16640
0
              return tl::unexpected(*process_error);
16641
0
            }
16642
            // Set error to true.
16643
0
            error = true;
16644
0
            break;
16645
0
          }
16646
          // Set tokenizer's next index to temporary position.
16647
0
          tokenizer.next_index = temporary_position;
16648
0
        }
16649
        // Set regexp position to tokenizer's next index.
16650
0
        regexp_position = tokenizer.next_index;
16651
0
      }
16652
16653
      // If error is true continue.
16654
0
      if (error) continue;
16655
      // If depth is not zero:
16656
0
      if (depth != 0) {
16657
        // Run process a tokenizing error given tokenizer, regexp start, and
16658
        // tokenizer's index.
16659
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16660
0
                regexp_start, tokenizer.index)) {
16661
0
          return tl::unexpected(*process_error);
16662
0
        }
16663
0
        continue;
16664
0
      }
16665
      // Let regexp length be regexp position - regexp start - 1.
16666
0
      auto regexp_length = regexp_position - regexp_start - 1;
16667
      // If regexp length is zero:
16668
0
      if (regexp_length == 0) {
16669
        // Run process a tokenizing error given tokenizer, regexp start, and
16670
        // tokenizer's index.
16671
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16672
0
                regexp_start, tokenizer.index)) {
16673
0
          ada_log("process_tokenizing_error failed");
16674
0
          return tl::unexpected(*process_error);
16675
0
        }
16676
0
        continue;
16677
0
      }
16678
      // Run add a token given tokenizer, "regexp", regexp position, regexp
16679
      // start, and regexp length.
16680
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
16681
0
                          regexp_length);
16682
0
      continue;
16683
0
    }
16684
    // Run add a token with default position and length given tokenizer and
16685
    // "char".
16686
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
16687
0
  }
16688
  // Run add a token with default length given tokenizer, "end", tokenizer's
16689
  // index, and tokenizer's index.
16690
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
16691
0
                                          tokenizer.index);
16692
16693
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
16694
  // Return tokenizer's token list.
16695
0
  return tokenizer.token_list;
16696
0
}
16697
16698
0
std::string escape_pattern_string(std::string_view input) {
16699
0
  ada_log("escape_pattern_string called with input=", input);
16700
0
  if (input.empty()) [[unlikely]] {
16701
0
    return "";
16702
0
  }
16703
  // Assert: input is an ASCII string.
16704
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
16705
  // Let result be the empty string.
16706
0
  std::string result{};
16707
0
  result.reserve(input.size());
16708
16709
  // TODO: Optimization opportunity: Use a lookup table
16710
0
  constexpr auto should_escape = [](const char c) {
16711
0
    return c == '+' || c == '*' || c == '?' || c == ':' || c == '{' ||
16712
0
           c == '}' || c == '(' || c == ')' || c == '\\';
16713
0
  };
16714
16715
  // While index is less than input's length:
16716
0
  for (const auto& c : input) {
16717
0
    if (should_escape(c)) {
16718
      // then append U+005C (\) to the end of result.
16719
0
      result.append("\\");
16720
0
    }
16721
16722
    // Append c to the end of result.
16723
0
    result += c;
16724
0
  }
16725
  // Return result.
16726
0
  return result;
16727
0
}
16728
16729
namespace {
16730
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
16731
  std::array<uint8_t, 256> out{};
16732
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
16733
                  '|', '/', '\\'}) {
16734
    out[c] = 1;
16735
  }
16736
  return out;
16737
}();
16738
16739
0
constexpr bool should_escape_regexp_char(char c) {
16740
0
  return escape_regexp_table[(uint8_t)c];
16741
0
}
16742
}  // namespace
16743
16744
0
std::string escape_regexp_string(std::string_view input) {
16745
  // Assert: input is an ASCII string.
16746
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
16747
  // Let result be the empty string.
16748
0
  std::string result{};
16749
0
  result.reserve(input.size());
16750
0
  for (const auto& c : input) {
16751
    // TODO: Optimize this even further
16752
0
    if (should_escape_regexp_char(c)) {
16753
0
      result.append(std::string("\\") + c);
16754
0
    } else {
16755
0
      result.push_back(c);
16756
0
    }
16757
0
  }
16758
0
  return result;
16759
0
}
16760
16761
std::string process_base_url_string(std::string_view input,
16762
0
                                    url_pattern_init::process_type type) {
16763
  // If type is not "pattern" return input.
16764
0
  if (type != url_pattern_init::process_type::pattern) {
16765
0
    return std::string(input);
16766
0
  }
16767
  // Return the result of escaping a pattern string given input.
16768
0
  return escape_pattern_string(input);
16769
0
}
16770
16771
constexpr bool is_absolute_pathname(
16772
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
16773
  // If input is the empty string, then return false.
16774
0
  if (input.empty()) [[unlikely]] {
16775
0
    return false;
16776
0
  }
16777
  // If input[0] is U+002F (/), then return true.
16778
0
  if (input.starts_with("/")) return true;
16779
  // If type is "url", then return false.
16780
0
  if (type == url_pattern_init::process_type::url) return false;
16781
  // If input's code point length is less than 2, then return false.
16782
0
  if (input.size() < 2) return false;
16783
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
16784
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
16785
  // Return false.
16786
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
16787
0
}
16788
16789
std::string generate_pattern_string(
16790
    std::vector<url_pattern_part>& part_list,
16791
0
    url_pattern_compile_component_options& options) {
16792
  // Let result be the empty string.
16793
0
  std::string result{};
16794
  // Let index list be the result of getting the indices for part list.
16795
  // For each index of index list:
16796
0
  for (size_t index = 0; index < part_list.size(); index++) {
16797
    // Let part be part list[index].
16798
0
    auto part = part_list[index];
16799
    // Let previous part be part list[index - 1] if index is greater than 0,
16800
    // otherwise let it be null.
16801
    // TODO: Optimization opportunity. Find a way to avoid making a copy here.
16802
0
    std::optional<url_pattern_part> previous_part =
16803
0
        index == 0 ? std::nullopt : std::optional(part_list[index - 1]);
16804
    // Let next part be part list[index + 1] if index is less than index list's
16805
    // size - 1, otherwise let it be null.
16806
0
    std::optional<url_pattern_part> next_part =
16807
0
        index < part_list.size() - 1 ? std::optional(part_list[index + 1])
16808
0
                                     : std::nullopt;
16809
    // If part's type is "fixed-text" then:
16810
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16811
      // If part's modifier is "none" then:
16812
0
      if (part.modifier == url_pattern_part_modifier::none) {
16813
        // Append the result of running escape a pattern string given part's
16814
        // value to the end of result.
16815
0
        result.append(escape_pattern_string(part.value));
16816
0
        continue;
16817
0
      }
16818
      // Append "{" to the end of result.
16819
0
      result += "{";
16820
      // Append the result of running escape a pattern string given part's value
16821
      // to the end of result.
16822
0
      result.append(escape_pattern_string(part.value));
16823
      // Append "}" to the end of result.
16824
0
      result += "}";
16825
      // Append the result of running convert a modifier to a string given
16826
      // part's modifier to the end of result.
16827
0
      result.append(convert_modifier_to_string(part.modifier));
16828
0
      continue;
16829
0
    }
16830
    // Let custom name be true if part's name[0] is not an ASCII digit;
16831
    // otherwise false.
16832
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
16833
    // Let needs grouping be true if at least one of the following are true,
16834
    // otherwise let it be false:
16835
    // - part's suffix is not the empty string.
16836
    // - part's prefix is not the empty string and is not options's prefix code
16837
    // point.
16838
0
    bool needs_grouping =
16839
0
        !part.suffix.empty() ||
16840
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
16841
16842
    // If all of the following are true:
16843
    // - needs grouping is false; and
16844
    // - custom name is true; and
16845
    // - part's type is "segment-wildcard"; and
16846
    // - part's modifier is "none"; and
16847
    // - next part is not null; and
16848
    // - next part's prefix is the empty string; and
16849
    // - next part's suffix is the empty string
16850
0
    if (!needs_grouping && custom_name &&
16851
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
16852
0
        part.modifier == url_pattern_part_modifier::none &&
16853
0
        next_part.has_value() && next_part->prefix.empty() &&
16854
0
        next_part->suffix.empty()) {
16855
      // If next part's type is "fixed-text":
16856
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
16857
        // Set needs grouping to true if the result of running is a valid name
16858
        // code point given next part's value's first code point and the boolean
16859
        // false is true.
16860
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
16861
0
          needs_grouping = true;
16862
0
        }
16863
0
      } else {
16864
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
16865
0
        needs_grouping = !next_part->name.empty() &&
16866
0
                         unicode::is_ascii_digit(next_part->name[0]);
16867
0
      }
16868
0
    }
16869
16870
    // If all of the following are true:
16871
    // - needs grouping is false; and
16872
    // - part's prefix is the empty string; and
16873
    // - previous part is not null; and
16874
    // - previous part's type is "fixed-text"; and
16875
    // - previous part's value's last code point is options's prefix code point.
16876
    // then set needs grouping to true.
16877
0
    if (!needs_grouping && part.prefix.empty() && previous_part.has_value() &&
16878
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
16879
0
        !options.get_prefix().empty() &&
16880
0
        previous_part->value.at(previous_part->value.size() - 1) ==
16881
0
            options.get_prefix()[0]) {
16882
0
      needs_grouping = true;
16883
0
    }
16884
16885
    // Assert: part's name is not the empty string or null.
16886
0
    ADA_ASSERT_TRUE(!part.name.empty());
16887
16888
    // If needs grouping is true, then append "{" to the end of result.
16889
0
    if (needs_grouping) {
16890
0
      result.append("{");
16891
0
    }
16892
16893
    // Append the result of running escape a pattern string given part's prefix
16894
    // to the end of result.
16895
0
    result.append(escape_pattern_string(part.prefix));
16896
16897
    // If custom name is true:
16898
0
    if (custom_name) {
16899
      // Append ":" to the end of result.
16900
0
      result.append(":");
16901
      // Append part's name to the end of result.
16902
0
      result.append(part.name);
16903
0
    }
16904
16905
    // If part's type is "regexp" then:
16906
0
    if (part.type == url_pattern_part_type::REGEXP) {
16907
      // Append "(" to the end of result.
16908
0
      result.append("(");
16909
      // Append part's value to the end of result.
16910
0
      result.append(part.value);
16911
      // Append ")" to the end of result.
16912
0
      result.append(")");
16913
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
16914
0
               !custom_name) {
16915
      // Otherwise if part's type is "segment-wildcard" and custom name is
16916
      // false: Append "(" to the end of result.
16917
0
      result.append("(");
16918
      // Append the result of running generate a segment wildcard regexp given
16919
      // options to the end of result.
16920
0
      result.append(generate_segment_wildcard_regexp(options));
16921
      // Append ")" to the end of result.
16922
0
      result.append(")");
16923
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16924
      // Otherwise if part's type is "full-wildcard":
16925
      // If custom name is false and one of the following is true:
16926
      // - previous part is null; or
16927
      // - previous part's type is "fixed-text"; or
16928
      // - previous part's modifier is not "none"; or
16929
      // - needs grouping is true; or
16930
      // - part's prefix is not the empty string
16931
      // - then append "*" to the end of result.
16932
0
      if (!custom_name &&
16933
0
          (!previous_part.has_value() ||
16934
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
16935
0
           previous_part->modifier != url_pattern_part_modifier::none ||
16936
0
           needs_grouping || !part.prefix.empty())) {
16937
0
        result.append("*");
16938
0
      } else {
16939
        // Append "(" to the end of result.
16940
        // Append full wildcard regexp value to the end of result.
16941
        // Append ")" to the end of result.
16942
0
        result.append("(.*)");
16943
0
      }
16944
0
    }
16945
16946
    // If all of the following are true:
16947
    // - part's type is "segment-wildcard"; and
16948
    // - custom name is true; and
16949
    // - part's suffix is not the empty string; and
16950
    // - The result of running is a valid name code point given part's suffix's
16951
    // first code point and the boolean false is true then append U+005C (\) to
16952
    // the end of result.
16953
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
16954
0
        !part.suffix.empty() &&
16955
0
        idna::valid_name_code_point(part.suffix[0], false)) {
16956
0
      result.append("\\");
16957
0
    }
16958
16959
    // Append the result of running escape a pattern string given part's suffix
16960
    // to the end of result.
16961
0
    result.append(escape_pattern_string(part.suffix));
16962
    // If needs grouping is true, then append "}" to the end of result.
16963
0
    if (needs_grouping) result.append("}");
16964
    // Append the result of running convert a modifier to a string given part's
16965
    // modifier to the end of result.
16966
0
    result.append(convert_modifier_to_string(part.modifier));
16967
0
  }
16968
  // Return result.
16969
0
  return result;
16970
0
}
16971
}  // namespace ada::url_pattern_helpers
16972
16973
#endif  // ADA_INCLUDE_URL_PATTERN
16974
/* end file src/url_pattern_helpers.cpp */
16975
/* begin file src/url_pattern_regex.cpp */
16976
#if ADA_INCLUDE_URL_PATTERN
16977
16978
16979
namespace ada::url_pattern_regex {
16980
16981
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
16982
std::optional<std::regex> std_regex_provider::create_instance(
16983
    std::string_view pattern, bool ignore_case) {
16984
  // Let flags be an empty string.
16985
  // If options's ignore case is true then set flags to "vi".
16986
  // Otherwise set flags to "v"
16987
  auto flags = ignore_case
16988
                   ? std::regex::icase | std::regex_constants::ECMAScript
16989
                   : std::regex_constants::ECMAScript;
16990
  try {
16991
    return std::regex(pattern.data(), pattern.size(), flags);
16992
  } catch (const std::regex_error& e) {
16993
    (void)e;
16994
    ada_log("std_regex_provider::create_instance failed:", e.what());
16995
    return std::nullopt;
16996
  }
16997
}
16998
16999
std::optional<std::vector<std::optional<std::string>>>
17000
std_regex_provider::regex_search(std::string_view input,
17001
                                 const std::regex& pattern) {
17002
  std::string input_str(
17003
      input.begin(),
17004
      input.end());  // Convert string_view to string for regex_search
17005
  std::smatch match_result;
17006
  if (!std::regex_search(input_str, match_result, pattern,
17007
                         std::regex_constants::match_any)) {
17008
    return std::nullopt;
17009
  }
17010
  std::vector<std::optional<std::string>> matches;
17011
  // If input is empty, let's assume the result will be empty as well.
17012
  if (input.empty() || match_result.empty()) {
17013
    return matches;
17014
  }
17015
  matches.reserve(match_result.size());
17016
  for (size_t i = 1; i < match_result.size(); ++i) {
17017
    if (auto entry = match_result[i]; entry.matched) {
17018
      matches.emplace_back(entry.str());
17019
    }
17020
  }
17021
  return matches;
17022
}
17023
17024
bool std_regex_provider::regex_match(std::string_view input,
17025
                                     const std::regex& pattern) {
17026
  return std::regex_match(input.begin(), input.end(), pattern);
17027
}
17028
17029
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17030
17031
}  // namespace ada::url_pattern_regex
17032
17033
#endif  // ADA_INCLUDE_URL_PATTERN
17034
/* end file src/url_pattern_regex.cpp */
17035
#endif  // ADA_INCLUDE_URL_PATTERN
17036
17037
/* begin file src/ada_c.cpp */
17038
17039
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
17040
0
  return *(ada::result<ada::url_aggregator>*)result;
17041
0
}
17042
17043
extern "C" {
17044
typedef void* ada_url;
17045
typedef void* ada_url_search_params;
17046
typedef void* ada_strings;
17047
typedef void* ada_url_search_params_keys_iter;
17048
typedef void* ada_url_search_params_values_iter;
17049
typedef void* ada_url_search_params_entries_iter;
17050
17051
struct ada_string {
17052
  const char* data;
17053
  size_t length;
17054
};
17055
17056
struct ada_owned_string {
17057
  const char* data;
17058
  size_t length;
17059
};
17060
17061
struct ada_string_pair {
17062
  ada_string key;
17063
  ada_string value;
17064
};
17065
17066
0
ada_string ada_string_create(const char* data, size_t length) {
17067
0
  ada_string out{};
17068
0
  out.data = data;
17069
0
  out.length = length;
17070
0
  return out;
17071
0
}
17072
17073
struct ada_url_components {
17074
  /*
17075
   * By using 32-bit integers, we implicitly assume that the URL string
17076
   * cannot exceed 4 GB.
17077
   *
17078
   * https://user:pass@example.com:1234/foo/bar?baz#quux
17079
   *       |     |    |          | ^^^^|       |   |
17080
   *       |     |    |          | |   |       |   `----- hash_start
17081
   *       |     |    |          | |   |       `--------- search_start
17082
   *       |     |    |          | |   `----------------- pathname_start
17083
   *       |     |    |          | `--------------------- port
17084
   *       |     |    |          `----------------------- host_end
17085
   *       |     |    `---------------------------------- host_start
17086
   *       |     `--------------------------------------- username_end
17087
   *       `--------------------------------------------- protocol_end
17088
   */
17089
  uint32_t protocol_end;
17090
  /**
17091
   * Username end is not `omitted` by default (-1) to make username and password
17092
   * getters less costly to implement.
17093
   */
17094
  uint32_t username_end;
17095
  uint32_t host_start;
17096
  uint32_t host_end;
17097
  uint32_t port;
17098
  uint32_t pathname_start;
17099
  uint32_t search_start;
17100
  uint32_t hash_start;
17101
};
17102
17103
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17104
0
  return new ada::result<ada::url_aggregator>(
17105
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17106
0
}
17107
17108
ada_url ada_parse_with_base(const char* input, size_t input_length,
17109
0
                            const char* base, size_t base_length) noexcept {
17110
0
  auto base_out =
17111
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17112
17113
0
  if (!base_out) {
17114
0
    return new ada::result<ada::url_aggregator>(base_out);
17115
0
  }
17116
17117
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17118
0
      std::string_view(input, input_length), &base_out.value()));
17119
0
}
17120
17121
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17122
0
  return ada::can_parse(std::string_view(input, length));
17123
0
}
17124
17125
bool ada_can_parse_with_base(const char* input, size_t input_length,
17126
0
                             const char* base, size_t base_length) noexcept {
17127
0
  std::string_view base_view(base, base_length);
17128
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17129
0
}
17130
17131
0
void ada_free(ada_url result) noexcept {
17132
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17133
0
  delete r;
17134
0
}
17135
17136
0
ada_url ada_copy(ada_url input) noexcept {
17137
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17138
0
  return new ada::result<ada::url_aggregator>(r);
17139
0
}
17140
17141
0
bool ada_is_valid(ada_url result) noexcept {
17142
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17143
0
  return r.has_value();
17144
0
}
17145
17146
// caller must free the result with ada_free_owned_string
17147
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17148
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17149
0
  ada_owned_string owned{};
17150
0
  if (!r) {
17151
0
    owned.data = nullptr;
17152
0
    owned.length = 0;
17153
0
    return owned;
17154
0
  }
17155
0
  std::string out = r->get_origin();
17156
0
  owned.length = out.size();
17157
0
  owned.data = new char[owned.length];
17158
0
  memcpy((void*)owned.data, out.data(), owned.length);
17159
0
  return owned;
17160
0
}
17161
17162
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17163
0
  delete[] owned.data;
17164
0
}
17165
17166
0
ada_string ada_get_href(ada_url result) noexcept {
17167
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17168
0
  if (!r) {
17169
0
    return ada_string_create(nullptr, 0);
17170
0
  }
17171
0
  std::string_view out = r->get_href();
17172
0
  return ada_string_create(out.data(), out.length());
17173
0
}
17174
17175
0
ada_string ada_get_username(ada_url result) noexcept {
17176
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17177
0
  if (!r) {
17178
0
    return ada_string_create(nullptr, 0);
17179
0
  }
17180
0
  std::string_view out = r->get_username();
17181
0
  return ada_string_create(out.data(), out.length());
17182
0
}
17183
17184
0
ada_string ada_get_password(ada_url result) noexcept {
17185
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17186
0
  if (!r) {
17187
0
    return ada_string_create(nullptr, 0);
17188
0
  }
17189
0
  std::string_view out = r->get_password();
17190
0
  return ada_string_create(out.data(), out.length());
17191
0
}
17192
17193
0
ada_string ada_get_port(ada_url result) noexcept {
17194
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17195
0
  if (!r) {
17196
0
    return ada_string_create(nullptr, 0);
17197
0
  }
17198
0
  std::string_view out = r->get_port();
17199
0
  return ada_string_create(out.data(), out.length());
17200
0
}
17201
17202
0
ada_string ada_get_hash(ada_url result) noexcept {
17203
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17204
0
  if (!r) {
17205
0
    return ada_string_create(nullptr, 0);
17206
0
  }
17207
0
  std::string_view out = r->get_hash();
17208
0
  return ada_string_create(out.data(), out.length());
17209
0
}
17210
17211
0
ada_string ada_get_host(ada_url result) noexcept {
17212
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17213
0
  if (!r) {
17214
0
    return ada_string_create(nullptr, 0);
17215
0
  }
17216
0
  std::string_view out = r->get_host();
17217
0
  return ada_string_create(out.data(), out.length());
17218
0
}
17219
17220
0
ada_string ada_get_hostname(ada_url result) noexcept {
17221
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17222
0
  if (!r) {
17223
0
    return ada_string_create(nullptr, 0);
17224
0
  }
17225
0
  std::string_view out = r->get_hostname();
17226
0
  return ada_string_create(out.data(), out.length());
17227
0
}
17228
17229
0
ada_string ada_get_pathname(ada_url result) noexcept {
17230
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17231
0
  if (!r) {
17232
0
    return ada_string_create(nullptr, 0);
17233
0
  }
17234
0
  std::string_view out = r->get_pathname();
17235
0
  return ada_string_create(out.data(), out.length());
17236
0
}
17237
17238
0
ada_string ada_get_search(ada_url result) noexcept {
17239
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17240
0
  if (!r) {
17241
0
    return ada_string_create(nullptr, 0);
17242
0
  }
17243
0
  std::string_view out = r->get_search();
17244
0
  return ada_string_create(out.data(), out.length());
17245
0
}
17246
17247
0
ada_string ada_get_protocol(ada_url result) noexcept {
17248
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17249
0
  if (!r) {
17250
0
    return ada_string_create(nullptr, 0);
17251
0
  }
17252
0
  std::string_view out = r->get_protocol();
17253
0
  return ada_string_create(out.data(), out.length());
17254
0
}
17255
17256
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17257
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17258
0
  if (!r) {
17259
0
    return 0;
17260
0
  }
17261
0
  return r->host_type;
17262
0
}
17263
17264
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17265
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17266
0
  if (!r) {
17267
0
    return 0;
17268
0
  }
17269
0
  return r->type;
17270
0
}
17271
17272
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17273
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17274
0
  if (!r) {
17275
0
    return false;
17276
0
  }
17277
0
  return r->set_href(std::string_view(input, length));
17278
0
}
17279
17280
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17281
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17282
0
  if (!r) {
17283
0
    return false;
17284
0
  }
17285
0
  return r->set_host(std::string_view(input, length));
17286
0
}
17287
17288
bool ada_set_hostname(ada_url result, const char* input,
17289
0
                      size_t length) noexcept {
17290
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17291
0
  if (!r) {
17292
0
    return false;
17293
0
  }
17294
0
  return r->set_hostname(std::string_view(input, length));
17295
0
}
17296
17297
bool ada_set_protocol(ada_url result, const char* input,
17298
0
                      size_t length) noexcept {
17299
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17300
0
  if (!r) {
17301
0
    return false;
17302
0
  }
17303
0
  return r->set_protocol(std::string_view(input, length));
17304
0
}
17305
17306
bool ada_set_username(ada_url result, const char* input,
17307
0
                      size_t length) noexcept {
17308
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17309
0
  if (!r) {
17310
0
    return false;
17311
0
  }
17312
0
  return r->set_username(std::string_view(input, length));
17313
0
}
17314
17315
bool ada_set_password(ada_url result, const char* input,
17316
0
                      size_t length) noexcept {
17317
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17318
0
  if (!r) {
17319
0
    return false;
17320
0
  }
17321
0
  return r->set_password(std::string_view(input, length));
17322
0
}
17323
17324
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17325
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17326
0
  if (!r) {
17327
0
    return false;
17328
0
  }
17329
0
  return r->set_port(std::string_view(input, length));
17330
0
}
17331
17332
bool ada_set_pathname(ada_url result, const char* input,
17333
0
                      size_t length) noexcept {
17334
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17335
0
  if (!r) {
17336
0
    return false;
17337
0
  }
17338
0
  return r->set_pathname(std::string_view(input, length));
17339
0
}
17340
17341
/**
17342
 * Update the search/query of the URL.
17343
 *
17344
 * If a URL has `?` as the search value, passing empty string to this function
17345
 * does not remove the attribute. If you need to remove it, please use
17346
 * `ada_clear_search` method.
17347
 */
17348
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17349
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17350
0
  if (r) {
17351
0
    r->set_search(std::string_view(input, length));
17352
0
  }
17353
0
}
17354
17355
/**
17356
 * Update the hash/fragment of the URL.
17357
 *
17358
 * If a URL has `#` as the hash value, passing empty string to this function
17359
 * does not remove the attribute. If you need to remove it, please use
17360
 * `ada_clear_hash` method.
17361
 */
17362
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17363
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17364
0
  if (r) {
17365
0
    r->set_hash(std::string_view(input, length));
17366
0
  }
17367
0
}
17368
17369
0
void ada_clear_port(ada_url result) noexcept {
17370
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17371
0
  if (r) {
17372
0
    r->clear_port();
17373
0
  }
17374
0
}
17375
17376
/**
17377
 * Removes the hash of the URL.
17378
 *
17379
 * Despite `ada_set_hash` method, this function allows the complete
17380
 * removal of the hash attribute, even if it has a value of `#`.
17381
 */
17382
0
void ada_clear_hash(ada_url result) noexcept {
17383
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17384
0
  if (r) {
17385
0
    r->clear_hash();
17386
0
  }
17387
0
}
17388
17389
/**
17390
 * Removes the search of the URL.
17391
 *
17392
 * Despite `ada_set_search` method, this function allows the complete
17393
 * removal of the search attribute, even if it has a value of `?`.
17394
 */
17395
0
void ada_clear_search(ada_url result) noexcept {
17396
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17397
0
  if (r) {
17398
0
    r->clear_search();
17399
0
  }
17400
0
}
17401
17402
0
bool ada_has_credentials(ada_url result) noexcept {
17403
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17404
0
  if (!r) {
17405
0
    return false;
17406
0
  }
17407
0
  return r->has_credentials();
17408
0
}
17409
17410
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17411
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17412
0
  if (!r) {
17413
0
    return false;
17414
0
  }
17415
0
  return r->has_empty_hostname();
17416
0
}
17417
17418
0
bool ada_has_hostname(ada_url result) noexcept {
17419
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17420
0
  if (!r) {
17421
0
    return false;
17422
0
  }
17423
0
  return r->has_hostname();
17424
0
}
17425
17426
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17427
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17428
0
  if (!r) {
17429
0
    return false;
17430
0
  }
17431
0
  return r->has_non_empty_username();
17432
0
}
17433
17434
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17435
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17436
0
  if (!r) {
17437
0
    return false;
17438
0
  }
17439
0
  return r->has_non_empty_password();
17440
0
}
17441
17442
0
bool ada_has_port(ada_url result) noexcept {
17443
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17444
0
  if (!r) {
17445
0
    return false;
17446
0
  }
17447
0
  return r->has_port();
17448
0
}
17449
17450
0
bool ada_has_password(ada_url result) noexcept {
17451
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17452
0
  if (!r) {
17453
0
    return false;
17454
0
  }
17455
0
  return r->has_password();
17456
0
}
17457
17458
0
bool ada_has_hash(ada_url result) noexcept {
17459
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17460
0
  if (!r) {
17461
0
    return false;
17462
0
  }
17463
0
  return r->has_hash();
17464
0
}
17465
17466
0
bool ada_has_search(ada_url result) noexcept {
17467
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17468
0
  if (!r) {
17469
0
    return false;
17470
0
  }
17471
0
  return r->has_search();
17472
0
}
17473
17474
// returns a pointer to the internal url_aggregator::url_components
17475
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17476
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17477
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17478
0
  if (!r) {
17479
0
    return nullptr;
17480
0
  }
17481
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17482
0
}
17483
17484
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17485
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17486
0
  ada_owned_string owned{};
17487
0
  owned.length = out.length();
17488
0
  owned.data = new char[owned.length];
17489
0
  memcpy((void*)owned.data, out.data(), owned.length);
17490
0
  return owned;
17491
0
}
17492
17493
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17494
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17495
0
  ada_owned_string owned{};
17496
0
  owned.length = out.size();
17497
0
  owned.data = new char[owned.length];
17498
0
  memcpy((void*)owned.data, out.data(), owned.length);
17499
0
  return owned;
17500
0
}
17501
17502
ada_url_search_params ada_parse_search_params(const char* input,
17503
0
                                              size_t length) {
17504
0
  return new ada::result<ada::url_search_params>(
17505
0
      ada::url_search_params(std::string_view(input, length)));
17506
0
}
17507
17508
0
void ada_free_search_params(ada_url_search_params result) {
17509
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17510
0
  delete r;
17511
0
}
17512
17513
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17514
0
  ada::result<ada::url_search_params>& r =
17515
0
      *(ada::result<ada::url_search_params>*)result;
17516
0
  if (!r) return ada_owned_string{nullptr, 0};
17517
0
  std::string out = r->to_string();
17518
0
  ada_owned_string owned{};
17519
0
  owned.length = out.size();
17520
0
  owned.data = new char[owned.length];
17521
0
  memcpy((void*)owned.data, out.data(), owned.length);
17522
0
  return owned;
17523
0
}
17524
17525
0
size_t ada_search_params_size(ada_url_search_params result) {
17526
0
  ada::result<ada::url_search_params>& r =
17527
0
      *(ada::result<ada::url_search_params>*)result;
17528
0
  if (!r) {
17529
0
    return 0;
17530
0
  }
17531
0
  return r->size();
17532
0
}
17533
17534
0
void ada_search_params_sort(ada_url_search_params result) {
17535
0
  ada::result<ada::url_search_params>& r =
17536
0
      *(ada::result<ada::url_search_params>*)result;
17537
0
  if (r) {
17538
0
    r->sort();
17539
0
  }
17540
0
}
17541
17542
void ada_search_params_reset(ada_url_search_params result, const char* input,
17543
0
                             size_t length) {
17544
0
  ada::result<ada::url_search_params>& r =
17545
0
      *(ada::result<ada::url_search_params>*)result;
17546
0
  if (r) {
17547
0
    r->reset(std::string_view(input, length));
17548
0
  }
17549
0
}
17550
17551
void ada_search_params_append(ada_url_search_params result, const char* key,
17552
                              size_t key_length, const char* value,
17553
0
                              size_t value_length) {
17554
0
  ada::result<ada::url_search_params>& r =
17555
0
      *(ada::result<ada::url_search_params>*)result;
17556
0
  if (r) {
17557
0
    r->append(std::string_view(key, key_length),
17558
0
              std::string_view(value, value_length));
17559
0
  }
17560
0
}
17561
17562
void ada_search_params_set(ada_url_search_params result, const char* key,
17563
                           size_t key_length, const char* value,
17564
0
                           size_t value_length) {
17565
0
  ada::result<ada::url_search_params>& r =
17566
0
      *(ada::result<ada::url_search_params>*)result;
17567
0
  if (r) {
17568
0
    r->set(std::string_view(key, key_length),
17569
0
           std::string_view(value, value_length));
17570
0
  }
17571
0
}
17572
17573
void ada_search_params_remove(ada_url_search_params result, const char* key,
17574
0
                              size_t key_length) {
17575
0
  ada::result<ada::url_search_params>& r =
17576
0
      *(ada::result<ada::url_search_params>*)result;
17577
0
  if (r) {
17578
0
    r->remove(std::string_view(key, key_length));
17579
0
  }
17580
0
}
17581
17582
void ada_search_params_remove_value(ada_url_search_params result,
17583
                                    const char* key, size_t key_length,
17584
0
                                    const char* value, size_t value_length) {
17585
0
  ada::result<ada::url_search_params>& r =
17586
0
      *(ada::result<ada::url_search_params>*)result;
17587
0
  if (r) {
17588
0
    r->remove(std::string_view(key, key_length),
17589
0
              std::string_view(value, value_length));
17590
0
  }
17591
0
}
17592
17593
bool ada_search_params_has(ada_url_search_params result, const char* key,
17594
0
                           size_t key_length) {
17595
0
  ada::result<ada::url_search_params>& r =
17596
0
      *(ada::result<ada::url_search_params>*)result;
17597
0
  if (!r) {
17598
0
    return false;
17599
0
  }
17600
0
  return r->has(std::string_view(key, key_length));
17601
0
}
17602
17603
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17604
                                 size_t key_length, const char* value,
17605
0
                                 size_t value_length) {
17606
0
  ada::result<ada::url_search_params>& r =
17607
0
      *(ada::result<ada::url_search_params>*)result;
17608
0
  if (!r) {
17609
0
    return false;
17610
0
  }
17611
0
  return r->has(std::string_view(key, key_length),
17612
0
                std::string_view(value, value_length));
17613
0
}
17614
17615
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17616
0
                                 size_t key_length) {
17617
0
  ada::result<ada::url_search_params>& r =
17618
0
      *(ada::result<ada::url_search_params>*)result;
17619
0
  if (!r) {
17620
0
    return ada_string_create(nullptr, 0);
17621
0
  }
17622
0
  auto found = r->get(std::string_view(key, key_length));
17623
0
  if (!found.has_value()) {
17624
0
    return ada_string_create(nullptr, 0);
17625
0
  }
17626
0
  return ada_string_create(found->data(), found->length());
17627
0
}
17628
17629
ada_strings ada_search_params_get_all(ada_url_search_params result,
17630
0
                                      const char* key, size_t key_length) {
17631
0
  ada::result<ada::url_search_params>& r =
17632
0
      *(ada::result<ada::url_search_params>*)result;
17633
0
  if (!r) {
17634
0
    return new ada::result<std::vector<std::string>>(
17635
0
        std::vector<std::string>());
17636
0
  }
17637
0
  return new ada::result<std::vector<std::string>>(
17638
0
      r->get_all(std::string_view(key, key_length)));
17639
0
}
17640
17641
ada_url_search_params_keys_iter ada_search_params_get_keys(
17642
0
    ada_url_search_params result) {
17643
0
  ada::result<ada::url_search_params>& r =
17644
0
      *(ada::result<ada::url_search_params>*)result;
17645
0
  if (!r) {
17646
0
    return new ada::result<ada::url_search_params_keys_iter>(
17647
0
        ada::url_search_params_keys_iter());
17648
0
  }
17649
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
17650
0
}
17651
17652
ada_url_search_params_values_iter ada_search_params_get_values(
17653
0
    ada_url_search_params result) {
17654
0
  ada::result<ada::url_search_params>& r =
17655
0
      *(ada::result<ada::url_search_params>*)result;
17656
0
  if (!r) {
17657
0
    return new ada::result<ada::url_search_params_values_iter>(
17658
0
        ada::url_search_params_values_iter());
17659
0
  }
17660
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
17661
0
}
17662
17663
ada_url_search_params_entries_iter ada_search_params_get_entries(
17664
0
    ada_url_search_params result) {
17665
0
  ada::result<ada::url_search_params>& r =
17666
0
      *(ada::result<ada::url_search_params>*)result;
17667
0
  if (!r) {
17668
0
    return new ada::result<ada::url_search_params_entries_iter>(
17669
0
        ada::url_search_params_entries_iter());
17670
0
  }
17671
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
17672
0
}
17673
17674
0
void ada_free_strings(ada_strings result) {
17675
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17676
0
  delete r;
17677
0
}
17678
17679
0
size_t ada_strings_size(ada_strings result) {
17680
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17681
0
  if (!r) {
17682
0
    return 0;
17683
0
  }
17684
0
  return (*r)->size();
17685
0
}
17686
17687
0
ada_string ada_strings_get(ada_strings result, size_t index) {
17688
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17689
0
  if (!r) {
17690
0
    return ada_string_create(nullptr, 0);
17691
0
  }
17692
0
  std::string_view view = (*r)->at(index);
17693
0
  return ada_string_create(view.data(), view.length());
17694
0
}
17695
17696
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
17697
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17698
0
  delete r;
17699
0
}
17700
17701
ada_string ada_search_params_keys_iter_next(
17702
0
    ada_url_search_params_keys_iter result) {
17703
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17704
0
  if (!r) {
17705
0
    return ada_string_create(nullptr, 0);
17706
0
  }
17707
0
  auto next = (*r)->next();
17708
0
  if (!next.has_value()) {
17709
0
    return ada_string_create(nullptr, 0);
17710
0
  }
17711
0
  return ada_string_create(next->data(), next->length());
17712
0
}
17713
17714
bool ada_search_params_keys_iter_has_next(
17715
0
    ada_url_search_params_keys_iter result) {
17716
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17717
0
  if (!r) {
17718
0
    return false;
17719
0
  }
17720
0
  return (*r)->has_next();
17721
0
}
17722
17723
void ada_free_search_params_values_iter(
17724
0
    ada_url_search_params_values_iter result) {
17725
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17726
0
  delete r;
17727
0
}
17728
17729
ada_string ada_search_params_values_iter_next(
17730
0
    ada_url_search_params_values_iter result) {
17731
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17732
0
  if (!r) {
17733
0
    return ada_string_create(nullptr, 0);
17734
0
  }
17735
0
  auto next = (*r)->next();
17736
0
  if (!next.has_value()) {
17737
0
    return ada_string_create(nullptr, 0);
17738
0
  }
17739
0
  return ada_string_create(next->data(), next->length());
17740
0
}
17741
17742
bool ada_search_params_values_iter_has_next(
17743
0
    ada_url_search_params_values_iter result) {
17744
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17745
0
  if (!r) {
17746
0
    return false;
17747
0
  }
17748
0
  return (*r)->has_next();
17749
0
}
17750
17751
void ada_free_search_params_entries_iter(
17752
0
    ada_url_search_params_entries_iter result) {
17753
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17754
0
  delete r;
17755
0
}
17756
17757
ada_string_pair ada_search_params_entries_iter_next(
17758
0
    ada_url_search_params_entries_iter result) {
17759
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17760
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
17761
0
  auto next = (*r)->next();
17762
0
  if (!next.has_value()) {
17763
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
17764
0
  }
17765
0
  return ada_string_pair{
17766
0
      ada_string_create(next->first.data(), next->first.length()),
17767
0
      ada_string_create(next->second.data(), next->second.length())};
17768
0
}
17769
17770
bool ada_search_params_entries_iter_has_next(
17771
0
    ada_url_search_params_entries_iter result) {
17772
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17773
0
  if (!r) {
17774
0
    return false;
17775
0
  }
17776
0
  return (*r)->has_next();
17777
0
}
17778
17779
}  // extern "C"
17780
/* end file src/ada_c.cpp */
17781
/* end file src/ada.cpp */