Coverage Report

Created: 2025-08-26 06:35

/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source (jump to first uncovered line)
1
/* auto-generated on 2025-08-01 09:04:57 -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
ADA_PUSH_DISABLE_ALL_WARNINGS
137
/* begin file src/ada_idna.cpp */
138
/* auto-generated on 2025-06-26 23:04:30 -0300. Do not edit! */
139
/* begin file src/idna.cpp */
140
/* begin file src/unicode_transcoding.cpp */
141
142
#include <algorithm>
143
#include <cstdint>
144
#include <cstring>
145
146
namespace ada::idna {
147
148
0
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
149
0
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
150
0
  size_t pos = 0;
151
0
  const char32_t* start{utf32_output};
152
0
  while (pos < len) {
153
    // try to convert the next block of 16 ASCII bytes
154
0
    if (pos + 16 <= len) {  // if it is safe to read 16 more
155
                            // bytes, check that they are ascii
156
0
      uint64_t v1;
157
0
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
158
0
      uint64_t v2;
159
0
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
160
0
      uint64_t v{v1 | v2};
161
0
      if ((v & 0x8080808080808080) == 0) {
162
0
        size_t final_pos = pos + 16;
163
0
        while (pos < final_pos) {
164
0
          *utf32_output++ = char32_t(buf[pos]);
165
0
          pos++;
166
0
        }
167
0
        continue;
168
0
      }
169
0
    }
170
0
    uint8_t leading_byte = data[pos];  // leading byte
171
0
    if (leading_byte < 0b10000000) {
172
      // converting one ASCII byte !!!
173
0
      *utf32_output++ = char32_t(leading_byte);
174
0
      pos++;
175
0
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
176
      // We have a two-byte UTF-8
177
0
      if (pos + 1 >= len) {
178
0
        return 0;
179
0
      }  // minimal bound checking
180
0
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
181
0
        return 0;
182
0
      }
183
      // range check
184
0
      uint32_t code_point =
185
0
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
186
0
      if (code_point < 0x80 || 0x7ff < code_point) {
187
0
        return 0;
188
0
      }
189
0
      *utf32_output++ = char32_t(code_point);
190
0
      pos += 2;
191
0
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
192
      // We have a three-byte UTF-8
193
0
      if (pos + 2 >= len) {
194
0
        return 0;
195
0
      }  // minimal bound checking
196
197
0
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
198
0
        return 0;
199
0
      }
200
0
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
201
0
        return 0;
202
0
      }
203
      // range check
204
0
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
205
0
                            (data[pos + 1] & 0b00111111) << 6 |
206
0
                            (data[pos + 2] & 0b00111111);
207
0
      if (code_point < 0x800 || 0xffff < code_point ||
208
0
          (0xd7ff < code_point && code_point < 0xe000)) {
209
0
        return 0;
210
0
      }
211
0
      *utf32_output++ = char32_t(code_point);
212
0
      pos += 3;
213
0
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
214
      // we have a 4-byte UTF-8 word.
215
0
      if (pos + 3 >= len) {
216
0
        return 0;
217
0
      }  // minimal bound checking
218
0
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
219
0
        return 0;
220
0
      }
221
0
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
222
0
        return 0;
223
0
      }
224
0
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
225
0
        return 0;
226
0
      }
227
228
      // range check
229
0
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
230
0
                            (data[pos + 1] & 0b00111111) << 12 |
231
0
                            (data[pos + 2] & 0b00111111) << 6 |
232
0
                            (data[pos + 3] & 0b00111111);
233
0
      if (code_point <= 0xffff || 0x10ffff < code_point) {
234
0
        return 0;
235
0
      }
236
0
      *utf32_output++ = char32_t(code_point);
237
0
      pos += 4;
238
0
    } else {
239
0
      return 0;
240
0
    }
241
0
  }
242
0
  return utf32_output - start;
243
0
}
244
245
0
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
246
  // We are not BOM aware.
247
0
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
248
0
  size_t counter{0};
249
0
  for (size_t i = 0; i != len; ++i) {
250
0
    ++counter;                                      // ASCII
251
0
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
252
0
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
253
0
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
254
0
  }
255
0
  return counter;
256
0
}
257
258
0
size_t utf32_length_from_utf8(const char* buf, size_t len) {
259
0
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
260
0
  return std::count_if(p, std::next(p, len), [](int8_t c) {
261
    // -65 is 0b10111111, anything larger in two-complement's
262
    // should start a new code point.
263
0
    return c > -65;
264
0
  });
265
0
}
266
267
0
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
268
0
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
269
0
  size_t pos = 0;
270
0
  const char* start{utf8_output};
271
0
  while (pos < len) {
272
    // try to convert the next block of 2 ASCII characters
273
0
    if (pos + 2 <= len) {  // if it is safe to read 8 more
274
                           // bytes, check that they are ascii
275
0
      uint64_t v;
276
0
      std::memcpy(&v, data + pos, sizeof(uint64_t));
277
0
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
278
0
        *utf8_output++ = char(buf[pos]);
279
0
        *utf8_output++ = char(buf[pos + 1]);
280
0
        pos += 2;
281
0
        continue;
282
0
      }
283
0
    }
284
0
    uint32_t word = data[pos];
285
0
    if ((word & 0xFFFFFF80) == 0) {
286
      // will generate one UTF-8 bytes
287
0
      *utf8_output++ = char(word);
288
0
      pos++;
289
0
    } else if ((word & 0xFFFFF800) == 0) {
290
      // will generate two UTF-8 bytes
291
      // we have 0b110XXXXX 0b10XXXXXX
292
0
      *utf8_output++ = char((word >> 6) | 0b11000000);
293
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
294
0
      pos++;
295
0
    } else if ((word & 0xFFFF0000) == 0) {
296
      // will generate three UTF-8 bytes
297
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
298
0
      if (word >= 0xD800 && word <= 0xDFFF) {
299
0
        return 0;
300
0
      }
301
0
      *utf8_output++ = char((word >> 12) | 0b11100000);
302
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
303
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
304
0
      pos++;
305
0
    } else {
306
      // will generate four UTF-8 bytes
307
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
308
      // 0b10XXXXXX
309
0
      if (word > 0x10FFFF) {
310
0
        return 0;
311
0
      }
312
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
313
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
314
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
315
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
316
0
      pos++;
317
0
    }
318
0
  }
319
0
  return utf8_output - start;
320
0
}
321
}  // namespace ada::idna
322
/* end file src/unicode_transcoding.cpp */
323
/* begin file src/mapping.cpp */
324
325
#include <algorithm>
326
#include <array>
327
#include <string>
328
329
/* begin file src/mapping_tables.cpp */
330
// IDNA  16.0.0
331
332
// clang-format off
333
#ifndef ADA_IDNA_TABLES_H
334
#define ADA_IDNA_TABLES_H
335
#include <cstdint>
336
337
namespace ada::idna {
338
339
const uint32_t mappings[5236] =
340
{
341
  97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
342
  114, 115, 116, 117, 118, 119, 120, 121, 122, 32, 32, 776, 32, 772, 50, 51, 32, 769,
343
  956, 32, 807, 49, 49, 8260, 52, 49, 8260, 50, 51, 8260, 52, 224, 225, 226, 227,
344
  228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
345
  244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 257, 259, 261, 263, 265, 267,
346
  269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299,
347
  301, 303, 105, 775, 309, 311, 314, 316, 318, 108, 183, 322, 324, 326, 328, 700,
348
  110, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359,
349
  361, 363, 365, 367, 369, 371, 373, 375, 255, 378, 380, 382, 595, 387, 389, 596,
350
  392, 598, 599, 396, 477, 601, 603, 402, 608, 611, 617, 616, 409, 623, 626, 629,
351
  417, 419, 421, 640, 424, 643, 429, 648, 432, 650, 651, 436, 438, 658, 441, 445,
352
  100, 382, 108, 106, 110, 106, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481,
353
  483, 485, 487, 489, 491, 493, 495, 100, 122, 501, 405, 447, 505, 507, 509, 511,
354
  513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541, 543,
355
  414, 547, 549, 551, 553, 555, 557, 559, 561, 563, 11365, 572, 410, 11366, 578, 384,
356
  649, 652, 583, 585, 587, 589, 591, 614, 633, 635, 641, 32, 774, 32, 775, 32, 778,
357
  32, 808, 32, 771, 32, 779, 661, 768, 787, 776, 769, 953, 881, 883, 697, 887, 32,
358
  953, 59, 1011, 32, 776, 769, 940, 941, 942, 943, 972, 973, 974, 945, 946, 947, 948,
359
  949, 950, 951, 952, 954, 955, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967,
360
  968, 969, 970, 971, 983, 985, 987, 989, 991, 993, 995, 997, 999, 1001, 1003, 1005,
361
  1007, 1016, 1019, 891, 892, 893, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111,
362
  1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077,
363
  1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,
364
  1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1121, 1123,
365
  1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151,
366
  1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187,
367
  1189, 1191, 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215,
368
  1231, 1218, 1220, 1222, 1224, 1226, 1228, 1230, 1233, 1235, 1237, 1239, 1241, 1243,
369
  1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267, 1269, 1271,
370
  1273, 1275, 1277, 1279, 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
371
  1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327,
372
  1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390,
373
  1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404,
374
  1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, 1575, 1652,
375
  1608, 1652, 1735, 1652, 1610, 1652, 2325, 2364, 2326, 2364, 2327, 2364, 2332, 2364,
376
  2337, 2364, 2338, 2364, 2347, 2364, 2351, 2364, 2465, 2492, 2466, 2492, 2479, 2492,
377
  2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2849, 2876,
378
  2850, 2876, 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, 3851, 3906, 4023, 3916,
379
  4023, 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, 3956, 4018,
380
  3968, 4018, 3953, 3968, 4019, 3968, 4019, 3953, 3968, 3986, 4023, 3996, 4023, 4001,
381
  4023, 4006, 4023, 4011, 4023, 3984, 4021, 11520, 11521, 11522, 11523, 11524, 11525,
382
  11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537,
383
  11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549,
384
  11550, 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, 11565, 4316, 5104,
385
  5105, 5106, 5107, 5108, 5109, 42571, 7306, 4304, 4305, 4306, 4307, 4308, 4309, 4310,
386
  4311, 4312, 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325,
387
  4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339,
388
  4340, 4341, 4342, 4343, 4344, 4345, 4346, 4349, 4350, 4351, 592, 593, 7426, 604,
389
  7446, 7447, 7453, 7461, 594, 597, 607, 609, 613, 618, 7547, 669, 621, 7557, 671,
390
  625, 624, 627, 628, 632, 642, 427, 7452, 656, 657, 7681, 7683, 7685, 7687, 7689,
391
  7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717,
392
  7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745,
393
  7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773,
394
  7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801,
395
  7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829,
396
  97, 702, 223, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861,
397
  7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889,
398
  7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917,
399
  7919, 7921, 7923, 7925, 7927, 7929, 7931, 7933, 7935, 7936, 7937, 7938, 7939, 7940,
400
  7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972,
401
  7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002,
402
  8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038,
403
  8039, 7936, 953, 7937, 953, 7938, 953, 7939, 953, 7940, 953, 7941, 953, 7942, 953,
404
  7943, 953, 7968, 953, 7969, 953, 7970, 953, 7971, 953, 7972, 953, 7973, 953, 7974,
405
  953, 7975, 953, 8032, 953, 8033, 953, 8034, 953, 8035, 953, 8036, 953, 8037, 953,
406
  8038, 953, 8039, 953, 8048, 953, 945, 953, 940, 953, 8118, 953, 8112, 8113, 32,
407
  787, 32, 834, 32, 776, 834, 8052, 953, 951, 953, 942, 953, 8134, 953, 8050, 32,
408
  787, 768, 32, 787, 769, 32, 787, 834, 912, 8144, 8145, 8054, 32, 788, 768, 32, 788,
409
  769, 32, 788, 834, 944, 8160, 8161, 8058, 8165, 32, 776, 768, 96, 8060, 953, 969,
410
  953, 974, 953, 8182, 953, 8056, 8208, 32, 819, 8242, 8242, 8242, 8242, 8242, 8245,
411
  8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, 63, 63, 33, 33, 63, 48, 53, 54, 55,
412
  56, 57, 43, 8722, 61, 40, 41, 97, 47, 99, 97, 47, 115, 176, 99, 99, 47, 111, 99,
413
  47, 117, 176, 102, 115, 109, 116, 101, 108, 116, 109, 8526, 1488, 1489, 1490, 1491,
414
  102, 97, 120, 8721, 49, 8260, 55, 49, 8260, 57, 49, 8260, 49, 48, 49, 8260, 51,
415
  50, 8260, 51, 49, 8260, 53, 50, 8260, 53, 51, 8260, 53, 52, 8260, 53, 49, 8260,
416
  54, 53, 8260, 54, 49, 8260, 56, 51, 8260, 56, 53, 8260, 56, 55, 8260, 56, 105, 105,
417
  105, 105, 105, 105, 118, 118, 105, 118, 105, 105, 118, 105, 105, 105, 105, 120,
418
  120, 105, 120, 105, 105, 8580, 48, 8260, 51, 8747, 8747, 8747, 8747, 8747, 8750,
419
  8750, 8750, 8750, 8750, 12296, 12297, 49, 50, 49, 51, 49, 52, 49, 53, 49, 54, 49,
420
  55, 49, 56, 49, 57, 50, 48, 40, 49, 41, 40, 50, 41, 40, 51, 41, 40, 52, 41, 40,
421
  53, 41, 40, 54, 41, 40, 55, 41, 40, 56, 41, 40, 57, 41, 40, 49, 48, 41, 40, 49,
422
  49, 41, 40, 49, 50, 41, 40, 49, 51, 41, 40, 49, 52, 41, 40, 49, 53, 41, 40, 49,
423
  54, 41, 40, 49, 55, 41, 40, 49, 56, 41, 40, 49, 57, 41, 40, 50, 48, 41, 40, 97,
424
  41, 40, 98, 41, 40, 99, 41, 40, 100, 41, 40, 101, 41, 40, 102, 41, 40, 103, 41,
425
  40, 104, 41, 40, 105, 41, 40, 106, 41, 40, 107, 41, 40, 108, 41, 40, 109, 41, 40,
426
  110, 41, 40, 111, 41, 40, 112, 41, 40, 113, 41, 40, 114, 41, 40, 115, 41, 40, 116,
427
  41, 40, 117, 41, 40, 118, 41, 40, 119, 41, 40, 120, 41, 40, 121, 41, 40, 122, 41,
428
  58, 58, 61, 61, 61, 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318,
429
  11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330,
430
  11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342,
431
  11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354,
432
  11355, 11356, 11357, 11358, 11359, 11361, 619, 7549, 637, 11368, 11370, 11372, 11379,
433
  11382, 575, 576, 11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409,
434
  11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433,
435
  11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457,
436
  11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481,
437
  11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, 11617, 27597, 40863, 19968,
438
  20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866,
439
  20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340,
440
  21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823,
441
  22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049,
442
  24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515,
443
  25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352,
444
  26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700,
445
  28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916,
446
  29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446,
447
  30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566,
448
  32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267,
449
  33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915,
450
  35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275,
451
  36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272,
452
  38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913,
453
  39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730,
454
  39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701,
455
  40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, 40864, 46, 12306, 21316,
456
  21317, 32, 12441, 32, 12442, 12424, 12426, 12467, 12488, 4352, 4353, 4522, 4354,
457
  4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, 4358, 4359,
458
  4360, 4385, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450,
459
  4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464,
460
  4465, 4466, 4467, 4468, 4469, 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, 4569,
461
  4380, 4573, 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, 4396, 4397, 4398,
462
  4399, 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, 4488,
463
  4497, 4498, 4500, 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, 19993, 19969,
464
  22825, 22320, 40, 4352, 41, 40, 4354, 41, 40, 4355, 41, 40, 4357, 41, 40, 4358,
465
  41, 40, 4359, 41, 40, 4361, 41, 40, 4363, 41, 40, 4364, 41, 40, 4366, 41, 40, 4367,
466
  41, 40, 4368, 41, 40, 4369, 41, 40, 4370, 41, 40, 44032, 41, 40, 45208, 41, 40,
467
  45796, 41, 40, 46972, 41, 40, 47560, 41, 40, 48148, 41, 40, 49324, 41, 40, 50500,
468
  41, 40, 51088, 41, 40, 52264, 41, 40, 52852, 41, 40, 53440, 41, 40, 54028, 41, 40,
469
  54616, 41, 40, 51452, 41, 40, 50724, 51204, 41, 40, 50724, 54980, 41, 40, 19968,
470
  41, 40, 20108, 41, 40, 19977, 41, 40, 22235, 41, 40, 20116, 41, 40, 20845, 41, 40,
471
  19971, 41, 40, 20843, 41, 40, 20061, 41, 40, 21313, 41, 40, 26376, 41, 40, 28779,
472
  41, 40, 27700, 41, 40, 26408, 41, 40, 37329, 41, 40, 22303, 41, 40, 26085, 41, 40,
473
  26666, 41, 40, 26377, 41, 40, 31038, 41, 40, 21517, 41, 40, 29305, 41, 40, 36001,
474
  41, 40, 31069, 41, 40, 21172, 41, 40, 20195, 41, 40, 21628, 41, 40, 23398, 41, 40,
475
  30435, 41, 40, 20225, 41, 40, 36039, 41, 40, 21332, 41, 40, 31085, 41, 40, 20241,
476
  41, 40, 33258, 41, 40, 33267, 41, 21839, 24188, 31631, 112, 116, 101, 50, 50, 50,
477
  52, 50, 53, 50, 54, 50, 55, 50, 56, 50, 57, 51, 48, 51, 51, 51, 52, 51, 53, 52280,
478
  44256, 51452, 51032, 50864, 31192, 30007, 36969, 20778, 21360, 27880, 38917, 20889,
479
  27491, 24038, 21491, 21307, 23447, 22812, 51, 54, 51, 55, 51, 56, 51, 57, 52, 48,
480
  52, 52, 52, 53, 52, 54, 52, 55, 52, 56, 52, 57, 53, 48, 49, 26376, 50, 26376, 51,
481
  26376, 52, 26376, 53, 26376, 54, 26376, 55, 26376, 56, 26376, 57, 26376, 49, 48,
482
  26376, 49, 49, 26376, 49, 50, 26376, 104, 103, 101, 114, 103, 101, 118, 108, 116,
483
  100, 12450, 12452, 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12469, 12471,
484
  12473, 12475, 12477, 12479, 12481, 12484, 12486, 12490, 12491, 12492, 12493, 12494,
485
  12495, 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, 12518,
486
  12520, 12521, 12522, 12523, 12524, 12525, 12527, 12528, 12529, 12530, 20196, 21644,
487
  12450, 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450,
488
  12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, 12457,
489
  12531, 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531,
490
  12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, 12521, 12483, 12488, 12459,
491
  12525, 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462,
492
  12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, 12480, 12540, 12461, 12525,
493
  12461, 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461,
494
  12525, 12527, 12483, 12488, 12464, 12521, 12512, 12488, 12531, 12463, 12523, 12476,
495
  12452, 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, 12467, 12523, 12490,
496
  12467, 12540, 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, 12540, 12512,
497
  12471, 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, 12488, 12480, 12540,
498
  12473, 12487, 12471, 12489, 12523, 12490, 12494, 12494, 12483, 12488, 12495, 12452,
499
  12484, 12497, 12540, 12475, 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524,
500
  12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499,
501
  12523, 12501, 12449, 12521, 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483,
502
  12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, 12506,
503
  12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540,
504
  12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, 12507,
505
  12531, 12509, 12531, 12489, 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452,
506
  12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, 12510,
507
  12531, 12471, 12519, 12531, 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522,
508
  12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, 12531, 12516, 12540, 12489,
509
  12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, 12521,
510
  12523, 12500, 12540, 12523, 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488,
511
  12466, 12531, 48, 28857, 49, 28857, 50, 28857, 51, 28857, 52, 28857, 53, 28857,
512
  54, 28857, 55, 28857, 56, 28857, 57, 28857, 49, 48, 28857, 49, 49, 28857, 49, 50,
513
  28857, 49, 51, 28857, 49, 52, 28857, 49, 53, 28857, 49, 54, 28857, 49, 55, 28857,
514
  49, 56, 28857, 49, 57, 28857, 50, 48, 28857, 50, 49, 28857, 50, 50, 28857, 50, 51,
515
  28857, 50, 52, 28857, 104, 112, 97, 100, 97, 97, 117, 98, 97, 114, 111, 118, 112,
516
  99, 100, 109, 100, 109, 50, 100, 109, 51, 105, 117, 24179, 25104, 26157, 21644,
517
  22823, 27491, 26126, 27835, 26666, 24335, 20250, 31038, 110, 97, 956, 97, 109, 97,
518
  107, 97, 107, 98, 109, 98, 103, 98, 99, 97, 108, 107, 99, 97, 108, 112, 102, 110,
519
  102, 956, 102, 956, 103, 109, 103, 107, 103, 104, 122, 107, 104, 122, 109, 104,
520
  122, 116, 104, 122, 956, 108, 109, 108, 100, 108, 102, 109, 110, 109, 956, 109,
521
  109, 109, 99, 109, 107, 109, 109, 109, 50, 99, 109, 50, 107, 109, 50, 109, 109,
522
  51, 99, 109, 51, 107, 109, 51, 109, 8725, 115, 109, 8725, 115, 50, 107, 112, 97,
523
  109, 112, 97, 103, 112, 97, 114, 97, 100, 114, 97, 100, 8725, 115, 114, 97, 100,
524
  8725, 115, 50, 112, 115, 110, 115, 956, 115, 109, 115, 112, 118, 110, 118, 956,
525
  118, 109, 118, 107, 118, 112, 119, 110, 119, 956, 119, 109, 119, 107, 119, 107,
526
  969, 109, 969, 98, 113, 99, 8725, 107, 103, 100, 98, 103, 121, 104, 97, 105, 110,
527
  107, 107, 107, 116, 108, 110, 108, 111, 103, 108, 120, 109, 105, 108, 109, 111,
528
  108, 112, 104, 112, 112, 109, 112, 114, 115, 118, 119, 98, 118, 8725, 109, 97, 8725,
529
  109, 49, 26085, 50, 26085, 51, 26085, 52, 26085, 53, 26085, 54, 26085, 55, 26085,
530
  56, 26085, 57, 26085, 49, 48, 26085, 49, 49, 26085, 49, 50, 26085, 49, 51, 26085,
531
  49, 52, 26085, 49, 53, 26085, 49, 54, 26085, 49, 55, 26085, 49, 56, 26085, 49, 57,
532
  26085, 50, 48, 26085, 50, 49, 26085, 50, 50, 26085, 50, 51, 26085, 50, 52, 26085,
533
  50, 53, 26085, 50, 54, 26085, 50, 55, 26085, 50, 56, 26085, 50, 57, 26085, 51, 48,
534
  26085, 51, 49, 26085, 103, 97, 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575,
535
  42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, 42599,
536
  42601, 42603, 42605, 42625, 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641,
537
  42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, 42799,
538
  42803, 42805, 42807, 42809, 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825,
539
  42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, 42849,
540
  42851, 42853, 42855, 42857, 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881,
541
  42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, 42913,
542
  42915, 42917, 42919, 42921, 620, 670, 647, 43859, 42933, 42935, 42937, 42939, 42941,
543
  42943, 42945, 42947, 42900, 7566, 42952, 42954, 612, 42957, 42961, 42967, 42969,
544
  42971, 411, 42998, 43831, 43858, 653, 5024, 5025, 5026, 5027, 5028, 5029, 5030,
545
  5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044,
546
  5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058,
547
  5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072,
548
  5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086,
549
  5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100,
550
  5101, 5102, 5103, 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, 22856,
551
  25078, 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, 28889, 29662, 33853,
552
  37226, 39409, 20098, 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, 35172,
553
  25289, 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, 20919, 21214, 25796,
554
  27347, 29200, 30439, 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, 32160,
555
  33737, 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, 36034, 38647, 22744,
556
  23650, 27155, 28122, 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, 31260,
557
  32190, 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, 29575, 30064, 21271,
558
  30971, 20415, 24489, 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, 35498,
559
  27578, 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, 26753, 31975, 33391,
560
  35538, 37327, 21237, 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, 40654,
561
  26310, 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, 29833, 31178, 32244,
562
  32879, 36646, 34030, 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, 24565,
563
  25467, 27566, 31806, 29557, 22265, 23994, 24604, 29618, 29801, 32666, 32838, 37428,
564
  38646, 38728, 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615,
565
  26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611, 27969, 28316,
566
  29705, 30041, 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459,
567
  24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877, 29702, 30178,
568
  32633, 35023, 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023,
569
  40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160, 33590, 21050,
570
  20999, 24230, 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952,
571
  22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742, 31934, 34322,
572
  35576, 36920, 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813,
573
  21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724, 24936, 24974,
574
  25074, 25935, 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865,
575
  31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265, 32321, 32626,
576
  32773, 33261, 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627,
577
  38911, 38971, 24693, 148206, 33304, 20006, 20917, 20840, 20352, 20805, 20864, 21191,
578
  21242, 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, 24274, 24281, 24425,
579
  24493, 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, 25942, 26395, 26454,
580
  28379, 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, 30237, 30239, 30427,
581
  30452, 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, 33775, 34681, 35137,
582
  35206, 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, 38524, 38875, 38923,
583
  39698, 141386, 141380, 144341, 15261, 16408, 16441, 152137, 154832, 163539, 40771,
584
  40846, 102, 102, 102, 105, 102, 108, 102, 102, 108, 1396, 1398, 1396, 1381, 1396,
585
  1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501,
586
  1512, 1514, 1513, 1473, 1513, 1474, 1513, 1468, 1473, 1513, 1468, 1474, 1488, 1463,
587
  1488, 1464, 1488, 1468, 1489, 1468, 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468,
588
  1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, 1499, 1468, 1500, 1468, 1502, 1468,
589
  1504, 1468, 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, 1511, 1468, 1512, 1468,
590
  1514, 1468, 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, 1488, 1500, 1649, 1659,
591
  1662, 1664, 1658, 1663, 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677, 1676, 1678,
592
  1672, 1688, 1681, 1705, 1711, 1715, 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747,
593
  1709, 1734, 1736, 1739, 1733, 1737, 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608,
594
  1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, 1574, 1609, 1740, 1574, 1580, 1574,
595
  1581, 1574, 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, 1582, 1576, 1605, 1576,
596
  1609, 1576, 1610, 1578, 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578, 1609, 1578,
597
  1610, 1579, 1580, 1579, 1605, 1579, 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581,
598
  1605, 1582, 1580, 1582, 1581, 1582, 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587,
599
  1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, 1581, 1590, 1582, 1590, 1605, 1591,
600
  1581, 1591, 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, 1580, 1594, 1605, 1601,
601
  1580, 1601, 1581, 1601, 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602, 1581, 1602,
602
  1605, 1602, 1609, 1602, 1610, 1603, 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603,
603
  1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, 1580, 1604, 1581, 1604, 1582, 1604,
604
  1605, 1604, 1609, 1604, 1610, 1605, 1580, 1605, 1605, 1605, 1609, 1605, 1610, 1606,
605
  1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, 1609, 1606, 1610, 1607, 1580, 1607,
606
  1605, 1607, 1609, 1607, 1610, 1610, 1581, 1610, 1582, 1610, 1609, 1584, 1648, 1585,
607
  1648, 1609, 1648, 32, 1612, 1617, 32, 1613, 1617, 32, 1614, 1617, 32, 1615, 1617,
608
  32, 1616, 1617, 32, 1617, 1648, 1574, 1585, 1574, 1586, 1574, 1606, 1576, 1585,
609
  1576, 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, 1606, 1579, 1585, 1579, 1586,
610
  1579, 1606, 1605, 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, 1585, 1610, 1586,
611
  1574, 1582, 1574, 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, 1607, 1606, 1607,
612
  1607, 1648, 1579, 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, 1614, 1617, 1600,
613
  1615, 1617, 1600, 1616, 1617, 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, 1594,
614
  1609, 1594, 1610, 1587, 1609, 1587, 1610, 1588, 1609, 1588, 1610, 1581, 1609, 1580,
615
  1609, 1580, 1610, 1582, 1609, 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, 1588,
616
  1580, 1588, 1581, 1588, 1582, 1588, 1585, 1587, 1585, 1589, 1585, 1590, 1585, 1575,
617
  1611, 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, 1605, 1578, 1582, 1605, 1578,
618
  1605, 1580, 1578, 1605, 1581, 1578, 1605, 1582, 1581, 1605, 1610, 1581, 1605, 1609,
619
  1587, 1581, 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, 1605, 1581, 1587, 1605,
620
  1580, 1587, 1605, 1605, 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581, 1605, 1588,
621
  1580, 1610, 1588, 1605, 1582, 1588, 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605,
622
  1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, 1610, 1593, 1580, 1605, 1593, 1605,
623
  1605, 1593, 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, 1594, 1605, 1609, 1601,
624
  1582, 1605, 1602, 1605, 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604, 1581, 1610,
625
  1604, 1581, 1609, 1604, 1580, 1580, 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581,
626
  1580, 1605, 1581, 1610, 1605, 1580, 1581, 1605, 1582, 1605, 1605, 1580, 1582, 1607,
627
  1605, 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, 1581, 1609, 1606, 1580, 1605,
628
  1606, 1580, 1609, 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, 1605, 1576, 1582,
629
  1610, 1578, 1580, 1610, 1578, 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, 1578,
630
  1605, 1610, 1578, 1605, 1609, 1580, 1605, 1610, 1580, 1581, 1609, 1580, 1605, 1609,
631
  1587, 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, 1590, 1581, 1610, 1604, 1580,
632
  1610, 1604, 1605, 1610, 1610, 1580, 1610, 1610, 1605, 1610, 1605, 1605, 1610, 1602,
633
  1605, 1610, 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, 1610, 1606, 1580, 1581,
634
  1605, 1582, 1610, 1604, 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610, 1581, 1580,
635
  1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606,
636
  1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603,
637
  1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, 1585, 1587, 1608, 1604,
638
  1593, 1604, 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, 1609, 1589, 1604, 1609,
639
  32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605,
640
  1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, 12289,
641
  12310, 12311, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298, 12299,
642
  12300, 12301, 12302, 12303, 91, 93, 35, 38, 42, 45, 60, 62, 92, 36, 37, 64, 32,
643
  1611, 1600, 1611, 1600, 1617, 32, 1618, 1600, 1618, 1569, 1570, 1571, 1572, 1573,
644
  1577, 1604, 1570, 1604, 1571, 1604, 1573, 34, 39, 94, 124, 126, 10629, 10630, 12539,
645
  12453, 12515, 162, 163, 172, 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, 9632,
646
  9675, 66600, 66601, 66602, 66603, 66604, 66605, 66606, 66607, 66608, 66609, 66610,
647
  66611, 66612, 66613, 66614, 66615, 66616, 66617, 66618, 66619, 66620, 66621, 66622,
648
  66623, 66624, 66625, 66626, 66627, 66628, 66629, 66630, 66631, 66632, 66633, 66634,
649
  66635, 66636, 66637, 66638, 66639, 66776, 66777, 66778, 66779, 66780, 66781, 66782,
650
  66783, 66784, 66785, 66786, 66787, 66788, 66789, 66790, 66791, 66792, 66793, 66794,
651
  66795, 66796, 66797, 66798, 66799, 66800, 66801, 66802, 66803, 66804, 66805, 66806,
652
  66807, 66808, 66809, 66810, 66811, 66967, 66968, 66969, 66970, 66971, 66972, 66973,
653
  66974, 66975, 66976, 66977, 66979, 66980, 66981, 66982, 66983, 66984, 66985, 66986,
654
  66987, 66988, 66989, 66990, 66991, 66992, 66993, 66995, 66996, 66997, 66998, 66999,
655
  67000, 67001, 67003, 67004, 720, 721, 665, 675, 43878, 677, 676, 7569, 600, 606,
656
  681, 610, 667, 668, 615, 644, 682, 683, 122628, 42894, 622, 122629, 654, 122630,
657
  630, 631, 634, 122632, 638, 680, 678, 43879, 679, 11377, 655, 673, 674, 664, 448,
658
  449, 450, 122634, 122654, 68800, 68801, 68802, 68803, 68804, 68805, 68806, 68807,
659
  68808, 68809, 68810, 68811, 68812, 68813, 68814, 68815, 68816, 68817, 68818, 68819,
660
  68820, 68821, 68822, 68823, 68824, 68825, 68826, 68827, 68828, 68829, 68830, 68831,
661
  68832, 68833, 68834, 68835, 68836, 68837, 68838, 68839, 68840, 68841, 68842, 68843,
662
  68844, 68845, 68846, 68847, 68848, 68849, 68850, 68976, 68977, 68978, 68979, 68980,
663
  68981, 68982, 68983, 68984, 68985, 68986, 68987, 68988, 68989, 68990, 68991, 68992,
664
  68993, 68994, 68995, 68996, 68997, 71872, 71873, 71874, 71875, 71876, 71877, 71878,
665
  71879, 71880, 71881, 71882, 71883, 71884, 71885, 71886, 71887, 71888, 71889, 71890,
666
  71891, 71892, 71893, 71894, 71895, 71896, 71897, 71898, 71899, 71900, 71901, 71902,
667
  71903, 93792, 93793, 93794, 93795, 93796, 93797, 93798, 93799, 93800, 93801, 93802,
668
  93803, 93804, 93805, 93806, 93807, 93808, 93809, 93810, 93811, 93812, 93813, 93814,
669
  93815, 93816, 93817, 93818, 93819, 93820, 93821, 93822, 93823, 119127, 119141, 119128,
670
  119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128, 119141, 119152,
671
  119128, 119141, 119153, 119128, 119141, 119154, 119225, 119141, 119226, 119141,
672
  119225, 119141, 119150, 119226, 119141, 119150, 119225, 119141, 119151, 119226,
673
  119141, 119151, 305, 567, 8711, 8706, 125218, 125219, 125220, 125221, 125222, 125223,
674
  125224, 125225, 125226, 125227, 125228, 125229, 125230, 125231, 125232, 125233,
675
  125234, 125235, 125236, 125237, 125238, 125239, 125240, 125241, 125242, 125243,
676
  125244, 125245, 125246, 125247, 125248, 125249, 125250, 125251, 1646, 1697, 1647,
677
  48, 44, 49, 44, 50, 44, 51, 44, 52, 44, 53, 44, 54, 44, 55, 44, 56, 44, 57, 44,
678
  12308, 115, 12309, 119, 122, 104, 118, 115, 100, 115, 115, 112, 112, 118, 119, 99,
679
  109, 114, 100, 106, 12411, 12363, 12467, 12467, 23383, 21452, 22810, 35299, 20132,
680
  26144, 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436,
681
  25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, 30003, 21106, 21942,
682
  37197, 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433,
683
  12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, 12309, 12308, 21213,
684
  12309, 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, 131362, 20320, 20411,
685
  20482, 20602, 20633, 20687, 13470, 132666, 20820, 20836, 20855, 132380, 13497, 20839,
686
  132427, 20887, 20900, 20172, 20908, 168415, 20995, 13535, 21051, 21062, 21111, 13589,
687
  21253, 21254, 21321, 21338, 21363, 21373, 21375, 133676, 28784, 21450, 21471, 133987,
688
  21483, 21489, 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, 21843, 21859,
689
  21892, 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, 22516, 22541,
690
  22411, 22578, 22577, 22700, 136420, 22770, 22775, 22790, 22818, 22882, 136872, 136938,
691
  23020, 23067, 23079, 23000, 23142, 14062, 14076, 23304, 23358, 137672, 23491, 23512,
692
  23539, 138008, 23551, 23558, 24403, 14209, 23648, 23744, 23693, 138724, 23875, 138726,
693
  23918, 23915, 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, 139651,
694
  14460, 24240, 24243, 24246, 172946, 140081, 33281, 24354, 14535, 144056, 156122,
695
  24418, 24427, 14563, 24474, 24525, 24535, 24569, 24705, 14650, 14620, 141012, 24775,
696
  24904, 24908, 24954, 25010, 24996, 25007, 25054, 25115, 25181, 25265, 25300, 25424,
697
  142092, 25405, 25340, 25448, 25475, 25572, 142321, 25634, 25541, 25513, 14894, 25705,
698
  25726, 25757, 25719, 14956, 25964, 143370, 26083, 26360, 26185, 15129, 15112, 15076,
699
  20882, 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, 144323, 15177, 26618,
700
  26501, 26706, 144493, 26766, 26655, 26900, 26946, 27043, 27114, 27304, 145059, 27355,
701
  15384, 27425, 145575, 27476, 15438, 27506, 27551, 27579, 146061, 138507, 146170,
702
  27726, 146620, 27839, 27853, 27751, 27926, 27966, 28009, 28024, 28037, 146718, 27956,
703
  28207, 28270, 15667, 28359, 147153, 28153, 28526, 147294, 147342, 28614, 28729,
704
  28699, 15766, 28746, 28797, 28791, 28845, 132389, 28997, 148067, 29084, 148395,
705
  29224, 29264, 149000, 29312, 29333, 149301, 149524, 29562, 29579, 16044, 29605,
706
  16056, 29767, 29788, 29829, 29898, 16155, 29988, 150582, 30014, 150674, 139679,
707
  30224, 151457, 151480, 151620, 16380, 16392, 151795, 151794, 151833, 151859, 30494,
708
  30495, 30603, 16454, 16534, 152605, 30798, 16611, 153126, 153242, 153285, 31211,
709
  16687, 31306, 31311, 153980, 154279, 31470, 16898, 154539, 31686, 31689, 16935,
710
  154752, 31954, 17056, 31976, 31971, 32000, 155526, 32099, 17153, 32199, 32258, 32325,
711
  17204, 156200, 156231, 17241, 156377, 32634, 156478, 32661, 32762, 156890, 156963,
712
  32864, 157096, 32880, 144223, 17365, 32946, 33027, 17419, 33086, 23221, 157607,
713
  157621, 144275, 144284, 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457,
714
  33459, 33469, 33510, 158524, 33565, 33635, 33709, 33571, 33725, 33767, 33619, 33738,
715
  33740, 33756, 158774, 159083, 158933, 17707, 34033, 34035, 34070, 160714, 34148,
716
  159532, 17757, 17761, 159665, 159954, 17771, 34384, 34407, 34409, 34473, 34440,
717
  34574, 34530, 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, 161383, 35031,
718
  35038, 17973, 35066, 13499, 161966, 162150, 18110, 18119, 35488, 162984, 36011,
719
  36033, 36123, 36215, 163631, 133124, 36299, 36284, 36336, 133342, 36564, 165330,
720
  165357, 37012, 37105, 37137, 165678, 37147, 37432, 37591, 37592, 37500, 37881, 37909,
721
  166906, 38283, 18837, 38327, 167287, 18918, 38595, 23986, 38691, 168261, 168474,
722
  19054, 19062, 38880, 168970, 19122, 169110, 38953, 169398, 39138, 19251, 39209,
723
  39335, 39362, 39422, 19406, 170800, 40000, 40189, 19662, 19693, 40295, 172238, 19704,
724
  172293, 172558, 172689, 19798, 40702, 40709, 40719, 40726, 173568,
725
726
};
727
const uint32_t table[8150][2] =
728
{
729
  {0, 1}, {65, 16777219}, {66, 16777475}, {67, 16777731},
730
  {68, 16777987}, {69, 16778243}, {70, 16778499}, {71, 16778755},
731
  {72, 16779011}, {73, 16779267}, {74, 16779523}, {75, 16779779},
732
  {76, 16780035}, {77, 16780291}, {78, 16780547}, {79, 16780803},
733
  {80, 16781059}, {81, 16781315}, {82, 16781571}, {83, 16781827},
734
  {84, 16782083}, {85, 16782339}, {86, 16782595}, {87, 16782851},
735
  {88, 16783107}, {89, 16783363}, {90, 16783619}, {91, 1},
736
  {128, 2}, {160, 16783875}, {161, 1}, {168, 33561347},
737
  {169, 1}, {170, 16777219}, {171, 1}, {173, 0},
738
  {174, 1}, {175, 33561859}, {176, 1}, {178, 16785155},
739
  {179, 16785411}, {180, 33562883}, {181, 16786179}, {182, 1},
740
  {184, 33563651}, {185, 16786947}, {186, 16780803}, {187, 1},
741
  {188, 50341635}, {189, 50342403}, {190, 50343171}, {191, 1},
742
  {192, 16789507}, {193, 16789763}, {194, 16790019}, {195, 16790275},
743
  {196, 16790531}, {197, 16790787}, {198, 16791043}, {199, 16791299},
744
  {200, 16791555}, {201, 16791811}, {202, 16792067}, {203, 16792323},
745
  {204, 16792579}, {205, 16792835}, {206, 16793091}, {207, 16793347},
746
  {208, 16793603}, {209, 16793859}, {210, 16794115}, {211, 16794371},
747
  {212, 16794627}, {213, 16794883}, {214, 16795139}, {215, 1},
748
  {216, 16795395}, {217, 16795651}, {218, 16795907}, {219, 16796163},
749
  {220, 16796419}, {221, 16796675}, {222, 16796931}, {223, 1},
750
  {256, 16797187}, {257, 1}, {258, 16797443}, {259, 1},
751
  {260, 16797699}, {261, 1}, {262, 16797955}, {263, 1},
752
  {264, 16798211}, {265, 1}, {266, 16798467}, {267, 1},
753
  {268, 16798723}, {269, 1}, {270, 16798979}, {271, 1},
754
  {272, 16799235}, {273, 1}, {274, 16799491}, {275, 1},
755
  {276, 16799747}, {277, 1}, {278, 16800003}, {279, 1},
756
  {280, 16800259}, {281, 1}, {282, 16800515}, {283, 1},
757
  {284, 16800771}, {285, 1}, {286, 16801027}, {287, 1},
758
  {288, 16801283}, {289, 1}, {290, 16801539}, {291, 1},
759
  {292, 16801795}, {293, 1}, {294, 16802051}, {295, 1},
760
  {296, 16802307}, {297, 1}, {298, 16802563}, {299, 1},
761
  {300, 16802819}, {301, 1}, {302, 16803075}, {303, 1},
762
  {304, 33580547}, {305, 1}, {306, 33556483}, {308, 16803843},
763
  {309, 1}, {310, 16804099}, {311, 1}, {313, 16804355},
764
  {314, 1}, {315, 16804611}, {316, 1}, {317, 16804867},
765
  {318, 1}, {319, 33582339}, {321, 16805635}, {322, 1},
766
  {323, 16805891}, {324, 1}, {325, 16806147}, {326, 1},
767
  {327, 16806403}, {328, 1}, {329, 33583875}, {330, 16807171},
768
  {331, 1}, {332, 16807427}, {333, 1}, {334, 16807683},
769
  {335, 1}, {336, 16807939}, {337, 1}, {338, 16808195},
770
  {339, 1}, {340, 16808451}, {341, 1}, {342, 16808707},
771
  {343, 1}, {344, 16808963}, {345, 1}, {346, 16809219},
772
  {347, 1}, {348, 16809475}, {349, 1}, {350, 16809731},
773
  {351, 1}, {352, 16809987}, {353, 1}, {354, 16810243},
774
  {355, 1}, {356, 16810499}, {357, 1}, {358, 16810755},
775
  {359, 1}, {360, 16811011}, {361, 1}, {362, 16811267},
776
  {363, 1}, {364, 16811523}, {365, 1}, {366, 16811779},
777
  {367, 1}, {368, 16812035}, {369, 1}, {370, 16812291},
778
  {371, 1}, {372, 16812547}, {373, 1}, {374, 16812803},
779
  {375, 1}, {376, 16813059}, {377, 16813315}, {378, 1},
780
  {379, 16813571}, {380, 1}, {381, 16813827}, {382, 1},
781
  {383, 16781827}, {384, 1}, {385, 16814083}, {386, 16814339},
782
  {387, 1}, {388, 16814595}, {389, 1}, {390, 16814851},
783
  {391, 16815107}, {392, 1}, {393, 16815363}, {394, 16815619},
784
  {395, 16815875}, {396, 1}, {398, 16816131}, {399, 16816387},
785
  {400, 16816643}, {401, 16816899}, {402, 1}, {403, 16817155},
786
  {404, 16817411}, {405, 1}, {406, 16817667}, {407, 16817923},
787
  {408, 16818179}, {409, 1}, {412, 16818435}, {413, 16818691},
788
  {414, 1}, {415, 16818947}, {416, 16819203}, {417, 1},
789
  {418, 16819459}, {419, 1}, {420, 16819715}, {421, 1},
790
  {422, 16819971}, {423, 16820227}, {424, 1}, {425, 16820483},
791
  {426, 1}, {428, 16820739}, {429, 1}, {430, 16820995},
792
  {431, 16821251}, {432, 1}, {433, 16821507}, {434, 16821763},
793
  {435, 16822019}, {436, 1}, {437, 16822275}, {438, 1},
794
  {439, 16822531}, {440, 16822787}, {441, 1}, {444, 16823043},
795
  {445, 1}, {452, 33600515}, {455, 33601027}, {458, 33601539},
796
  {461, 16824835}, {462, 1}, {463, 16825091}, {464, 1},
797
  {465, 16825347}, {466, 1}, {467, 16825603}, {468, 1},
798
  {469, 16825859}, {470, 1}, {471, 16826115}, {472, 1},
799
  {473, 16826371}, {474, 1}, {475, 16826627}, {476, 1},
800
  {478, 16826883}, {479, 1}, {480, 16827139}, {481, 1},
801
  {482, 16827395}, {483, 1}, {484, 16827651}, {485, 1},
802
  {486, 16827907}, {487, 1}, {488, 16828163}, {489, 1},
803
  {490, 16828419}, {491, 1}, {492, 16828675}, {493, 1},
804
  {494, 16828931}, {495, 1}, {497, 33606403}, {500, 16829699},
805
  {501, 1}, {502, 16829955}, {503, 16830211}, {504, 16830467},
806
  {505, 1}, {506, 16830723}, {507, 1}, {508, 16830979},
807
  {509, 1}, {510, 16831235}, {511, 1}, {512, 16831491},
808
  {513, 1}, {514, 16831747}, {515, 1}, {516, 16832003},
809
  {517, 1}, {518, 16832259}, {519, 1}, {520, 16832515},
810
  {521, 1}, {522, 16832771}, {523, 1}, {524, 16833027},
811
  {525, 1}, {526, 16833283}, {527, 1}, {528, 16833539},
812
  {529, 1}, {530, 16833795}, {531, 1}, {532, 16834051},
813
  {533, 1}, {534, 16834307}, {535, 1}, {536, 16834563},
814
  {537, 1}, {538, 16834819}, {539, 1}, {540, 16835075},
815
  {541, 1}, {542, 16835331}, {543, 1}, {544, 16835587},
816
  {545, 1}, {546, 16835843}, {547, 1}, {548, 16836099},
817
  {549, 1}, {550, 16836355}, {551, 1}, {552, 16836611},
818
  {553, 1}, {554, 16836867}, {555, 1}, {556, 16837123},
819
  {557, 1}, {558, 16837379}, {559, 1}, {560, 16837635},
820
  {561, 1}, {562, 16837891}, {563, 1}, {570, 16838147},
821
  {571, 16838403}, {572, 1}, {573, 16838659}, {574, 16838915},
822
  {575, 1}, {577, 16839171}, {578, 1}, {579, 16839427},
823
  {580, 16839683}, {581, 16839939}, {582, 16840195}, {583, 1},
824
  {584, 16840451}, {585, 1}, {586, 16840707}, {587, 1},
825
  {588, 16840963}, {589, 1}, {590, 16841219}, {591, 1},
826
  {688, 16779011}, {689, 16841475}, {690, 16779523}, {691, 16781571},
827
  {692, 16841731}, {693, 16841987}, {694, 16842243}, {695, 16782851},
828
  {696, 16783363}, {697, 1}, {728, 33619715}, {729, 33620227},
829
  {730, 33620739}, {731, 33621251}, {732, 33621763}, {733, 33622275},
830
  {734, 1}, {736, 16817411}, {737, 16780035}, {738, 16781827},
831
  {739, 16783107}, {740, 16845571}, {741, 1}, {832, 16845827},
832
  {833, 16785923}, {834, 1}, {835, 16846083}, {836, 33623555},
833
  {837, 16846851}, {838, 1}, {847, 0}, {848, 1},
834
  {880, 16847107}, {881, 1}, {882, 16847363}, {883, 1},
835
  {884, 16847619}, {885, 1}, {886, 16847875}, {887, 1},
836
  {888, 2}, {890, 33625347}, {891, 1}, {894, 16848643},
837
  {895, 16848899}, {896, 2}, {900, 33562883}, {901, 50403587},
838
  {902, 16849923}, {903, 16805379}, {904, 16850179}, {905, 16850435},
839
  {906, 16850691}, {907, 2}, {908, 16850947}, {909, 2},
840
  {910, 16851203}, {911, 16851459}, {912, 1}, {913, 16851715},
841
  {914, 16851971}, {915, 16852227}, {916, 16852483}, {917, 16852739},
842
  {918, 16852995}, {919, 16853251}, {920, 16853507}, {921, 16846851},
843
  {922, 16853763}, {923, 16854019}, {924, 16786179}, {925, 16854275},
844
  {926, 16854531}, {927, 16854787}, {928, 16855043}, {929, 16855299},
845
  {930, 2}, {931, 16855555}, {932, 16855811}, {933, 16856067},
846
  {934, 16856323}, {935, 16856579}, {936, 16856835}, {937, 16857091},
847
  {938, 16857347}, {939, 16857603}, {940, 1}, {975, 16857859},
848
  {976, 16851971}, {977, 16853507}, {978, 16856067}, {979, 16851203},
849
  {980, 16857603}, {981, 16856323}, {982, 16855043}, {983, 1},
850
  {984, 16858115}, {985, 1}, {986, 16858371}, {987, 1},
851
  {988, 16858627}, {989, 1}, {990, 16858883}, {991, 1},
852
  {992, 16859139}, {993, 1}, {994, 16859395}, {995, 1},
853
  {996, 16859651}, {997, 1}, {998, 16859907}, {999, 1},
854
  {1000, 16860163}, {1001, 1}, {1002, 16860419}, {1003, 1},
855
  {1004, 16860675}, {1005, 1}, {1006, 16860931}, {1007, 1},
856
  {1008, 16853763}, {1009, 16855299}, {1010, 16855555}, {1011, 1},
857
  {1012, 16853507}, {1013, 16852739}, {1014, 1}, {1015, 16861187},
858
  {1016, 1}, {1017, 16855555}, {1018, 16861443}, {1019, 1},
859
  {1021, 16861699}, {1022, 16861955}, {1023, 16862211}, {1024, 16862467},
860
  {1025, 16862723}, {1026, 16862979}, {1027, 16863235}, {1028, 16863491},
861
  {1029, 16863747}, {1030, 16864003}, {1031, 16864259}, {1032, 16864515},
862
  {1033, 16864771}, {1034, 16865027}, {1035, 16865283}, {1036, 16865539},
863
  {1037, 16865795}, {1038, 16866051}, {1039, 16866307}, {1040, 16866563},
864
  {1041, 16866819}, {1042, 16867075}, {1043, 16867331}, {1044, 16867587},
865
  {1045, 16867843}, {1046, 16868099}, {1047, 16868355}, {1048, 16868611},
866
  {1049, 16868867}, {1050, 16869123}, {1051, 16869379}, {1052, 16869635},
867
  {1053, 16869891}, {1054, 16870147}, {1055, 16870403}, {1056, 16870659},
868
  {1057, 16870915}, {1058, 16871171}, {1059, 16871427}, {1060, 16871683},
869
  {1061, 16871939}, {1062, 16872195}, {1063, 16872451}, {1064, 16872707},
870
  {1065, 16872963}, {1066, 16873219}, {1067, 16873475}, {1068, 16873731},
871
  {1069, 16873987}, {1070, 16874243}, {1071, 16874499}, {1072, 1},
872
  {1120, 16874755}, {1121, 1}, {1122, 16875011}, {1123, 1},
873
  {1124, 16875267}, {1125, 1}, {1126, 16875523}, {1127, 1},
874
  {1128, 16875779}, {1129, 1}, {1130, 16876035}, {1131, 1},
875
  {1132, 16876291}, {1133, 1}, {1134, 16876547}, {1135, 1},
876
  {1136, 16876803}, {1137, 1}, {1138, 16877059}, {1139, 1},
877
  {1140, 16877315}, {1141, 1}, {1142, 16877571}, {1143, 1},
878
  {1144, 16877827}, {1145, 1}, {1146, 16878083}, {1147, 1},
879
  {1148, 16878339}, {1149, 1}, {1150, 16878595}, {1151, 1},
880
  {1152, 16878851}, {1153, 1}, {1162, 16879107}, {1163, 1},
881
  {1164, 16879363}, {1165, 1}, {1166, 16879619}, {1167, 1},
882
  {1168, 16879875}, {1169, 1}, {1170, 16880131}, {1171, 1},
883
  {1172, 16880387}, {1173, 1}, {1174, 16880643}, {1175, 1},
884
  {1176, 16880899}, {1177, 1}, {1178, 16881155}, {1179, 1},
885
  {1180, 16881411}, {1181, 1}, {1182, 16881667}, {1183, 1},
886
  {1184, 16881923}, {1185, 1}, {1186, 16882179}, {1187, 1},
887
  {1188, 16882435}, {1189, 1}, {1190, 16882691}, {1191, 1},
888
  {1192, 16882947}, {1193, 1}, {1194, 16883203}, {1195, 1},
889
  {1196, 16883459}, {1197, 1}, {1198, 16883715}, {1199, 1},
890
  {1200, 16883971}, {1201, 1}, {1202, 16884227}, {1203, 1},
891
  {1204, 16884483}, {1205, 1}, {1206, 16884739}, {1207, 1},
892
  {1208, 16884995}, {1209, 1}, {1210, 16885251}, {1211, 1},
893
  {1212, 16885507}, {1213, 1}, {1214, 16885763}, {1215, 1},
894
  {1216, 16886019}, {1217, 16886275}, {1218, 1}, {1219, 16886531},
895
  {1220, 1}, {1221, 16886787}, {1222, 1}, {1223, 16887043},
896
  {1224, 1}, {1225, 16887299}, {1226, 1}, {1227, 16887555},
897
  {1228, 1}, {1229, 16887811}, {1230, 1}, {1232, 16888067},
898
  {1233, 1}, {1234, 16888323}, {1235, 1}, {1236, 16888579},
899
  {1237, 1}, {1238, 16888835}, {1239, 1}, {1240, 16889091},
900
  {1241, 1}, {1242, 16889347}, {1243, 1}, {1244, 16889603},
901
  {1245, 1}, {1246, 16889859}, {1247, 1}, {1248, 16890115},
902
  {1249, 1}, {1250, 16890371}, {1251, 1}, {1252, 16890627},
903
  {1253, 1}, {1254, 16890883}, {1255, 1}, {1256, 16891139},
904
  {1257, 1}, {1258, 16891395}, {1259, 1}, {1260, 16891651},
905
  {1261, 1}, {1262, 16891907}, {1263, 1}, {1264, 16892163},
906
  {1265, 1}, {1266, 16892419}, {1267, 1}, {1268, 16892675},
907
  {1269, 1}, {1270, 16892931}, {1271, 1}, {1272, 16893187},
908
  {1273, 1}, {1274, 16893443}, {1275, 1}, {1276, 16893699},
909
  {1277, 1}, {1278, 16893955}, {1279, 1}, {1280, 16894211},
910
  {1281, 1}, {1282, 16894467}, {1283, 1}, {1284, 16894723},
911
  {1285, 1}, {1286, 16894979}, {1287, 1}, {1288, 16895235},
912
  {1289, 1}, {1290, 16895491}, {1291, 1}, {1292, 16895747},
913
  {1293, 1}, {1294, 16896003}, {1295, 1}, {1296, 16896259},
914
  {1297, 1}, {1298, 16896515}, {1299, 1}, {1300, 16896771},
915
  {1301, 1}, {1302, 16897027}, {1303, 1}, {1304, 16897283},
916
  {1305, 1}, {1306, 16897539}, {1307, 1}, {1308, 16897795},
917
  {1309, 1}, {1310, 16898051}, {1311, 1}, {1312, 16898307},
918
  {1313, 1}, {1314, 16898563}, {1315, 1}, {1316, 16898819},
919
  {1317, 1}, {1318, 16899075}, {1319, 1}, {1320, 16899331},
920
  {1321, 1}, {1322, 16899587}, {1323, 1}, {1324, 16899843},
921
  {1325, 1}, {1326, 16900099}, {1327, 1}, {1328, 2},
922
  {1329, 16900355}, {1330, 16900611}, {1331, 16900867}, {1332, 16901123},
923
  {1333, 16901379}, {1334, 16901635}, {1335, 16901891}, {1336, 16902147},
924
  {1337, 16902403}, {1338, 16902659}, {1339, 16902915}, {1340, 16903171},
925
  {1341, 16903427}, {1342, 16903683}, {1343, 16903939}, {1344, 16904195},
926
  {1345, 16904451}, {1346, 16904707}, {1347, 16904963}, {1348, 16905219},
927
  {1349, 16905475}, {1350, 16905731}, {1351, 16905987}, {1352, 16906243},
928
  {1353, 16906499}, {1354, 16906755}, {1355, 16907011}, {1356, 16907267},
929
  {1357, 16907523}, {1358, 16907779}, {1359, 16908035}, {1360, 16908291},
930
  {1361, 16908547}, {1362, 16908803}, {1363, 16909059}, {1364, 16909315},
931
  {1365, 16909571}, {1366, 16909827}, {1367, 2}, {1369, 1},
932
  {1415, 33687299}, {1416, 1}, {1419, 2}, {1421, 1},
933
  {1424, 2}, {1425, 1}, {1480, 2}, {1488, 1},
934
  {1515, 2}, {1519, 1}, {1525, 2}, {1542, 1},
935
  {1564, 2}, {1565, 1}, {1653, 33687811}, {1654, 33688323},
936
  {1655, 33688835}, {1656, 33689347}, {1657, 1}, {1757, 2},
937
  {1758, 1}, {1806, 2}, {1808, 1}, {1867, 2},
938
  {1869, 1}, {1970, 2}, {1984, 1}, {2043, 2},
939
  {2045, 1}, {2094, 2}, {2096, 1}, {2111, 2},
940
  {2112, 1}, {2140, 2}, {2142, 1}, {2143, 2},
941
  {2144, 1}, {2155, 2}, {2160, 1}, {2191, 2},
942
  {2199, 1}, {2274, 2}, {2275, 1}, {2392, 33689859},
943
  {2393, 33690371}, {2394, 33690883}, {2395, 33691395}, {2396, 33691907},
944
  {2397, 33692419}, {2398, 33692931}, {2399, 33693443}, {2400, 1},
945
  {2436, 2}, {2437, 1}, {2445, 2}, {2447, 1},
946
  {2449, 2}, {2451, 1}, {2473, 2}, {2474, 1},
947
  {2481, 2}, {2482, 1}, {2483, 2}, {2486, 1},
948
  {2490, 2}, {2492, 1}, {2501, 2}, {2503, 1},
949
  {2505, 2}, {2507, 1}, {2511, 2}, {2519, 1},
950
  {2520, 2}, {2524, 33693955}, {2525, 33694467}, {2526, 2},
951
  {2527, 33694979}, {2528, 1}, {2532, 2}, {2534, 1},
952
  {2559, 2}, {2561, 1}, {2564, 2}, {2565, 1},
953
  {2571, 2}, {2575, 1}, {2577, 2}, {2579, 1},
954
  {2601, 2}, {2602, 1}, {2609, 2}, {2610, 1},
955
  {2611, 33695491}, {2612, 2}, {2613, 1}, {2614, 33696003},
956
  {2615, 2}, {2616, 1}, {2618, 2}, {2620, 1},
957
  {2621, 2}, {2622, 1}, {2627, 2}, {2631, 1},
958
  {2633, 2}, {2635, 1}, {2638, 2}, {2641, 1},
959
  {2642, 2}, {2649, 33696515}, {2650, 33697027}, {2651, 33697539},
960
  {2652, 1}, {2653, 2}, {2654, 33698051}, {2655, 2},
961
  {2662, 1}, {2679, 2}, {2689, 1}, {2692, 2},
962
  {2693, 1}, {2702, 2}, {2703, 1}, {2706, 2},
963
  {2707, 1}, {2729, 2}, {2730, 1}, {2737, 2},
964
  {2738, 1}, {2740, 2}, {2741, 1}, {2746, 2},
965
  {2748, 1}, {2758, 2}, {2759, 1}, {2762, 2},
966
  {2763, 1}, {2766, 2}, {2768, 1}, {2769, 2},
967
  {2784, 1}, {2788, 2}, {2790, 1}, {2802, 2},
968
  {2809, 1}, {2816, 2}, {2817, 1}, {2820, 2},
969
  {2821, 1}, {2829, 2}, {2831, 1}, {2833, 2},
970
  {2835, 1}, {2857, 2}, {2858, 1}, {2865, 2},
971
  {2866, 1}, {2868, 2}, {2869, 1}, {2874, 2},
972
  {2876, 1}, {2885, 2}, {2887, 1}, {2889, 2},
973
  {2891, 1}, {2894, 2}, {2901, 1}, {2904, 2},
974
  {2908, 33698563}, {2909, 33699075}, {2910, 2}, {2911, 1},
975
  {2916, 2}, {2918, 1}, {2936, 2}, {2946, 1},
976
  {2948, 2}, {2949, 1}, {2955, 2}, {2958, 1},
977
  {2961, 2}, {2962, 1}, {2966, 2}, {2969, 1},
978
  {2971, 2}, {2972, 1}, {2973, 2}, {2974, 1},
979
  {2976, 2}, {2979, 1}, {2981, 2}, {2984, 1},
980
  {2987, 2}, {2990, 1}, {3002, 2}, {3006, 1},
981
  {3011, 2}, {3014, 1}, {3017, 2}, {3018, 1},
982
  {3022, 2}, {3024, 1}, {3025, 2}, {3031, 1},
983
  {3032, 2}, {3046, 1}, {3067, 2}, {3072, 1},
984
  {3085, 2}, {3086, 1}, {3089, 2}, {3090, 1},
985
  {3113, 2}, {3114, 1}, {3130, 2}, {3132, 1},
986
  {3141, 2}, {3142, 1}, {3145, 2}, {3146, 1},
987
  {3150, 2}, {3157, 1}, {3159, 2}, {3160, 1},
988
  {3163, 2}, {3165, 1}, {3166, 2}, {3168, 1},
989
  {3172, 2}, {3174, 1}, {3184, 2}, {3191, 1},
990
  {3213, 2}, {3214, 1}, {3217, 2}, {3218, 1},
991
  {3241, 2}, {3242, 1}, {3252, 2}, {3253, 1},
992
  {3258, 2}, {3260, 1}, {3269, 2}, {3270, 1},
993
  {3273, 2}, {3274, 1}, {3278, 2}, {3285, 1},
994
  {3287, 2}, {3293, 1}, {3295, 2}, {3296, 1},
995
  {3300, 2}, {3302, 1}, {3312, 2}, {3313, 1},
996
  {3316, 2}, {3328, 1}, {3341, 2}, {3342, 1},
997
  {3345, 2}, {3346, 1}, {3397, 2}, {3398, 1},
998
  {3401, 2}, {3402, 1}, {3408, 2}, {3412, 1},
999
  {3428, 2}, {3430, 1}, {3456, 2}, {3457, 1},
1000
  {3460, 2}, {3461, 1}, {3479, 2}, {3482, 1},
1001
  {3506, 2}, {3507, 1}, {3516, 2}, {3517, 1},
1002
  {3518, 2}, {3520, 1}, {3527, 2}, {3530, 1},
1003
  {3531, 2}, {3535, 1}, {3541, 2}, {3542, 1},
1004
  {3543, 2}, {3544, 1}, {3552, 2}, {3558, 1},
1005
  {3568, 2}, {3570, 1}, {3573, 2}, {3585, 1},
1006
  {3635, 33699587}, {3636, 1}, {3643, 2}, {3647, 1},
1007
  {3676, 2}, {3713, 1}, {3715, 2}, {3716, 1},
1008
  {3717, 2}, {3718, 1}, {3723, 2}, {3724, 1},
1009
  {3748, 2}, {3749, 1}, {3750, 2}, {3751, 1},
1010
  {3763, 33700099}, {3764, 1}, {3774, 2}, {3776, 1},
1011
  {3781, 2}, {3782, 1}, {3783, 2}, {3784, 1},
1012
  {3791, 2}, {3792, 1}, {3802, 2}, {3804, 33700611},
1013
  {3805, 33701123}, {3806, 1}, {3808, 2}, {3840, 1},
1014
  {3852, 16924419}, {3853, 1}, {3907, 33701891}, {3908, 1},
1015
  {3912, 2}, {3913, 1}, {3917, 33702403}, {3918, 1},
1016
  {3922, 33702915}, {3923, 1}, {3927, 33703427}, {3928, 1},
1017
  {3932, 33703939}, {3933, 1}, {3945, 33704451}, {3946, 1},
1018
  {3949, 2}, {3953, 1}, {3955, 33704963}, {3956, 1},
1019
  {3957, 33705475}, {3958, 33705987}, {3959, 50483715}, {3960, 33707267},
1020
  {3961, 50484995}, {3962, 1}, {3969, 33706755}, {3970, 1},
1021
  {3987, 33708547}, {3988, 1}, {3992, 2}, {3993, 1},
1022
  {3997, 33709059}, {3998, 1}, {4002, 33709571}, {4003, 1},
1023
  {4007, 33710083}, {4008, 1}, {4012, 33710595}, {4013, 1},
1024
  {4025, 33711107}, {4026, 1}, {4029, 2}, {4030, 1},
1025
  {4045, 2}, {4046, 1}, {4059, 2}, {4096, 1},
1026
  {4256, 16934403}, {4257, 16934659}, {4258, 16934915}, {4259, 16935171},
1027
  {4260, 16935427}, {4261, 16935683}, {4262, 16935939}, {4263, 16936195},
1028
  {4264, 16936451}, {4265, 16936707}, {4266, 16936963}, {4267, 16937219},
1029
  {4268, 16937475}, {4269, 16937731}, {4270, 16937987}, {4271, 16938243},
1030
  {4272, 16938499}, {4273, 16938755}, {4274, 16939011}, {4275, 16939267},
1031
  {4276, 16939523}, {4277, 16939779}, {4278, 16940035}, {4279, 16940291},
1032
  {4280, 16940547}, {4281, 16940803}, {4282, 16941059}, {4283, 16941315},
1033
  {4284, 16941571}, {4285, 16941827}, {4286, 16942083}, {4287, 16942339},
1034
  {4288, 16942595}, {4289, 16942851}, {4290, 16943107}, {4291, 16943363},
1035
  {4292, 16943619}, {4293, 16943875}, {4294, 2}, {4295, 16944131},
1036
  {4296, 2}, {4301, 16944387}, {4302, 2}, {4304, 1},
1037
  {4348, 16944643}, {4349, 1}, {4447, 0}, {4449, 1},
1038
  {4681, 2}, {4682, 1}, {4686, 2}, {4688, 1},
1039
  {4695, 2}, {4696, 1}, {4697, 2}, {4698, 1},
1040
  {4702, 2}, {4704, 1}, {4745, 2}, {4746, 1},
1041
  {4750, 2}, {4752, 1}, {4785, 2}, {4786, 1},
1042
  {4790, 2}, {4792, 1}, {4799, 2}, {4800, 1},
1043
  {4801, 2}, {4802, 1}, {4806, 2}, {4808, 1},
1044
  {4823, 2}, {4824, 1}, {4881, 2}, {4882, 1},
1045
  {4886, 2}, {4888, 1}, {4955, 2}, {4957, 1},
1046
  {4989, 2}, {4992, 1}, {5018, 2}, {5024, 1},
1047
  {5110, 2}, {5112, 16944899}, {5113, 16945155}, {5114, 16945411},
1048
  {5115, 16945667}, {5116, 16945923}, {5117, 16946179}, {5118, 2},
1049
  {5120, 1}, {5760, 2}, {5761, 1}, {5789, 2},
1050
  {5792, 1}, {5881, 2}, {5888, 1}, {5910, 2},
1051
  {5919, 1}, {5943, 2}, {5952, 1}, {5972, 2},
1052
  {5984, 1}, {5997, 2}, {5998, 1}, {6001, 2},
1053
  {6002, 1}, {6004, 2}, {6016, 1}, {6068, 0},
1054
  {6070, 1}, {6110, 2}, {6112, 1}, {6122, 2},
1055
  {6128, 1}, {6138, 2}, {6144, 1}, {6155, 0},
1056
  {6160, 1}, {6170, 2}, {6176, 1}, {6265, 2},
1057
  {6272, 1}, {6315, 2}, {6320, 1}, {6390, 2},
1058
  {6400, 1}, {6431, 2}, {6432, 1}, {6444, 2},
1059
  {6448, 1}, {6460, 2}, {6464, 1}, {6465, 2},
1060
  {6468, 1}, {6510, 2}, {6512, 1}, {6517, 2},
1061
  {6528, 1}, {6572, 2}, {6576, 1}, {6602, 2},
1062
  {6608, 1}, {6619, 2}, {6622, 1}, {6684, 2},
1063
  {6686, 1}, {6751, 2}, {6752, 1}, {6781, 2},
1064
  {6783, 1}, {6794, 2}, {6800, 1}, {6810, 2},
1065
  {6816, 1}, {6830, 2}, {6832, 1}, {6863, 2},
1066
  {6912, 1}, {6989, 2}, {6990, 1}, {7156, 2},
1067
  {7164, 1}, {7224, 2}, {7227, 1}, {7242, 2},
1068
  {7245, 1}, {7296, 16867075}, {7297, 16867587}, {7298, 16870147},
1069
  {7299, 16870915}, {7300, 16871171}, {7302, 16873219}, {7303, 16875011},
1070
  {7304, 16946435}, {7305, 16946691}, {7306, 1}, {7307, 2},
1071
  {7312, 16946947}, {7313, 16947203}, {7314, 16947459}, {7315, 16947715},
1072
  {7316, 16947971}, {7317, 16948227}, {7318, 16948483}, {7319, 16948739},
1073
  {7320, 16948995}, {7321, 16949251}, {7322, 16949507}, {7323, 16949763},
1074
  {7324, 16944643}, {7325, 16950019}, {7326, 16950275}, {7327, 16950531},
1075
  {7328, 16950787}, {7329, 16951043}, {7330, 16951299}, {7331, 16951555},
1076
  {7332, 16951811}, {7333, 16952067}, {7334, 16952323}, {7335, 16952579},
1077
  {7336, 16952835}, {7337, 16953091}, {7338, 16953347}, {7339, 16953603},
1078
  {7340, 16953859}, {7341, 16954115}, {7342, 16954371}, {7343, 16954627},
1079
  {7344, 16954883}, {7345, 16955139}, {7346, 16955395}, {7347, 16955651},
1080
  {7348, 16955907}, {7349, 16956163}, {7350, 16956419}, {7351, 16956675},
1081
  {7352, 16956931}, {7353, 16957187}, {7354, 16957443}, {7355, 2},
1082
  {7357, 16957699}, {7358, 16957955}, {7359, 16958211}, {7360, 1},
1083
  {7368, 2}, {7376, 1}, {7419, 2}, {7424, 1},
1084
  {7468, 16777219}, {7469, 16791043}, {7470, 16777475}, {7471, 1},
1085
  {7472, 16777987}, {7473, 16778243}, {7474, 16816131}, {7475, 16778755},
1086
  {7476, 16779011}, {7477, 16779267}, {7478, 16779523}, {7479, 16779779},
1087
  {7480, 16780035}, {7481, 16780291}, {7482, 16780547}, {7483, 1},
1088
  {7484, 16780803}, {7485, 16835843}, {7486, 16781059}, {7487, 16781571},
1089
  {7488, 16782083}, {7489, 16782339}, {7490, 16782851}, {7491, 16777219},
1090
  {7492, 16958467}, {7493, 16958723}, {7494, 16958979}, {7495, 16777475},
1091
  {7496, 16777987}, {7497, 16778243}, {7498, 16816387}, {7499, 16816643},
1092
  {7500, 16959235}, {7501, 16778755}, {7502, 1}, {7503, 16779779},
1093
  {7504, 16780291}, {7505, 16807171}, {7506, 16780803}, {7507, 16814851},
1094
  {7508, 16959491}, {7509, 16959747}, {7510, 16781059}, {7511, 16782083},
1095
  {7512, 16782339}, {7513, 16960003}, {7514, 16818435}, {7515, 16782595},
1096
  {7516, 16960259}, {7517, 16851971}, {7518, 16852227}, {7519, 16852483},
1097
  {7520, 16856323}, {7521, 16856579}, {7522, 16779267}, {7523, 16781571},
1098
  {7524, 16782339}, {7525, 16782595}, {7526, 16851971}, {7527, 16852227},
1099
  {7528, 16855299}, {7529, 16856323}, {7530, 16856579}, {7531, 1},
1100
  {7544, 16869891}, {7545, 1}, {7579, 16960515}, {7580, 16777731},
1101
  {7581, 16960771}, {7582, 16793603}, {7583, 16959235}, {7584, 16778499},
1102
  {7585, 16961027}, {7586, 16961283}, {7587, 16961539}, {7588, 16817923},
1103
  {7589, 16817667}, {7590, 16961795}, {7591, 16962051}, {7592, 16962307},
1104
  {7593, 16962563}, {7594, 16962819}, {7595, 16963075}, {7596, 16963331},
1105
  {7597, 16963587}, {7598, 16818691}, {7599, 16963843}, {7600, 16964099},
1106
  {7601, 16818947}, {7602, 16964355}, {7603, 16964611}, {7604, 16820483},
1107
  {7605, 16964867}, {7606, 16839683}, {7607, 16821507}, {7608, 16965123},
1108
  {7609, 16821763}, {7610, 16839939}, {7611, 16783619}, {7612, 16965379},
1109
  {7613, 16965635}, {7614, 16822531}, {7615, 16853507}, {7616, 1},
1110
  {7680, 16965891}, {7681, 1}, {7682, 16966147}, {7683, 1},
1111
  {7684, 16966403}, {7685, 1}, {7686, 16966659}, {7687, 1},
1112
  {7688, 16966915}, {7689, 1}, {7690, 16967171}, {7691, 1},
1113
  {7692, 16967427}, {7693, 1}, {7694, 16967683}, {7695, 1},
1114
  {7696, 16967939}, {7697, 1}, {7698, 16968195}, {7699, 1},
1115
  {7700, 16968451}, {7701, 1}, {7702, 16968707}, {7703, 1},
1116
  {7704, 16968963}, {7705, 1}, {7706, 16969219}, {7707, 1},
1117
  {7708, 16969475}, {7709, 1}, {7710, 16969731}, {7711, 1},
1118
  {7712, 16969987}, {7713, 1}, {7714, 16970243}, {7715, 1},
1119
  {7716, 16970499}, {7717, 1}, {7718, 16970755}, {7719, 1},
1120
  {7720, 16971011}, {7721, 1}, {7722, 16971267}, {7723, 1},
1121
  {7724, 16971523}, {7725, 1}, {7726, 16971779}, {7727, 1},
1122
  {7728, 16972035}, {7729, 1}, {7730, 16972291}, {7731, 1},
1123
  {7732, 16972547}, {7733, 1}, {7734, 16972803}, {7735, 1},
1124
  {7736, 16973059}, {7737, 1}, {7738, 16973315}, {7739, 1},
1125
  {7740, 16973571}, {7741, 1}, {7742, 16973827}, {7743, 1},
1126
  {7744, 16974083}, {7745, 1}, {7746, 16974339}, {7747, 1},
1127
  {7748, 16974595}, {7749, 1}, {7750, 16974851}, {7751, 1},
1128
  {7752, 16975107}, {7753, 1}, {7754, 16975363}, {7755, 1},
1129
  {7756, 16975619}, {7757, 1}, {7758, 16975875}, {7759, 1},
1130
  {7760, 16976131}, {7761, 1}, {7762, 16976387}, {7763, 1},
1131
  {7764, 16976643}, {7765, 1}, {7766, 16976899}, {7767, 1},
1132
  {7768, 16977155}, {7769, 1}, {7770, 16977411}, {7771, 1},
1133
  {7772, 16977667}, {7773, 1}, {7774, 16977923}, {7775, 1},
1134
  {7776, 16978179}, {7777, 1}, {7778, 16978435}, {7779, 1},
1135
  {7780, 16978691}, {7781, 1}, {7782, 16978947}, {7783, 1},
1136
  {7784, 16979203}, {7785, 1}, {7786, 16979459}, {7787, 1},
1137
  {7788, 16979715}, {7789, 1}, {7790, 16979971}, {7791, 1},
1138
  {7792, 16980227}, {7793, 1}, {7794, 16980483}, {7795, 1},
1139
  {7796, 16980739}, {7797, 1}, {7798, 16980995}, {7799, 1},
1140
  {7800, 16981251}, {7801, 1}, {7802, 16981507}, {7803, 1},
1141
  {7804, 16981763}, {7805, 1}, {7806, 16982019}, {7807, 1},
1142
  {7808, 16982275}, {7809, 1}, {7810, 16982531}, {7811, 1},
1143
  {7812, 16982787}, {7813, 1}, {7814, 16983043}, {7815, 1},
1144
  {7816, 16983299}, {7817, 1}, {7818, 16983555}, {7819, 1},
1145
  {7820, 16983811}, {7821, 1}, {7822, 16984067}, {7823, 1},
1146
  {7824, 16984323}, {7825, 1}, {7826, 16984579}, {7827, 1},
1147
  {7828, 16984835}, {7829, 1}, {7834, 33762307}, {7835, 16978179},
1148
  {7836, 1}, {7838, 16985603}, {7839, 1}, {7840, 16985859},
1149
  {7841, 1}, {7842, 16986115}, {7843, 1}, {7844, 16986371},
1150
  {7845, 1}, {7846, 16986627}, {7847, 1}, {7848, 16986883},
1151
  {7849, 1}, {7850, 16987139}, {7851, 1}, {7852, 16987395},
1152
  {7853, 1}, {7854, 16987651}, {7855, 1}, {7856, 16987907},
1153
  {7857, 1}, {7858, 16988163}, {7859, 1}, {7860, 16988419},
1154
  {7861, 1}, {7862, 16988675}, {7863, 1}, {7864, 16988931},
1155
  {7865, 1}, {7866, 16989187}, {7867, 1}, {7868, 16989443},
1156
  {7869, 1}, {7870, 16989699}, {7871, 1}, {7872, 16989955},
1157
  {7873, 1}, {7874, 16990211}, {7875, 1}, {7876, 16990467},
1158
  {7877, 1}, {7878, 16990723}, {7879, 1}, {7880, 16990979},
1159
  {7881, 1}, {7882, 16991235}, {7883, 1}, {7884, 16991491},
1160
  {7885, 1}, {7886, 16991747}, {7887, 1}, {7888, 16992003},
1161
  {7889, 1}, {7890, 16992259}, {7891, 1}, {7892, 16992515},
1162
  {7893, 1}, {7894, 16992771}, {7895, 1}, {7896, 16993027},
1163
  {7897, 1}, {7898, 16993283}, {7899, 1}, {7900, 16993539},
1164
  {7901, 1}, {7902, 16993795}, {7903, 1}, {7904, 16994051},
1165
  {7905, 1}, {7906, 16994307}, {7907, 1}, {7908, 16994563},
1166
  {7909, 1}, {7910, 16994819}, {7911, 1}, {7912, 16995075},
1167
  {7913, 1}, {7914, 16995331}, {7915, 1}, {7916, 16995587},
1168
  {7917, 1}, {7918, 16995843}, {7919, 1}, {7920, 16996099},
1169
  {7921, 1}, {7922, 16996355}, {7923, 1}, {7924, 16996611},
1170
  {7925, 1}, {7926, 16996867}, {7927, 1}, {7928, 16997123},
1171
  {7929, 1}, {7930, 16997379}, {7931, 1}, {7932, 16997635},
1172
  {7933, 1}, {7934, 16997891}, {7935, 1}, {7944, 16998147},
1173
  {7945, 16998403}, {7946, 16998659}, {7947, 16998915}, {7948, 16999171},
1174
  {7949, 16999427}, {7950, 16999683}, {7951, 16999939}, {7952, 1},
1175
  {7958, 2}, {7960, 17000195}, {7961, 17000451}, {7962, 17000707},
1176
  {7963, 17000963}, {7964, 17001219}, {7965, 17001475}, {7966, 2},
1177
  {7968, 1}, {7976, 17001731}, {7977, 17001987}, {7978, 17002243},
1178
  {7979, 17002499}, {7980, 17002755}, {7981, 17003011}, {7982, 17003267},
1179
  {7983, 17003523}, {7984, 1}, {7992, 17003779}, {7993, 17004035},
1180
  {7994, 17004291}, {7995, 17004547}, {7996, 17004803}, {7997, 17005059},
1181
  {7998, 17005315}, {7999, 17005571}, {8000, 1}, {8006, 2},
1182
  {8008, 17005827}, {8009, 17006083}, {8010, 17006339}, {8011, 17006595},
1183
  {8012, 17006851}, {8013, 17007107}, {8014, 2}, {8016, 1},
1184
  {8024, 2}, {8025, 17007363}, {8026, 2}, {8027, 17007619},
1185
  {8028, 2}, {8029, 17007875}, {8030, 2}, {8031, 17008131},
1186
  {8032, 1}, {8040, 17008387}, {8041, 17008643}, {8042, 17008899},
1187
  {8043, 17009155}, {8044, 17009411}, {8045, 17009667}, {8046, 17009923},
1188
  {8047, 17010179}, {8048, 1}, {8049, 16849923}, {8050, 1},
1189
  {8051, 16850179}, {8052, 1}, {8053, 16850435}, {8054, 1},
1190
  {8055, 16850691}, {8056, 1}, {8057, 16850947}, {8058, 1},
1191
  {8059, 16851203}, {8060, 1}, {8061, 16851459}, {8062, 2},
1192
  {8064, 33787651}, {8065, 33788163}, {8066, 33788675}, {8067, 33789187},
1193
  {8068, 33789699}, {8069, 33790211}, {8070, 33790723}, {8071, 33791235},
1194
  {8072, 33787651}, {8073, 33788163}, {8074, 33788675}, {8075, 33789187},
1195
  {8076, 33789699}, {8077, 33790211}, {8078, 33790723}, {8079, 33791235},
1196
  {8080, 33791747}, {8081, 33792259}, {8082, 33792771}, {8083, 33793283},
1197
  {8084, 33793795}, {8085, 33794307}, {8086, 33794819}, {8087, 33795331},
1198
  {8088, 33791747}, {8089, 33792259}, {8090, 33792771}, {8091, 33793283},
1199
  {8092, 33793795}, {8093, 33794307}, {8094, 33794819}, {8095, 33795331},
1200
  {8096, 33795843}, {8097, 33796355}, {8098, 33796867}, {8099, 33797379},
1201
  {8100, 33797891}, {8101, 33798403}, {8102, 33798915}, {8103, 33799427},
1202
  {8104, 33795843}, {8105, 33796355}, {8106, 33796867}, {8107, 33797379},
1203
  {8108, 33797891}, {8109, 33798403}, {8110, 33798915}, {8111, 33799427},
1204
  {8112, 1}, {8114, 33799939}, {8115, 33800451}, {8116, 33800963},
1205
  {8117, 2}, {8118, 1}, {8119, 33801475}, {8120, 17024771},
1206
  {8121, 17025027}, {8122, 17022723}, {8123, 16849923}, {8124, 33800451},
1207
  {8125, 33802499}, {8126, 16846851}, {8127, 33802499}, {8128, 33803011},
1208
  {8129, 50580739}, {8130, 33804291}, {8131, 33804803}, {8132, 33805315},
1209
  {8133, 2}, {8134, 1}, {8135, 33805827}, {8136, 17029123},
1210
  {8137, 16850179}, {8138, 17027075}, {8139, 16850435}, {8140, 33804803},
1211
  {8141, 50583811}, {8142, 50584579}, {8143, 50585347}, {8144, 1},
1212
  {8147, 17031683}, {8148, 2}, {8150, 1}, {8152, 17031939},
1213
  {8153, 17032195}, {8154, 17032451}, {8155, 16850691}, {8156, 2},
1214
  {8157, 50587139}, {8158, 50587907}, {8159, 50588675}, {8160, 1},
1215
  {8163, 17035011}, {8164, 1}, {8168, 17035267}, {8169, 17035523},
1216
  {8170, 17035779}, {8171, 16851203}, {8172, 17036035}, {8173, 50590723},
1217
  {8174, 50403587}, {8175, 17037059}, {8176, 2}, {8178, 33814531},
1218
  {8179, 33815043}, {8180, 33815555}, {8181, 2}, {8182, 1},
1219
  {8183, 33816067}, {8184, 17039363}, {8185, 16850947}, {8186, 17037315},
1220
  {8187, 16851459}, {8188, 33815043}, {8189, 33562883}, {8190, 33809923},
1221
  {8191, 2}, {8192, 16783875}, {8203, 0}, {8204, 1},
1222
  {8206, 2}, {8208, 1}, {8209, 17039619}, {8210, 1},
1223
  {8215, 33817091}, {8216, 1}, {8228, 2}, {8231, 1},
1224
  {8232, 2}, {8239, 16783875}, {8240, 1}, {8243, 33817603},
1225
  {8244, 50595331}, {8245, 1}, {8246, 33818883}, {8247, 50596611},
1226
  {8248, 1}, {8252, 33820163}, {8253, 1}, {8254, 33820675},
1227
  {8255, 1}, {8263, 33821187}, {8264, 33821699}, {8265, 33822211},
1228
  {8266, 1}, {8279, 67372035}, {8280, 1}, {8287, 16783875},
1229
  {8288, 0}, {8293, 2}, {8298, 0}, {8304, 17045507},
1230
  {8305, 16779267}, {8306, 2}, {8308, 16787715}, {8309, 17045763},
1231
  {8310, 17046019}, {8311, 17046275}, {8312, 17046531}, {8313, 17046787},
1232
  {8314, 17047043}, {8315, 17047299}, {8316, 17047555}, {8317, 17047811},
1233
  {8318, 17048067}, {8319, 16780547}, {8320, 17045507}, {8321, 16786947},
1234
  {8322, 16785155}, {8323, 16785411}, {8324, 16787715}, {8325, 17045763},
1235
  {8326, 17046019}, {8327, 17046275}, {8328, 17046531}, {8329, 17046787},
1236
  {8330, 17047043}, {8331, 17047299}, {8332, 17047555}, {8333, 17047811},
1237
  {8334, 17048067}, {8335, 2}, {8336, 16777219}, {8337, 16778243},
1238
  {8338, 16780803}, {8339, 16783107}, {8340, 16816387}, {8341, 16779011},
1239
  {8342, 16779779}, {8343, 16780035}, {8344, 16780291}, {8345, 16780547},
1240
  {8346, 16781059}, {8347, 16781827}, {8348, 16782083}, {8349, 2},
1241
  {8352, 1}, {8360, 33558787}, {8361, 1}, {8385, 2},
1242
  {8400, 1}, {8433, 2}, {8448, 50602755}, {8449, 50603523},
1243
  {8450, 16777731}, {8451, 33827075}, {8452, 1}, {8453, 50604803},
1244
  {8454, 50605571}, {8455, 16816643}, {8456, 1}, {8457, 33829123},
1245
  {8458, 16778755}, {8459, 16779011}, {8463, 16802051}, {8464, 16779267},
1246
  {8466, 16780035}, {8468, 1}, {8469, 16780547}, {8470, 33557763},
1247
  {8471, 1}, {8473, 16781059}, {8474, 16781315}, {8475, 16781571},
1248
  {8478, 1}, {8480, 33829635}, {8481, 50607363}, {8482, 33830915},
1249
  {8483, 1}, {8484, 16783619}, {8485, 1}, {8486, 16857091},
1250
  {8487, 1}, {8488, 16783619}, {8489, 1}, {8490, 16779779},
1251
  {8491, 16790787}, {8492, 16777475}, {8493, 16777731}, {8494, 1},
1252
  {8495, 16778243}, {8497, 16778499}, {8498, 17054211}, {8499, 16780291},
1253
  {8500, 16780803}, {8501, 17054467}, {8502, 17054723}, {8503, 17054979},
1254
  {8504, 17055235}, {8505, 16779267}, {8506, 1}, {8507, 50609923},
1255
  {8508, 16855043}, {8509, 16852227}, {8511, 16855043}, {8512, 17056259},
1256
  {8513, 1}, {8517, 16777987}, {8519, 16778243}, {8520, 16779267},
1257
  {8521, 16779523}, {8522, 1}, {8528, 50610947}, {8529, 50611715},
1258
  {8530, 67389699}, {8531, 50613507}, {8532, 50614275}, {8533, 50615043},
1259
  {8534, 50615811}, {8535, 50616579}, {8536, 50617347}, {8537, 50618115},
1260
  {8538, 50618883}, {8539, 50619651}, {8540, 50620419}, {8541, 50621187},
1261
  {8542, 50621955}, {8543, 33564419}, {8544, 16779267}, {8545, 33845507},
1262
  {8546, 50623235}, {8547, 33846787}, {8548, 16782595}, {8549, 33847299},
1263
  {8550, 50625027}, {8551, 67403011}, {8552, 33849603}, {8553, 16783107},
1264
  {8554, 33850115}, {8555, 50627843}, {8556, 16780035}, {8557, 16777731},
1265
  {8558, 16777987}, {8559, 16780291}, {8560, 16779267}, {8561, 33845507},
1266
  {8562, 50622723}, {8563, 33846787}, {8564, 16782595}, {8565, 33847299},
1267
  {8566, 50625027}, {8567, 67403011}, {8568, 33849603}, {8569, 16783107},
1268
  {8570, 33850115}, {8571, 50627843}, {8572, 16780035}, {8573, 16777731},
1269
  {8574, 16777987}, {8575, 16780291}, {8576, 1}, {8579, 17074179},
1270
  {8580, 1}, {8585, 50628867}, {8586, 1}, {8588, 2},
1271
  {8592, 1}, {8748, 33852419}, {8749, 50630147}, {8750, 1},
1272
  {8751, 33853699}, {8752, 50631427}, {8753, 1}, {9001, 17077763},
1273
  {9002, 17078019}, {9003, 1}, {9258, 2}, {9280, 1},
1274
  {9291, 2}, {9312, 16786947}, {9313, 16785155}, {9314, 16785411},
1275
  {9315, 16787715}, {9316, 17045763}, {9317, 17046019}, {9318, 17046275},
1276
  {9319, 17046531}, {9320, 17046787}, {9321, 33835779}, {9322, 33564163},
1277
  {9323, 33855491}, {9324, 33856003}, {9325, 33856515}, {9326, 33857027},
1278
  {9327, 33857539}, {9328, 33858051}, {9329, 33858563}, {9330, 33859075},
1279
  {9331, 33859587}, {9332, 50637315}, {9333, 50638083}, {9334, 50638851},
1280
  {9335, 50639619}, {9336, 50640387}, {9337, 50641155}, {9338, 50641923},
1281
  {9339, 50642691}, {9340, 50643459}, {9341, 67421443}, {9342, 67422467},
1282
  {9343, 67423491}, {9344, 67424515}, {9345, 67425539}, {9346, 67426563},
1283
  {9347, 67427587}, {9348, 67428611}, {9349, 67429635}, {9350, 67430659},
1284
  {9351, 67431683}, {9352, 2}, {9372, 50655491}, {9373, 50656259},
1285
  {9374, 50657027}, {9375, 50657795}, {9376, 50658563}, {9377, 50659331},
1286
  {9378, 50660099}, {9379, 50660867}, {9380, 50661635}, {9381, 50662403},
1287
  {9382, 50663171}, {9383, 50663939}, {9384, 50664707}, {9385, 50665475},
1288
  {9386, 50666243}, {9387, 50667011}, {9388, 50667779}, {9389, 50668547},
1289
  {9390, 50669315}, {9391, 50670083}, {9392, 50670851}, {9393, 50671619},
1290
  {9394, 50672387}, {9395, 50673155}, {9396, 50673923}, {9397, 50674691},
1291
  {9398, 16777219}, {9399, 16777475}, {9400, 16777731}, {9401, 16777987},
1292
  {9402, 16778243}, {9403, 16778499}, {9404, 16778755}, {9405, 16779011},
1293
  {9406, 16779267}, {9407, 16779523}, {9408, 16779779}, {9409, 16780035},
1294
  {9410, 16780291}, {9411, 16780547}, {9412, 16780803}, {9413, 16781059},
1295
  {9414, 16781315}, {9415, 16781571}, {9416, 16781827}, {9417, 16782083},
1296
  {9418, 16782339}, {9419, 16782595}, {9420, 16782851}, {9421, 16783107},
1297
  {9422, 16783363}, {9423, 16783619}, {9424, 16777219}, {9425, 16777475},
1298
  {9426, 16777731}, {9427, 16777987}, {9428, 16778243}, {9429, 16778499},
1299
  {9430, 16778755}, {9431, 16779011}, {9432, 16779267}, {9433, 16779523},
1300
  {9434, 16779779}, {9435, 16780035}, {9436, 16780291}, {9437, 16780547},
1301
  {9438, 16780803}, {9439, 16781059}, {9440, 16781315}, {9441, 16781571},
1302
  {9442, 16781827}, {9443, 16782083}, {9444, 16782339}, {9445, 16782595},
1303
  {9446, 16782851}, {9447, 16783107}, {9448, 16783363}, {9449, 16783619},
1304
  {9450, 17045507}, {9451, 1}, {10764, 67406851}, {10765, 1},
1305
  {10868, 50675459}, {10869, 33899011}, {10870, 50675971}, {10871, 1},
1306
  {10972, 33899523}, {10973, 1}, {11124, 2}, {11126, 1},
1307
  {11158, 2}, {11159, 1}, {11264, 17122819}, {11265, 17123075},
1308
  {11266, 17123331}, {11267, 17123587}, {11268, 17123843}, {11269, 17124099},
1309
  {11270, 17124355}, {11271, 17124611}, {11272, 17124867}, {11273, 17125123},
1310
  {11274, 17125379}, {11275, 17125635}, {11276, 17125891}, {11277, 17126147},
1311
  {11278, 17126403}, {11279, 17126659}, {11280, 17126915}, {11281, 17127171},
1312
  {11282, 17127427}, {11283, 17127683}, {11284, 17127939}, {11285, 17128195},
1313
  {11286, 17128451}, {11287, 17128707}, {11288, 17128963}, {11289, 17129219},
1314
  {11290, 17129475}, {11291, 17129731}, {11292, 17129987}, {11293, 17130243},
1315
  {11294, 17130499}, {11295, 17130755}, {11296, 17131011}, {11297, 17131267},
1316
  {11298, 17131523}, {11299, 17131779}, {11300, 17132035}, {11301, 17132291},
1317
  {11302, 17132547}, {11303, 17132803}, {11304, 17133059}, {11305, 17133315},
1318
  {11306, 17133571}, {11307, 17133827}, {11308, 17134083}, {11309, 17134339},
1319
  {11310, 17134595}, {11311, 17134851}, {11312, 1}, {11360, 17135107},
1320
  {11361, 1}, {11362, 17135363}, {11363, 17135619}, {11364, 17135875},
1321
  {11365, 1}, {11367, 17136131}, {11368, 1}, {11369, 17136387},
1322
  {11370, 1}, {11371, 17136643}, {11372, 1}, {11373, 16958723},
1323
  {11374, 16963331}, {11375, 16958467}, {11376, 16960515}, {11377, 1},
1324
  {11378, 17136899}, {11379, 1}, {11381, 17137155}, {11382, 1},
1325
  {11388, 16779523}, {11389, 16782595}, {11390, 17137411}, {11391, 17137667},
1326
  {11392, 17137923}, {11393, 1}, {11394, 17138179}, {11395, 1},
1327
  {11396, 17138435}, {11397, 1}, {11398, 17138691}, {11399, 1},
1328
  {11400, 17138947}, {11401, 1}, {11402, 17139203}, {11403, 1},
1329
  {11404, 17139459}, {11405, 1}, {11406, 17139715}, {11407, 1},
1330
  {11408, 17139971}, {11409, 1}, {11410, 17140227}, {11411, 1},
1331
  {11412, 17140483}, {11413, 1}, {11414, 17140739}, {11415, 1},
1332
  {11416, 17140995}, {11417, 1}, {11418, 17141251}, {11419, 1},
1333
  {11420, 17141507}, {11421, 1}, {11422, 17141763}, {11423, 1},
1334
  {11424, 17142019}, {11425, 1}, {11426, 17142275}, {11427, 1},
1335
  {11428, 17142531}, {11429, 1}, {11430, 17142787}, {11431, 1},
1336
  {11432, 17143043}, {11433, 1}, {11434, 17143299}, {11435, 1},
1337
  {11436, 17143555}, {11437, 1}, {11438, 17143811}, {11439, 1},
1338
  {11440, 17144067}, {11441, 1}, {11442, 17144323}, {11443, 1},
1339
  {11444, 17144579}, {11445, 1}, {11446, 17144835}, {11447, 1},
1340
  {11448, 17145091}, {11449, 1}, {11450, 17145347}, {11451, 1},
1341
  {11452, 17145603}, {11453, 1}, {11454, 17145859}, {11455, 1},
1342
  {11456, 17146115}, {11457, 1}, {11458, 17146371}, {11459, 1},
1343
  {11460, 17146627}, {11461, 1}, {11462, 17146883}, {11463, 1},
1344
  {11464, 17147139}, {11465, 1}, {11466, 17147395}, {11467, 1},
1345
  {11468, 17147651}, {11469, 1}, {11470, 17147907}, {11471, 1},
1346
  {11472, 17148163}, {11473, 1}, {11474, 17148419}, {11475, 1},
1347
  {11476, 17148675}, {11477, 1}, {11478, 17148931}, {11479, 1},
1348
  {11480, 17149187}, {11481, 1}, {11482, 17149443}, {11483, 1},
1349
  {11484, 17149699}, {11485, 1}, {11486, 17149955}, {11487, 1},
1350
  {11488, 17150211}, {11489, 1}, {11490, 17150467}, {11491, 1},
1351
  {11499, 17150723}, {11500, 1}, {11501, 17150979}, {11502, 1},
1352
  {11506, 17151235}, {11507, 1}, {11508, 2}, {11513, 1},
1353
  {11558, 2}, {11559, 1}, {11560, 2}, {11565, 1},
1354
  {11566, 2}, {11568, 1}, {11624, 2}, {11631, 17151491},
1355
  {11632, 1}, {11633, 2}, {11647, 1}, {11671, 2},
1356
  {11680, 1}, {11687, 2}, {11688, 1}, {11695, 2},
1357
  {11696, 1}, {11703, 2}, {11704, 1}, {11711, 2},
1358
  {11712, 1}, {11719, 2}, {11720, 1}, {11727, 2},
1359
  {11728, 1}, {11735, 2}, {11736, 1}, {11743, 2},
1360
  {11744, 1}, {11870, 2}, {11904, 1}, {11930, 2},
1361
  {11931, 1}, {11935, 17151747}, {11936, 1}, {12019, 17152003},
1362
  {12020, 2}, {12032, 17152259}, {12033, 17152515}, {12034, 17152771},
1363
  {12035, 17153027}, {12036, 17153283}, {12037, 17153539}, {12038, 17153795},
1364
  {12039, 17154051}, {12040, 17154307}, {12041, 17154563}, {12042, 17154819},
1365
  {12043, 17155075}, {12044, 17155331}, {12045, 17155587}, {12046, 17155843},
1366
  {12047, 17156099}, {12048, 17156355}, {12049, 17156611}, {12050, 17156867},
1367
  {12051, 17157123}, {12052, 17157379}, {12053, 17157635}, {12054, 17157891},
1368
  {12055, 17158147}, {12056, 17158403}, {12057, 17158659}, {12058, 17158915},
1369
  {12059, 17159171}, {12060, 17159427}, {12061, 17159683}, {12062, 17159939},
1370
  {12063, 17160195}, {12064, 17160451}, {12065, 17160707}, {12066, 17160963},
1371
  {12067, 17161219}, {12068, 17161475}, {12069, 17161731}, {12070, 17161987},
1372
  {12071, 17162243}, {12072, 17162499}, {12073, 17162755}, {12074, 17163011},
1373
  {12075, 17163267}, {12076, 17163523}, {12077, 17163779}, {12078, 17164035},
1374
  {12079, 17164291}, {12080, 17164547}, {12081, 17164803}, {12082, 17165059},
1375
  {12083, 17165315}, {12084, 17165571}, {12085, 17165827}, {12086, 17166083},
1376
  {12087, 17166339}, {12088, 17166595}, {12089, 17166851}, {12090, 17167107},
1377
  {12091, 17167363}, {12092, 17167619}, {12093, 17167875}, {12094, 17168131},
1378
  {12095, 17168387}, {12096, 17168643}, {12097, 17168899}, {12098, 17169155},
1379
  {12099, 17169411}, {12100, 17169667}, {12101, 17169923}, {12102, 17170179},
1380
  {12103, 17170435}, {12104, 17170691}, {12105, 17170947}, {12106, 17171203},
1381
  {12107, 17171459}, {12108, 17171715}, {12109, 17171971}, {12110, 17172227},
1382
  {12111, 17172483}, {12112, 17172739}, {12113, 17172995}, {12114, 17173251},
1383
  {12115, 17173507}, {12116, 17173763}, {12117, 17174019}, {12118, 17174275},
1384
  {12119, 17174531}, {12120, 17174787}, {12121, 17175043}, {12122, 17175299},
1385
  {12123, 17175555}, {12124, 17175811}, {12125, 17176067}, {12126, 17176323},
1386
  {12127, 17176579}, {12128, 17176835}, {12129, 17177091}, {12130, 17177347},
1387
  {12131, 17177603}, {12132, 17177859}, {12133, 17178115}, {12134, 17178371},
1388
  {12135, 17178627}, {12136, 17178883}, {12137, 17179139}, {12138, 17179395},
1389
  {12139, 17179651}, {12140, 17179907}, {12141, 17180163}, {12142, 17180419},
1390
  {12143, 17180675}, {12144, 17180931}, {12145, 17181187}, {12146, 17181443},
1391
  {12147, 17181699}, {12148, 17181955}, {12149, 17182211}, {12150, 17182467},
1392
  {12151, 17182723}, {12152, 17182979}, {12153, 17183235}, {12154, 17183491},
1393
  {12155, 17183747}, {12156, 17184003}, {12157, 17184259}, {12158, 17184515},
1394
  {12159, 17184771}, {12160, 17185027}, {12161, 17185283}, {12162, 17185539},
1395
  {12163, 17185795}, {12164, 17186051}, {12165, 17186307}, {12166, 17186563},
1396
  {12167, 17186819}, {12168, 17187075}, {12169, 17187331}, {12170, 17187587},
1397
  {12171, 17187843}, {12172, 17188099}, {12173, 17188355}, {12174, 17188611},
1398
  {12175, 17188867}, {12176, 17189123}, {12177, 17189379}, {12178, 17189635},
1399
  {12179, 17189891}, {12180, 17190147}, {12181, 17190403}, {12182, 17190659},
1400
  {12183, 17190915}, {12184, 17191171}, {12185, 17191427}, {12186, 17191683},
1401
  {12187, 17191939}, {12188, 17192195}, {12189, 17192451}, {12190, 17192707},
1402
  {12191, 17192963}, {12192, 17193219}, {12193, 17193475}, {12194, 17193731},
1403
  {12195, 17193987}, {12196, 17194243}, {12197, 17194499}, {12198, 17194755},
1404
  {12199, 17195011}, {12200, 17195267}, {12201, 17195523}, {12202, 17195779},
1405
  {12203, 17196035}, {12204, 17196291}, {12205, 17196547}, {12206, 17196803},
1406
  {12207, 17197059}, {12208, 17197315}, {12209, 17197571}, {12210, 17197827},
1407
  {12211, 17198083}, {12212, 17198339}, {12213, 17198595}, {12214, 17198851},
1408
  {12215, 17199107}, {12216, 17199363}, {12217, 17199619}, {12218, 17199875},
1409
  {12219, 17200131}, {12220, 17200387}, {12221, 17200643}, {12222, 17200899},
1410
  {12223, 17201155}, {12224, 17201411}, {12225, 17201667}, {12226, 17201923},
1411
  {12227, 17202179}, {12228, 17202435}, {12229, 17202691}, {12230, 17202947},
1412
  {12231, 17203203}, {12232, 17203459}, {12233, 17203715}, {12234, 17203971},
1413
  {12235, 17204227}, {12236, 17204483}, {12237, 17204739}, {12238, 17204995},
1414
  {12239, 17205251}, {12240, 17205507}, {12241, 17205763}, {12242, 17206019},
1415
  {12243, 17206275}, {12244, 17206531}, {12245, 17206787}, {12246, 2},
1416
  {12288, 16783875}, {12289, 1}, {12290, 17207043}, {12291, 1},
1417
  {12342, 17207299}, {12343, 1}, {12344, 17158147}, {12345, 17207555},
1418
  {12346, 17207811}, {12347, 1}, {12352, 2}, {12353, 1},
1419
  {12439, 2}, {12441, 1}, {12443, 33985283}, {12444, 33985795},
1420
  {12445, 1}, {12447, 33986307}, {12448, 1}, {12543, 33986819},
1421
  {12544, 2}, {12549, 1}, {12592, 2}, {12593, 17210115},
1422
  {12594, 17210371}, {12595, 17210627}, {12596, 17210883}, {12597, 17211139},
1423
  {12598, 17211395}, {12599, 17211651}, {12600, 17211907}, {12601, 17212163},
1424
  {12602, 17212419}, {12603, 17212675}, {12604, 17212931}, {12605, 17213187},
1425
  {12606, 17213443}, {12607, 17213699}, {12608, 17213955}, {12609, 17214211},
1426
  {12610, 17214467}, {12611, 17214723}, {12612, 17214979}, {12613, 17215235},
1427
  {12614, 17215491}, {12615, 17215747}, {12616, 17216003}, {12617, 17216259},
1428
  {12618, 17216515}, {12619, 17216771}, {12620, 17217027}, {12621, 17217283},
1429
  {12622, 17217539}, {12623, 17217795}, {12624, 17218051}, {12625, 17218307},
1430
  {12626, 17218563}, {12627, 17218819}, {12628, 17219075}, {12629, 17219331},
1431
  {12630, 17219587}, {12631, 17219843}, {12632, 17220099}, {12633, 17220355},
1432
  {12634, 17220611}, {12635, 17220867}, {12636, 17221123}, {12637, 17221379},
1433
  {12638, 17221635}, {12639, 17221891}, {12640, 17222147}, {12641, 17222403},
1434
  {12642, 17222659}, {12643, 17222915}, {12644, 0}, {12645, 17223171},
1435
  {12646, 17223427}, {12647, 17223683}, {12648, 17223939}, {12649, 17224195},
1436
  {12650, 17224451}, {12651, 17224707}, {12652, 17224963}, {12653, 17225219},
1437
  {12654, 17225475}, {12655, 17225731}, {12656, 17225987}, {12657, 17226243},
1438
  {12658, 17226499}, {12659, 17226755}, {12660, 17227011}, {12661, 17227267},
1439
  {12662, 17227523}, {12663, 17227779}, {12664, 17228035}, {12665, 17228291},
1440
  {12666, 17228547}, {12667, 17228803}, {12668, 17229059}, {12669, 17229315},
1441
  {12670, 17229571}, {12671, 17229827}, {12672, 17230083}, {12673, 17230339},
1442
  {12674, 17230595}, {12675, 17230851}, {12676, 17231107}, {12677, 17231363},
1443
  {12678, 17231619}, {12679, 17231875}, {12680, 17232131}, {12681, 17232387},
1444
  {12682, 17232643}, {12683, 17232899}, {12684, 17233155}, {12685, 17233411},
1445
  {12686, 17233667}, {12687, 2}, {12688, 1}, {12690, 17152259},
1446
  {12691, 17153795}, {12692, 17233923}, {12693, 17234179}, {12694, 17234435},
1447
  {12695, 17234691}, {12696, 17234947}, {12697, 17235203}, {12698, 17153283},
1448
  {12699, 17235459}, {12700, 17235715}, {12701, 17235971}, {12702, 17236227},
1449
  {12703, 17154307}, {12704, 1}, {12774, 2}, {12784, 1},
1450
  {12800, 50790915}, {12801, 50791683}, {12802, 50792451}, {12803, 50793219},
1451
  {12804, 50793987}, {12805, 50794755}, {12806, 50795523}, {12807, 50796291},
1452
  {12808, 50797059}, {12809, 50797827}, {12810, 50798595}, {12811, 50799363},
1453
  {12812, 50800131}, {12813, 50800899}, {12814, 50801667}, {12815, 50802435},
1454
  {12816, 50803203}, {12817, 50803971}, {12818, 50804739}, {12819, 50805507},
1455
  {12820, 50806275}, {12821, 50807043}, {12822, 50807811}, {12823, 50808579},
1456
  {12824, 50809347}, {12825, 50810115}, {12826, 50810883}, {12827, 50811651},
1457
  {12828, 50812419}, {12829, 67590403}, {12830, 67591427}, {12831, 2},
1458
  {12832, 50815235}, {12833, 50816003}, {12834, 50816771}, {12835, 50817539},
1459
  {12836, 50818307}, {12837, 50819075}, {12838, 50819843}, {12839, 50820611},
1460
  {12840, 50821379}, {12841, 50822147}, {12842, 50822915}, {12843, 50823683},
1461
  {12844, 50824451}, {12845, 50825219}, {12846, 50825987}, {12847, 50826755},
1462
  {12848, 50827523}, {12849, 50828291}, {12850, 50829059}, {12851, 50829827},
1463
  {12852, 50830595}, {12853, 50831363}, {12854, 50832131}, {12855, 50832899},
1464
  {12856, 50833667}, {12857, 50834435}, {12858, 50835203}, {12859, 50835971},
1465
  {12860, 50836739}, {12861, 50837507}, {12862, 50838275}, {12863, 50839043},
1466
  {12864, 50839811}, {12865, 50840579}, {12866, 50841347}, {12867, 50842115},
1467
  {12868, 17288451}, {12869, 17288707}, {12870, 17169155}, {12871, 17288963},
1468
  {12872, 1}, {12880, 50843651}, {12881, 33855747}, {12882, 34067203},
1469
  {12883, 33562371}, {12884, 34067715}, {12885, 34068227}, {12886, 34068739},
1470
  {12887, 34069251}, {12888, 34069763}, {12889, 34070275}, {12890, 34070787},
1471
  {12891, 33837571}, {12892, 33836803}, {12893, 34071299}, {12894, 34071811},
1472
  {12895, 34072323}, {12896, 17210115}, {12897, 17210883}, {12898, 17211651},
1473
  {12899, 17212163}, {12900, 17214211}, {12901, 17214467}, {12902, 17215235},
1474
  {12903, 17215747}, {12904, 17216003}, {12905, 17216515}, {12906, 17216771},
1475
  {12907, 17217027}, {12908, 17217283}, {12909, 17217539}, {12910, 17247491},
1476
  {12911, 17248259}, {12912, 17249027}, {12913, 17249795}, {12914, 17250563},
1477
  {12915, 17251331}, {12916, 17252099}, {12917, 17252867}, {12918, 17253635},
1478
  {12919, 17254403}, {12920, 17255171}, {12921, 17255939}, {12922, 17256707},
1479
  {12923, 17257475}, {12924, 34072835}, {12925, 34073347}, {12926, 17296643},
1480
  {12927, 1}, {12928, 17152259}, {12929, 17153795}, {12930, 17233923},
1481
  {12931, 17234179}, {12932, 17264131}, {12933, 17264899}, {12934, 17265667},
1482
  {12935, 17155075}, {12936, 17267203}, {12937, 17158147}, {12938, 17170947},
1483
  {12939, 17174019}, {12940, 17173763}, {12941, 17171203}, {12942, 17194755},
1484
  {12943, 17160195}, {12944, 17170435}, {12945, 17274115}, {12946, 17274883},
1485
  {12947, 17275651}, {12948, 17276419}, {12949, 17277187}, {12950, 17277955},
1486
  {12951, 17278723}, {12952, 17279491}, {12953, 17296899}, {12954, 17297155},
1487
  {12955, 17161731}, {12956, 17297411}, {12957, 17297667}, {12958, 17297923},
1488
  {12959, 17298179}, {12960, 17298435}, {12961, 17286403}, {12962, 17298691},
1489
  {12963, 17298947}, {12964, 17234435}, {12965, 17234691}, {12966, 17234947},
1490
  {12967, 17299203}, {12968, 17299459}, {12969, 17299715}, {12970, 17299971},
1491
  {12971, 17281795}, {12972, 17282563}, {12973, 17283331}, {12974, 17284099},
1492
  {12975, 17284867}, {12976, 17300227}, {12977, 34077699}, {12978, 34078211},
1493
  {12979, 34078723}, {12980, 34079235}, {12981, 34079747}, {12982, 33564931},
1494
  {12983, 34067971}, {12984, 34072067}, {12985, 34080259}, {12986, 34080771},
1495
  {12987, 34081283}, {12988, 34081795}, {12989, 34082307}, {12990, 34082819},
1496
  {12991, 34083331}, {12992, 34083843}, {12993, 34084355}, {12994, 34084867},
1497
  {12995, 34085379}, {12996, 34085891}, {12997, 34086403}, {12998, 34086915},
1498
  {12999, 34087427}, {13000, 34087939}, {13001, 50865667}, {13002, 50866435},
1499
  {13003, 50867203}, {13004, 34090755}, {13005, 50868483}, {13006, 34092035},
1500
  {13007, 50869763}, {13008, 17316099}, {13009, 17316355}, {13010, 17316611},
1501
  {13011, 17316867}, {13012, 17317123}, {13013, 17317379}, {13014, 17317635},
1502
  {13015, 17317891}, {13016, 17318147}, {13017, 17209603}, {13018, 17318403},
1503
  {13019, 17318659}, {13020, 17318915}, {13021, 17319171}, {13022, 17319427},
1504
  {13023, 17319683}, {13024, 17319939}, {13025, 17320195}, {13026, 17320451},
1505
  {13027, 17209859}, {13028, 17320707}, {13029, 17320963}, {13030, 17321219},
1506
  {13031, 17321475}, {13032, 17321731}, {13033, 17321987}, {13034, 17322243},
1507
  {13035, 17322499}, {13036, 17322755}, {13037, 17323011}, {13038, 17323267},
1508
  {13039, 17323523}, {13040, 17323779}, {13041, 17324035}, {13042, 17324291},
1509
  {13043, 17324547}, {13044, 17324803}, {13045, 17325059}, {13046, 17325315},
1510
  {13047, 17325571}, {13048, 17325827}, {13049, 17326083}, {13050, 17326339},
1511
  {13051, 17326595}, {13052, 17326851}, {13053, 17327107}, {13054, 17327363},
1512
  {13055, 34104835}, {13056, 67659779}, {13057, 67660803}, {13058, 67661827},
1513
  {13059, 50885635}, {13060, 67663619}, {13061, 50887427}, {13062, 50888195},
1514
  {13063, 84443395}, {13064, 67667459}, {13065, 50891267}, {13066, 50892035},
1515
  {13067, 50892803}, {13068, 67670787}, {13069, 67671811}, {13070, 50895619},
1516
  {13071, 50896387}, {13072, 34119939}, {13073, 50897667}, {13074, 67675651},
1517
  {13075, 67676675}, {13076, 34123267}, {13077, 84455427}, {13078, 101233923},
1518
  {13079, 84458243}, {13080, 50901507}, {13081, 84459523}, {13082, 84460803},
1519
  {13083, 67684867}, {13084, 50908675}, {13085, 50909443}, {13086, 50910211},
1520
  {13087, 67688195}, {13088, 84466435}, {13089, 67690499}, {13090, 50914307},
1521
  {13091, 50915075}, {13092, 50915843}, {13093, 34139395}, {13094, 34139907},
1522
  {13095, 34128643}, {13096, 34140419}, {13097, 50918147}, {13098, 50918915},
1523
  {13099, 84474115}, {13100, 50920963}, {13101, 67698947}, {13102, 84477187},
1524
  {13103, 50924035}, {13104, 34147587}, {13105, 34148099}, {13106, 84480259},
1525
  {13107, 67704323}, {13108, 84482563}, {13109, 50929411}, {13110, 84484611},
1526
  {13111, 34154243}, {13112, 50931971}, {13113, 50932739}, {13114, 50933507},
1527
  {13115, 50934275}, {13116, 50935043}, {13117, 67713027}, {13118, 50936835},
1528
  {13119, 34160387}, {13120, 50938115}, {13121, 50938883}, {13122, 50939651},
1529
  {13123, 67717635}, {13124, 50941443}, {13125, 50942211}, {13126, 50942979},
1530
  {13127, 84498179}, {13128, 67722243}, {13129, 34168835}, {13130, 84500995},
1531
  {13131, 34170627}, {13132, 67725571}, {13133, 67680003}, {13134, 50949379},
1532
  {13135, 50950147}, {13136, 50950915}, {13137, 67728899}, {13138, 34175491},
1533
  {13139, 50953219}, {13140, 67731203}, {13141, 34177795}, {13142, 84509955},
1534
  {13143, 50904323}, {13144, 34179587}, {13145, 34180099}, {13146, 34180611},
1535
  {13147, 34181123}, {13148, 34181635}, {13149, 34182147}, {13150, 34182659},
1536
  {13151, 34183171}, {13152, 34183683}, {13153, 34184195}, {13154, 50961923},
1537
  {13155, 50962691}, {13156, 50963459}, {13157, 50964227}, {13158, 50964995},
1538
  {13159, 50965763}, {13160, 50966531}, {13161, 50967299}, {13162, 50968067},
1539
  {13163, 50968835}, {13164, 50969603}, {13165, 50970371}, {13166, 50971139},
1540
  {13167, 50971907}, {13168, 50972675}, {13169, 50973443}, {13170, 34196995},
1541
  {13171, 34197507}, {13172, 50975235}, {13173, 34198787}, {13174, 34199299},
1542
  {13175, 34199811}, {13176, 50977539}, {13177, 50978307}, {13178, 34201859},
1543
  {13179, 34202371}, {13180, 34202883}, {13181, 34203395}, {13182, 34203907},
1544
  {13183, 67758851}, {13184, 34196483}, {13185, 34205443}, {13186, 34205955},
1545
  {13187, 34206467}, {13188, 34206979}, {13189, 34207491}, {13190, 34208003},
1546
  {13191, 34208515}, {13192, 50986243}, {13193, 67764227}, {13194, 34210819},
1547
  {13195, 34211331}, {13196, 34211843}, {13197, 34212355}, {13198, 34212867},
1548
  {13199, 34213379}, {13200, 34213891}, {13201, 50991619}, {13202, 50992387},
1549
  {13203, 50990851}, {13204, 50993155}, {13205, 34216707}, {13206, 34217219},
1550
  {13207, 34217731}, {13208, 33556995}, {13209, 34218243}, {13210, 34218755},
1551
  {13211, 34219267}, {13212, 34219779}, {13213, 34220291}, {13214, 34220803},
1552
  {13215, 50998531}, {13216, 50999299}, {13217, 34200579}, {13218, 51000067},
1553
  {13219, 51000835}, {13220, 51001603}, {13221, 34201347}, {13222, 51002371},
1554
  {13223, 51003139}, {13224, 67781123}, {13225, 34196483}, {13226, 51004931},
1555
  {13227, 51005699}, {13228, 51006467}, {13229, 51007235}, {13230, 84562435},
1556
  {13231, 101340931}, {13232, 34233603}, {13233, 34234115}, {13234, 34234627},
1557
  {13235, 34235139}, {13236, 34235651}, {13237, 34236163}, {13238, 34236675},
1558
  {13239, 34237187}, {13240, 34237699}, {13241, 34237187}, {13242, 34238211},
1559
  {13243, 34238723}, {13244, 34239235}, {13245, 34239747}, {13246, 34240259},
1560
  {13247, 34239747}, {13248, 34240771}, {13249, 34241283}, {13250, 2},
1561
  {13251, 34241795}, {13252, 33827331}, {13253, 33554947}, {13254, 67796739},
1562
  {13255, 2}, {13256, 34243331}, {13257, 34243843}, {13258, 34244355},
1563
  {13259, 34196227}, {13260, 34244867}, {13261, 34245379}, {13262, 34220803},
1564
  {13263, 34245891}, {13264, 33557251}, {13265, 34246403}, {13266, 51024131},
1565
  {13267, 34247683}, {13268, 34208003}, {13269, 51025411}, {13270, 51026179},
1566
  {13271, 34249731}, {13272, 2}, {13273, 51027459}, {13274, 34251011},
1567
  {13275, 34231811}, {13276, 34251523}, {13277, 34252035}, {13278, 51029763},
1568
  {13279, 51030531}, {13280, 34254083}, {13281, 34254595}, {13282, 34255107},
1569
  {13283, 34255619}, {13284, 34256131}, {13285, 34256643}, {13286, 34257155},
1570
  {13287, 34257667}, {13288, 34258179}, {13289, 51035907}, {13290, 51036675},
1571
  {13291, 51037443}, {13292, 51038211}, {13293, 51038979}, {13294, 51039747},
1572
  {13295, 51040515}, {13296, 51041283}, {13297, 51042051}, {13298, 51042819},
1573
  {13299, 51043587}, {13300, 51044355}, {13301, 51045123}, {13302, 51045891},
1574
  {13303, 51046659}, {13304, 51047427}, {13305, 51048195}, {13306, 51048963},
1575
  {13307, 51049731}, {13308, 51050499}, {13309, 51051267}, {13310, 51052035},
1576
  {13311, 51052803}, {13312, 1}, {42125, 2}, {42128, 1},
1577
  {42183, 2}, {42192, 1}, {42540, 2}, {42560, 17499139},
1578
  {42561, 1}, {42562, 17499395}, {42563, 1}, {42564, 17499651},
1579
  {42565, 1}, {42566, 17499907}, {42567, 1}, {42568, 17500163},
1580
  {42569, 1}, {42570, 16946435}, {42571, 1}, {42572, 17500419},
1581
  {42573, 1}, {42574, 17500675}, {42575, 1}, {42576, 17500931},
1582
  {42577, 1}, {42578, 17501187}, {42579, 1}, {42580, 17501443},
1583
  {42581, 1}, {42582, 17501699}, {42583, 1}, {42584, 17501955},
1584
  {42585, 1}, {42586, 17502211}, {42587, 1}, {42588, 17502467},
1585
  {42589, 1}, {42590, 17502723}, {42591, 1}, {42592, 17502979},
1586
  {42593, 1}, {42594, 17503235}, {42595, 1}, {42596, 17503491},
1587
  {42597, 1}, {42598, 17503747}, {42599, 1}, {42600, 17504003},
1588
  {42601, 1}, {42602, 17504259}, {42603, 1}, {42604, 17504515},
1589
  {42605, 1}, {42624, 17504771}, {42625, 1}, {42626, 17505027},
1590
  {42627, 1}, {42628, 17505283}, {42629, 1}, {42630, 17505539},
1591
  {42631, 1}, {42632, 17505795}, {42633, 1}, {42634, 17506051},
1592
  {42635, 1}, {42636, 17506307}, {42637, 1}, {42638, 17506563},
1593
  {42639, 1}, {42640, 17506819}, {42641, 1}, {42642, 17507075},
1594
  {42643, 1}, {42644, 17507331}, {42645, 1}, {42646, 17507587},
1595
  {42647, 1}, {42648, 17507843}, {42649, 1}, {42650, 17508099},
1596
  {42651, 1}, {42652, 16873219}, {42653, 16873731}, {42654, 1},
1597
  {42744, 2}, {42752, 1}, {42786, 17508355}, {42787, 1},
1598
  {42788, 17508611}, {42789, 1}, {42790, 17508867}, {42791, 1},
1599
  {42792, 17509123}, {42793, 1}, {42794, 17509379}, {42795, 1},
1600
  {42796, 17509635}, {42797, 1}, {42798, 17509891}, {42799, 1},
1601
  {42802, 17510147}, {42803, 1}, {42804, 17510403}, {42805, 1},
1602
  {42806, 17510659}, {42807, 1}, {42808, 17510915}, {42809, 1},
1603
  {42810, 17511171}, {42811, 1}, {42812, 17511427}, {42813, 1},
1604
  {42814, 17511683}, {42815, 1}, {42816, 17511939}, {42817, 1},
1605
  {42818, 17512195}, {42819, 1}, {42820, 17512451}, {42821, 1},
1606
  {42822, 17512707}, {42823, 1}, {42824, 17512963}, {42825, 1},
1607
  {42826, 17513219}, {42827, 1}, {42828, 17513475}, {42829, 1},
1608
  {42830, 17513731}, {42831, 1}, {42832, 17513987}, {42833, 1},
1609
  {42834, 17514243}, {42835, 1}, {42836, 17514499}, {42837, 1},
1610
  {42838, 17514755}, {42839, 1}, {42840, 17515011}, {42841, 1},
1611
  {42842, 17515267}, {42843, 1}, {42844, 17515523}, {42845, 1},
1612
  {42846, 17515779}, {42847, 1}, {42848, 17516035}, {42849, 1},
1613
  {42850, 17516291}, {42851, 1}, {42852, 17516547}, {42853, 1},
1614
  {42854, 17516803}, {42855, 1}, {42856, 17517059}, {42857, 1},
1615
  {42858, 17517315}, {42859, 1}, {42860, 17517571}, {42861, 1},
1616
  {42862, 17517827}, {42863, 1}, {42864, 17517827}, {42865, 1},
1617
  {42873, 17518083}, {42874, 1}, {42875, 17518339}, {42876, 1},
1618
  {42877, 17518595}, {42878, 17518851}, {42879, 1}, {42880, 17519107},
1619
  {42881, 1}, {42882, 17519363}, {42883, 1}, {42884, 17519619},
1620
  {42885, 1}, {42886, 17519875}, {42887, 1}, {42891, 17520131},
1621
  {42892, 1}, {42893, 16961539}, {42894, 1}, {42896, 17520387},
1622
  {42897, 1}, {42898, 17520643}, {42899, 1}, {42902, 17520899},
1623
  {42903, 1}, {42904, 17521155}, {42905, 1}, {42906, 17521411},
1624
  {42907, 1}, {42908, 17521667}, {42909, 1}, {42910, 17521923},
1625
  {42911, 1}, {42912, 17522179}, {42913, 1}, {42914, 17522435},
1626
  {42915, 1}, {42916, 17522691}, {42917, 1}, {42918, 17522947},
1627
  {42919, 1}, {42920, 17523203}, {42921, 1}, {42922, 16841475},
1628
  {42923, 16959235}, {42924, 16961283}, {42925, 17523459}, {42926, 16961795},
1629
  {42927, 1}, {42928, 17523715}, {42929, 17523971}, {42930, 16962307},
1630
  {42931, 17524227}, {42932, 17524483}, {42933, 1}, {42934, 17524739},
1631
  {42935, 1}, {42936, 17524995}, {42937, 1}, {42938, 17525251},
1632
  {42939, 1}, {42940, 17525507}, {42941, 1}, {42942, 17525763},
1633
  {42943, 1}, {42944, 17526019}, {42945, 1}, {42946, 17526275},
1634
  {42947, 1}, {42948, 17526531}, {42949, 16964611}, {42950, 17526787},
1635
  {42951, 17527043}, {42952, 1}, {42953, 17527299}, {42954, 1},
1636
  {42955, 17527555}, {42956, 17527811}, {42957, 1}, {42958, 2},
1637
  {42960, 17528067}, {42961, 1}, {42962, 2}, {42963, 1},
1638
  {42964, 2}, {42965, 1}, {42966, 17528323}, {42967, 1},
1639
  {42968, 17528579}, {42969, 1}, {42970, 17528835}, {42971, 1},
1640
  {42972, 17529091}, {42973, 2}, {42994, 16777731}, {42995, 16778499},
1641
  {42996, 16781315}, {42997, 17529347}, {42998, 1}, {43000, 16802051},
1642
  {43001, 16808195}, {43002, 1}, {43053, 2}, {43056, 1},
1643
  {43066, 2}, {43072, 1}, {43128, 2}, {43136, 1},
1644
  {43206, 2}, {43214, 1}, {43226, 2}, {43232, 1},
1645
  {43348, 2}, {43359, 1}, {43389, 2}, {43392, 1},
1646
  {43470, 2}, {43471, 1}, {43482, 2}, {43486, 1},
1647
  {43519, 2}, {43520, 1}, {43575, 2}, {43584, 1},
1648
  {43598, 2}, {43600, 1}, {43610, 2}, {43612, 1},
1649
  {43715, 2}, {43739, 1}, {43767, 2}, {43777, 1},
1650
  {43783, 2}, {43785, 1}, {43791, 2}, {43793, 1},
1651
  {43799, 2}, {43808, 1}, {43815, 2}, {43816, 1},
1652
  {43823, 2}, {43824, 1}, {43868, 17508867}, {43869, 17529603},
1653
  {43870, 17135363}, {43871, 17529859}, {43872, 1}, {43881, 17530115},
1654
  {43882, 1}, {43884, 2}, {43888, 17530371}, {43889, 17530627},
1655
  {43890, 17530883}, {43891, 17531139}, {43892, 17531395}, {43893, 17531651},
1656
  {43894, 17531907}, {43895, 17532163}, {43896, 17532419}, {43897, 17532675},
1657
  {43898, 17532931}, {43899, 17533187}, {43900, 17533443}, {43901, 17533699},
1658
  {43902, 17533955}, {43903, 17534211}, {43904, 17534467}, {43905, 17534723},
1659
  {43906, 17534979}, {43907, 17535235}, {43908, 17535491}, {43909, 17535747},
1660
  {43910, 17536003}, {43911, 17536259}, {43912, 17536515}, {43913, 17536771},
1661
  {43914, 17537027}, {43915, 17537283}, {43916, 17537539}, {43917, 17537795},
1662
  {43918, 17538051}, {43919, 17538307}, {43920, 17538563}, {43921, 17538819},
1663
  {43922, 17539075}, {43923, 17539331}, {43924, 17539587}, {43925, 17539843},
1664
  {43926, 17540099}, {43927, 17540355}, {43928, 17540611}, {43929, 17540867},
1665
  {43930, 17541123}, {43931, 17541379}, {43932, 17541635}, {43933, 17541891},
1666
  {43934, 17542147}, {43935, 17542403}, {43936, 17542659}, {43937, 17542915},
1667
  {43938, 17543171}, {43939, 17543427}, {43940, 17543683}, {43941, 17543939},
1668
  {43942, 17544195}, {43943, 17544451}, {43944, 17544707}, {43945, 17544963},
1669
  {43946, 17545219}, {43947, 17545475}, {43948, 17545731}, {43949, 17545987},
1670
  {43950, 17546243}, {43951, 17546499}, {43952, 17546755}, {43953, 17547011},
1671
  {43954, 17547267}, {43955, 17547523}, {43956, 17547779}, {43957, 17548035},
1672
  {43958, 17548291}, {43959, 17548547}, {43960, 17548803}, {43961, 17549059},
1673
  {43962, 17549315}, {43963, 17549571}, {43964, 17549827}, {43965, 17550083},
1674
  {43966, 17550339}, {43967, 17550595}, {43968, 1}, {44014, 2},
1675
  {44016, 1}, {44026, 2}, {44032, 1}, {55204, 2},
1676
  {55216, 1}, {55239, 2}, {55243, 1}, {55292, 2},
1677
  {63744, 17550851}, {63745, 17551107}, {63746, 17192707}, {63747, 17551363},
1678
  {63748, 17551619}, {63749, 17551875}, {63750, 17552131}, {63751, 17206531},
1679
  {63753, 17552387}, {63754, 17194755}, {63755, 17552643}, {63756, 17552899},
1680
  {63757, 17553155}, {63758, 17553411}, {63759, 17553667}, {63760, 17553923},
1681
  {63761, 17554179}, {63762, 17554435}, {63763, 17554691}, {63764, 17554947},
1682
  {63765, 17555203}, {63766, 17555459}, {63767, 17555715}, {63768, 17555971},
1683
  {63769, 17556227}, {63770, 17556483}, {63771, 17556739}, {63772, 17556995},
1684
  {63773, 17557251}, {63774, 17557507}, {63775, 17557763}, {63776, 17558019},
1685
  {63777, 17558275}, {63778, 17558531}, {63779, 17558787}, {63780, 17559043},
1686
  {63781, 17559299}, {63782, 17559555}, {63783, 17559811}, {63784, 17560067},
1687
  {63785, 17560323}, {63786, 17560579}, {63787, 17560835}, {63788, 17561091},
1688
  {63789, 17561347}, {63790, 17561603}, {63791, 17561859}, {63792, 17562115},
1689
  {63793, 17562371}, {63794, 17562627}, {63795, 17562883}, {63796, 17184003},
1690
  {63797, 17563139}, {63798, 17563395}, {63799, 17563651}, {63800, 17563907},
1691
  {63801, 17564163}, {63802, 17564419}, {63803, 17564675}, {63804, 17564931},
1692
  {63805, 17565187}, {63806, 17565443}, {63807, 17565699}, {63808, 17202691},
1693
  {63809, 17565955}, {63810, 17566211}, {63811, 17566467}, {63812, 17566723},
1694
  {63813, 17566979}, {63814, 17567235}, {63815, 17567491}, {63816, 17567747},
1695
  {63817, 17568003}, {63818, 17568259}, {63819, 17568515}, {63820, 17568771},
1696
  {63821, 17569027}, {63822, 17569283}, {63823, 17569539}, {63824, 17569795},
1697
  {63825, 17570051}, {63826, 17570307}, {63827, 17570563}, {63828, 17570819},
1698
  {63829, 17571075}, {63830, 17571331}, {63831, 17571587}, {63832, 17571843},
1699
  {63833, 17572099}, {63834, 17572355}, {63835, 17572611}, {63836, 17554947},
1700
  {63837, 17572867}, {63838, 17573123}, {63839, 17573379}, {63840, 17573635},
1701
  {63841, 17573891}, {63842, 17574147}, {63843, 17574403}, {63844, 17574659},
1702
  {63845, 17574915}, {63846, 17575171}, {63847, 17575427}, {63848, 17575683},
1703
  {63849, 17575939}, {63850, 17576195}, {63851, 17576451}, {63852, 17576707},
1704
  {63853, 17576963}, {63854, 17577219}, {63855, 17577475}, {63856, 17577731},
1705
  {63857, 17193219}, {63858, 17577987}, {63859, 17578243}, {63860, 17578499},
1706
  {63861, 17578755}, {63862, 17579011}, {63863, 17579267}, {63864, 17579523},
1707
  {63865, 17579779}, {63866, 17580035}, {63867, 17580291}, {63868, 17580547},
1708
  {63869, 17580803}, {63870, 17581059}, {63871, 17581315}, {63872, 17581571},
1709
  {63873, 17161731}, {63874, 17581827}, {63875, 17582083}, {63876, 17582339},
1710
  {63877, 17582595}, {63878, 17582851}, {63879, 17583107}, {63880, 17583363},
1711
  {63881, 17583619}, {63882, 17156867}, {63883, 17583875}, {63884, 17584131},
1712
  {63885, 17584387}, {63886, 17584643}, {63887, 17584899}, {63888, 17585155},
1713
  {63889, 17585411}, {63890, 17585667}, {63891, 17585923}, {63892, 17586179},
1714
  {63893, 17586435}, {63894, 17586691}, {63895, 17586947}, {63896, 17587203},
1715
  {63897, 17587459}, {63898, 17587715}, {63899, 17587971}, {63900, 17588227},
1716
  {63901, 17588483}, {63902, 17588739}, {63903, 17588995}, {63904, 17589251},
1717
  {63905, 17577475}, {63906, 17589507}, {63907, 17589763}, {63908, 17590019},
1718
  {63909, 17590275}, {63910, 17590531}, {63911, 17590787}, {63912, 17327619},
1719
  {63913, 17591043}, {63914, 17573379}, {63915, 17591299}, {63916, 17591555},
1720
  {63917, 17591811}, {63918, 17592067}, {63919, 17592323}, {63920, 17592579},
1721
  {63921, 17592835}, {63922, 17593091}, {63923, 17593347}, {63924, 17593603},
1722
  {63925, 17593859}, {63926, 17594115}, {63927, 17594371}, {63928, 17594627},
1723
  {63929, 17594883}, {63930, 17595139}, {63931, 17595395}, {63932, 17595651},
1724
  {63933, 17595907}, {63934, 17596163}, {63935, 17554947}, {63936, 17596419},
1725
  {63937, 17596675}, {63938, 17596931}, {63939, 17597187}, {63940, 17206275},
1726
  {63941, 17597443}, {63942, 17597699}, {63943, 17597955}, {63944, 17598211},
1727
  {63945, 17598467}, {63946, 17598723}, {63947, 17598979}, {63948, 17599235},
1728
  {63949, 17599491}, {63950, 17599747}, {63951, 17600003}, {63952, 17600259},
1729
  {63953, 17264899}, {63954, 17600515}, {63955, 17600771}, {63956, 17601027},
1730
  {63957, 17601283}, {63958, 17601539}, {63959, 17601795}, {63960, 17602051},
1731
  {63961, 17602307}, {63962, 17602563}, {63963, 17573891}, {63964, 17602819},
1732
  {63965, 17603075}, {63966, 17603331}, {63967, 17603587}, {63968, 17603843},
1733
  {63969, 17604099}, {63970, 17604355}, {63971, 17604611}, {63972, 17604867},
1734
  {63973, 17605123}, {63974, 17605379}, {63975, 17605635}, {63976, 17605891},
1735
  {63977, 17194499}, {63978, 17606147}, {63979, 17606403}, {63980, 17606659},
1736
  {63981, 17606915}, {63982, 17607171}, {63983, 17607427}, {63984, 17607683},
1737
  {63985, 17607939}, {63986, 17608195}, {63987, 17608451}, {63988, 17608707},
1738
  {63989, 17608963}, {63990, 17609219}, {63991, 17181955}, {63992, 17609475},
1739
  {63993, 17609731}, {63994, 17609987}, {63995, 17610243}, {63996, 17610499},
1740
  {63997, 17610755}, {63998, 17611011}, {63999, 17611267}, {64000, 17611523},
1741
  {64001, 17611779}, {64002, 17612035}, {64003, 17612291}, {64004, 17612547},
1742
  {64005, 17612803}, {64006, 17613059}, {64007, 17613315}, {64008, 17188867},
1743
  {64009, 17613571}, {64010, 17189635}, {64011, 17613827}, {64012, 17614083},
1744
  {64013, 17614339}, {64014, 1}, {64016, 17614595}, {64017, 1},
1745
  {64018, 17614851}, {64019, 1}, {64021, 17615107}, {64022, 17615363},
1746
  {64023, 17615619}, {64024, 17615875}, {64025, 17616131}, {64026, 17616387},
1747
  {64027, 17616643}, {64028, 17616899}, {64029, 17617155}, {64030, 17183747},
1748
  {64031, 1}, {64032, 17617411}, {64033, 1}, {64034, 17617667},
1749
  {64035, 1}, {64037, 17617923}, {64038, 17618179}, {64039, 1},
1750
  {64042, 17618435}, {64043, 17618691}, {64044, 17618947}, {64045, 17619203},
1751
  {64046, 17619459}, {64047, 17619715}, {64048, 17619971}, {64049, 17620227},
1752
  {64050, 17620483}, {64051, 17620739}, {64052, 17620995}, {64053, 17621251},
1753
  {64054, 17621507}, {64055, 17621763}, {64056, 17622019}, {64057, 17622275},
1754
  {64058, 17622531}, {64059, 17622787}, {64060, 17163523}, {64061, 17623043},
1755
  {64062, 17623299}, {64063, 17623555}, {64064, 17623811}, {64065, 17624067},
1756
  {64066, 17624323}, {64067, 17624579}, {64068, 17624835}, {64069, 17625091},
1757
  {64070, 17625347}, {64071, 17625603}, {64072, 17625859}, {64073, 17626115},
1758
  {64074, 17626371}, {64075, 17626627}, {64076, 17275651}, {64077, 17626883},
1759
  {64078, 17627139}, {64079, 17627395}, {64080, 17627651}, {64081, 17278723},
1760
  {64082, 17627907}, {64083, 17628163}, {64084, 17628419}, {64085, 17628675},
1761
  {64086, 17628931}, {64087, 17586691}, {64088, 17629187}, {64089, 17629443},
1762
  {64090, 17629699}, {64091, 17629955}, {64092, 17630211}, {64093, 17630467},
1763
  {64095, 17630723}, {64096, 17630979}, {64097, 17631235}, {64098, 17631491},
1764
  {64099, 17631747}, {64100, 17632003}, {64101, 17632259}, {64102, 17632515},
1765
  {64103, 17617923}, {64104, 17632771}, {64105, 17633027}, {64106, 17633283},
1766
  {64107, 17633539}, {64108, 17633795}, {64109, 17634051}, {64110, 2},
1767
  {64112, 17634307}, {64113, 17634563}, {64114, 17634819}, {64115, 17635075},
1768
  {64116, 17635331}, {64117, 17635587}, {64118, 17635843}, {64119, 17636099},
1769
  {64120, 17621507}, {64121, 17636355}, {64122, 17636611}, {64123, 17636867},
1770
  {64124, 17614595}, {64125, 17637123}, {64126, 17637379}, {64127, 17637635},
1771
  {64128, 17637891}, {64129, 17638147}, {64130, 17638403}, {64131, 17638659},
1772
  {64132, 17638915}, {64133, 17639171}, {64134, 17639427}, {64135, 17639683},
1773
  {64136, 17639939}, {64137, 17623555}, {64138, 17640195}, {64139, 17623811},
1774
  {64140, 17640451}, {64141, 17640707}, {64142, 17640963}, {64143, 17641219},
1775
  {64144, 17641475}, {64145, 17614851}, {64146, 17560323}, {64147, 17641731},
1776
  {64148, 17641987}, {64149, 17171971}, {64150, 17577731}, {64151, 17598723},
1777
  {64152, 17642243}, {64153, 17642499}, {64154, 17625603}, {64155, 17642755},
1778
  {64156, 17625859}, {64157, 17643011}, {64158, 17643267}, {64159, 17643523},
1779
  {64160, 17615363}, {64161, 17643779}, {64162, 17644035}, {64163, 17644291},
1780
  {64164, 17644547}, {64165, 17644803}, {64166, 17615619}, {64167, 17645059},
1781
  {64168, 17645315}, {64169, 17645571}, {64170, 17645827}, {64171, 17646083},
1782
  {64172, 17646339}, {64173, 17628931}, {64174, 17646595}, {64175, 17646851},
1783
  {64176, 17586691}, {64177, 17647107}, {64178, 17629955}, {64179, 17647363},
1784
  {64180, 17647619}, {64181, 17647875}, {64182, 17648131}, {64183, 17648387},
1785
  {64184, 17631235}, {64185, 17648643}, {64186, 17617667}, {64187, 17648899},
1786
  {64188, 17631491}, {64189, 17572867}, {64190, 17649155}, {64191, 17631747},
1787
  {64192, 17649411}, {64193, 17632259}, {64194, 17649667}, {64195, 17649923},
1788
  {64196, 17650179}, {64197, 17650435}, {64198, 17650691}, {64199, 17632771},
1789
  {64200, 17616899}, {64201, 17650947}, {64202, 17633027}, {64203, 17651203},
1790
  {64204, 17633283}, {64205, 17651459}, {64206, 17206531}, {64207, 17651715},
1791
  {64208, 17651971}, {64209, 17652227}, {64210, 17652483}, {64211, 17652739},
1792
  {64212, 17652995}, {64213, 17653251}, {64214, 17653507}, {64215, 17653763},
1793
  {64216, 17654019}, {64217, 17654275}, {64218, 2}, {64256, 34431747},
1794
  {64257, 34432259}, {64258, 34432771}, {64259, 51209219}, {64260, 51210499},
1795
  {64261, 33559043}, {64263, 2}, {64275, 34434051}, {64276, 34434563},
1796
  {64277, 34435075}, {64278, 34435587}, {64279, 34436099}, {64280, 2},
1797
  {64285, 34436611}, {64286, 1}, {64287, 34437123}, {64288, 17660419},
1798
  {64289, 17054467}, {64290, 17055235}, {64291, 17660675}, {64292, 17660931},
1799
  {64293, 17661187}, {64294, 17661443}, {64295, 17661699}, {64296, 17661955},
1800
  {64297, 17047043}, {64298, 34439427}, {64299, 34439939}, {64300, 51217667},
1801
  {64301, 51218435}, {64302, 34441987}, {64303, 34442499}, {64304, 34443011},
1802
  {64305, 34443523}, {64306, 34444035}, {64307, 34444547}, {64308, 34445059},
1803
  {64309, 34445571}, {64310, 34446083}, {64311, 2}, {64312, 34446595},
1804
  {64313, 34447107}, {64314, 34447619}, {64315, 34448131}, {64316, 34448643},
1805
  {64317, 2}, {64318, 34449155}, {64319, 2}, {64320, 34449667},
1806
  {64321, 34450179}, {64322, 2}, {64323, 34450691}, {64324, 34451203},
1807
  {64325, 2}, {64326, 34451715}, {64327, 34452227}, {64328, 34452739},
1808
  {64329, 34440451}, {64330, 34453251}, {64331, 34453763}, {64332, 34454275},
1809
  {64333, 34454787}, {64334, 34455299}, {64335, 34455811}, {64336, 17679107},
1810
  {64338, 17679363}, {64342, 17679619}, {64346, 17679875}, {64350, 17680131},
1811
  {64354, 17680387}, {64358, 17680643}, {64362, 17680899}, {64366, 17681155},
1812
  {64370, 17681411}, {64374, 17681667}, {64378, 17681923}, {64382, 17682179},
1813
  {64386, 17682435}, {64388, 17682691}, {64390, 17682947}, {64392, 17683203},
1814
  {64394, 17683459}, {64396, 17683715}, {64398, 17683971}, {64402, 17684227},
1815
  {64406, 17684483}, {64410, 17684739}, {64414, 17684995}, {64416, 17685251},
1816
  {64420, 17685507}, {64422, 17685763}, {64426, 17686019}, {64430, 17686275},
1817
  {64432, 17686531}, {64434, 1}, {64451, 2}, {64467, 17686787},
1818
  {64471, 16911619}, {64473, 17687043}, {64475, 17687299}, {64477, 33688835},
1819
  {64478, 17687555}, {64480, 17687811}, {64482, 17688067}, {64484, 17688323},
1820
  {64488, 17688579}, {64490, 34466051}, {64492, 34466563}, {64494, 34467075},
1821
  {64496, 34467587}, {64498, 34468099}, {64500, 34468611}, {64502, 34469123},
1822
  {64505, 34469635}, {64508, 17692931}, {64512, 34470403}, {64513, 34470915},
1823
  {64514, 34471427}, {64515, 34469635}, {64516, 34471939}, {64517, 34472451},
1824
  {64518, 34472963}, {64519, 34473475}, {64520, 34473987}, {64521, 34474499},
1825
  {64522, 34475011}, {64523, 34475523}, {64524, 34476035}, {64525, 34476547},
1826
  {64526, 34477059}, {64527, 34477571}, {64528, 34478083}, {64529, 34478595},
1827
  {64530, 34479107}, {64531, 34479619}, {64532, 34480131}, {64533, 34480643},
1828
  {64534, 34481155}, {64535, 34480899}, {64536, 34481667}, {64537, 34482179},
1829
  {64538, 34482691}, {64539, 34483203}, {64540, 34483715}, {64541, 34484227},
1830
  {64542, 34484739}, {64543, 34485251}, {64544, 34485763}, {64545, 34486275},
1831
  {64546, 34486787}, {64547, 34487299}, {64548, 34487811}, {64549, 34488323},
1832
  {64550, 34488835}, {64551, 34489347}, {64552, 34489859}, {64553, 34490371},
1833
  {64554, 34490883}, {64555, 34491395}, {64556, 34491907}, {64557, 34492419},
1834
  {64558, 34492931}, {64559, 34493443}, {64560, 34493955}, {64561, 34494467},
1835
  {64562, 34494979}, {64563, 34495491}, {64564, 34496003}, {64565, 34496515},
1836
  {64566, 34497027}, {64567, 34497539}, {64568, 34498051}, {64569, 34498563},
1837
  {64570, 34499075}, {64571, 34499587}, {64572, 34500099}, {64573, 34500611},
1838
  {64574, 34501123}, {64575, 34501635}, {64576, 34502147}, {64577, 34502659},
1839
  {64578, 34503171}, {64579, 34503683}, {64580, 34504195}, {64581, 34504707},
1840
  {64582, 34481411}, {64583, 34481923}, {64584, 34505219}, {64585, 34505731},
1841
  {64586, 34506243}, {64587, 34506755}, {64588, 34507267}, {64589, 34507779},
1842
  {64590, 34508291}, {64591, 34508803}, {64592, 34509315}, {64593, 34509827},
1843
  {64594, 34510339}, {64595, 34510851}, {64596, 34511363}, {64597, 34480387},
1844
  {64598, 34511875}, {64599, 34512387}, {64600, 34504451}, {64601, 34512899},
1845
  {64602, 34511619}, {64603, 34513411}, {64604, 34513923}, {64605, 34514435},
1846
  {64606, 51292163}, {64607, 51292931}, {64608, 51293699}, {64609, 51294467},
1847
  {64610, 51295235}, {64611, 51296003}, {64612, 34519555}, {64613, 34520067},
1848
  {64614, 34471427}, {64615, 34520579}, {64616, 34469635}, {64617, 34471939},
1849
  {64618, 34521091}, {64619, 34521603}, {64620, 34473987}, {64621, 34522115},
1850
  {64622, 34474499}, {64623, 34475011}, {64624, 34522627}, {64625, 34523139},
1851
  {64626, 34477059}, {64627, 34523651}, {64628, 34477571}, {64629, 34478083},
1852
  {64630, 34524163}, {64631, 34524675}, {64632, 34479107}, {64633, 34525187},
1853
  {64634, 34479619}, {64635, 34480131}, {64636, 34494467}, {64637, 34494979},
1854
  {64638, 34496515}, {64639, 34497027}, {64640, 34497539}, {64641, 34499587},
1855
  {64642, 34500099}, {64643, 34500611}, {64644, 34501123}, {64645, 34503171},
1856
  {64646, 34503683}, {64647, 34504195}, {64648, 34525699}, {64649, 34505219},
1857
  {64650, 34526211}, {64651, 34526723}, {64652, 34508291}, {64653, 34527235},
1858
  {64654, 34508803}, {64655, 34509315}, {64656, 34514435}, {64657, 34527747},
1859
  {64658, 34528259}, {64659, 34504451}, {64660, 34506499}, {64661, 34512899},
1860
  {64662, 34511619}, {64663, 34470403}, {64664, 34470915}, {64665, 34528771},
1861
  {64666, 34471427}, {64667, 34529283}, {64668, 34472451}, {64669, 34472963},
1862
  {64670, 34473475}, {64671, 34473987}, {64672, 34529795}, {64673, 34475523},
1863
  {64674, 34476035}, {64675, 34476547}, {64676, 34477059}, {64677, 34530307},
1864
  {64678, 34479107}, {64679, 34480643}, {64680, 34481155}, {64681, 34480899},
1865
  {64682, 34481667}, {64683, 34482179}, {64684, 34483203}, {64685, 34483715},
1866
  {64686, 34484227}, {64687, 34484739}, {64688, 34485251}, {64689, 34485763},
1867
  {64690, 34530819}, {64691, 34486275}, {64692, 34486787}, {64693, 34487299},
1868
  {64694, 34487811}, {64695, 34488323}, {64696, 34488835}, {64697, 34489859},
1869
  {64698, 34490371}, {64699, 34490883}, {64700, 34491395}, {64701, 34491907},
1870
  {64702, 34492419}, {64703, 34492931}, {64704, 34493443}, {64705, 34493955},
1871
  {64706, 34495491}, {64707, 34496003}, {64708, 34498051}, {64709, 34498563},
1872
  {64710, 34499075}, {64711, 34499587}, {64712, 34500099}, {64713, 34501635},
1873
  {64714, 34502147}, {64715, 34502659}, {64716, 34503171}, {64717, 34531331},
1874
  {64718, 34504707}, {64719, 34481411}, {64720, 34481923}, {64721, 34505219},
1875
  {64722, 34506755}, {64723, 34507267}, {64724, 34507779}, {64725, 34508291},
1876
  {64726, 34531843}, {64727, 34509827}, {64728, 34510339}, {64729, 34532355},
1877
  {64730, 34480387}, {64731, 34511875}, {64732, 34512387}, {64733, 34504451},
1878
  {64734, 34509571}, {64735, 34471427}, {64736, 34529283}, {64737, 34473987},
1879
  {64738, 34529795}, {64739, 34477059}, {64740, 34530307}, {64741, 34479107},
1880
  {64742, 34532867}, {64743, 34485251}, {64744, 34533379}, {64745, 34533891},
1881
  {64746, 34534403}, {64747, 34499587}, {64748, 34500099}, {64749, 34503171},
1882
  {64750, 34508291}, {64751, 34531843}, {64752, 34504451}, {64753, 34509571},
1883
  {64754, 51312131}, {64755, 51312899}, {64756, 51313667}, {64757, 34537219},
1884
  {64758, 34537731}, {64759, 34538243}, {64760, 34538755}, {64761, 34539267},
1885
  {64762, 34539779}, {64763, 34540291}, {64764, 34540803}, {64765, 34541315},
1886
  {64766, 34541827}, {64767, 34542339}, {64768, 34512131}, {64769, 34542851},
1887
  {64770, 34543363}, {64771, 34543875}, {64772, 34512643}, {64773, 34544387},
1888
  {64774, 34544899}, {64775, 34545411}, {64776, 34545923}, {64777, 34546435},
1889
  {64778, 34546947}, {64779, 34547459}, {64780, 34533891}, {64781, 34547971},
1890
  {64782, 34548483}, {64783, 34548995}, {64784, 34549507}, {64785, 34537219},
1891
  {64786, 34537731}, {64787, 34538243}, {64788, 34538755}, {64789, 34539267},
1892
  {64790, 34539779}, {64791, 34540291}, {64792, 34540803}, {64793, 34541315},
1893
  {64794, 34541827}, {64795, 34542339}, {64796, 34512131}, {64797, 34542851},
1894
  {64798, 34543363}, {64799, 34543875}, {64800, 34512643}, {64801, 34544387},
1895
  {64802, 34544899}, {64803, 34545411}, {64804, 34545923}, {64805, 34546435},
1896
  {64806, 34546947}, {64807, 34547459}, {64808, 34533891}, {64809, 34547971},
1897
  {64810, 34548483}, {64811, 34548995}, {64812, 34549507}, {64813, 34546435},
1898
  {64814, 34546947}, {64815, 34547459}, {64816, 34533891}, {64817, 34533379},
1899
  {64818, 34534403}, {64819, 34489347}, {64820, 34483715}, {64821, 34484227},
1900
  {64822, 34484739}, {64823, 34546435}, {64824, 34546947}, {64825, 34547459},
1901
  {64826, 34489347}, {64827, 34489859}, {64828, 34550019}, {64830, 1},
1902
  {64848, 51327747}, {64849, 51328515}, {64851, 51329283}, {64852, 51330051},
1903
  {64853, 51330819}, {64854, 51331587}, {64855, 51332355}, {64856, 51258371},
1904
  {64858, 51333123}, {64859, 51333891}, {64860, 51334659}, {64861, 51335427},
1905
  {64862, 51336195}, {64863, 51336963}, {64865, 51337731}, {64866, 51338499},
1906
  {64868, 51339267}, {64870, 51340035}, {64871, 51340803}, {64873, 51341571},
1907
  {64874, 51342339}, {64876, 51343107}, {64878, 51343875}, {64879, 51344643},
1908
  {64881, 51345411}, {64883, 51346179}, {64884, 51346947}, {64885, 51347715},
1909
  {64886, 51348483}, {64888, 51349251}, {64889, 51350019}, {64890, 51350787},
1910
  {64891, 51351555}, {64892, 51352323}, {64894, 51353091}, {64895, 51353859},
1911
  {64896, 51354627}, {64897, 51355395}, {64898, 51356163}, {64899, 51356931},
1912
  {64901, 51357699}, {64903, 51358467}, {64905, 51359235}, {64906, 51258627},
1913
  {64907, 51360003}, {64908, 51360771}, {64909, 51281923}, {64910, 51259139},
1914
  {64911, 51361539}, {64912, 2}, {64914, 51362307}, {64915, 51363075},
1915
  {64916, 51363843}, {64917, 51364611}, {64918, 51365379}, {64919, 51366147},
1916
  {64921, 51366915}, {64922, 51367683}, {64923, 51368451}, {64924, 51369219},
1917
  {64926, 51369987}, {64927, 51370755}, {64928, 51371523}, {64929, 51372291},
1918
  {64930, 51373059}, {64931, 51373827}, {64932, 51374595}, {64933, 51375363},
1919
  {64934, 51376131}, {64935, 51376899}, {64936, 51377667}, {64937, 51378435},
1920
  {64938, 51379203}, {64939, 51379971}, {64940, 51380739}, {64941, 51381507},
1921
  {64942, 51289091}, {64943, 51382275}, {64944, 51383043}, {64945, 51383811},
1922
  {64946, 51384579}, {64947, 51385347}, {64948, 51353091}, {64949, 51354627},
1923
  {64950, 51386115}, {64951, 51386883}, {64952, 51387651}, {64953, 51388419},
1924
  {64954, 51389187}, {64955, 51389955}, {64956, 51389187}, {64957, 51387651},
1925
  {64958, 51390723}, {64959, 51391491}, {64960, 51392259}, {64961, 51393027},
1926
  {64962, 51393795}, {64963, 51389955}, {64964, 51347715}, {64965, 51340035},
1927
  {64966, 51394563}, {64967, 51395331}, {64968, 2}, {64975, 1},
1928
  {64976, 2}, {65008, 51396099}, {65009, 51396867}, {65010, 68174851},
1929
  {65011, 68175875}, {65012, 68176899}, {65013, 68177923}, {65014, 68178947},
1930
  {65015, 68179971}, {65016, 68180995}, {65017, 51404803}, {65018, 303063811},
1931
  {65019, 135296259}, {65020, 68189443}, {65021, 1}, {65024, 0},
1932
  {65040, 17858819}, {65041, 17859075}, {65042, 2}, {65043, 17121027},
1933
  {65044, 16848643}, {65045, 17042947}, {65046, 17043971}, {65047, 17859331},
1934
  {65048, 17859587}, {65049, 2}, {65056, 1}, {65072, 2},
1935
  {65073, 17859843}, {65074, 17860099}, {65075, 17860355}, {65077, 17047811},
1936
  {65078, 17048067}, {65079, 17860611}, {65080, 17860867}, {65081, 17861123},
1937
  {65082, 17861379}, {65083, 17861635}, {65084, 17861891}, {65085, 17862147},
1938
  {65086, 17862403}, {65087, 17077763}, {65088, 17078019}, {65089, 17862659},
1939
  {65090, 17862915}, {65091, 17863171}, {65092, 17863427}, {65093, 1},
1940
  {65095, 17863683}, {65096, 17863939}, {65097, 33820675}, {65101, 17860355},
1941
  {65104, 17858819}, {65105, 17859075}, {65106, 2}, {65108, 16848643},
1942
  {65109, 17121027}, {65110, 17043971}, {65111, 17042947}, {65112, 17859843},
1943
  {65113, 17047811}, {65114, 17048067}, {65115, 17860611}, {65116, 17860867},
1944
  {65117, 17861123}, {65118, 17861379}, {65119, 17864195}, {65120, 17864451},
1945
  {65121, 17864707}, {65122, 17047043}, {65123, 17864963}, {65124, 17865219},
1946
  {65125, 17865475}, {65126, 17047555}, {65127, 2}, {65128, 17865731},
1947
  {65129, 17865987}, {65130, 17866243}, {65131, 17866499}, {65132, 2},
1948
  {65136, 34643971}, {65137, 34644483}, {65138, 34514947}, {65139, 1},
1949
  {65140, 34515715}, {65141, 2}, {65142, 34516483}, {65143, 34534915},
1950
  {65144, 34517251}, {65145, 34535683}, {65146, 34518019}, {65147, 34536451},
1951
  {65148, 34518787}, {65149, 34644995}, {65150, 34645507}, {65151, 34646019},
1952
  {65152, 17869315}, {65153, 17869571}, {65155, 17869827}, {65157, 17870083},
1953
  {65159, 17870339}, {65161, 17688835}, {65165, 16910595}, {65167, 17695235},
1954
  {65171, 17870595}, {65173, 17698307}, {65177, 17701379}, {65181, 17693443},
1955
  {65185, 17693955}, {65189, 17696515}, {65193, 17846019}, {65195, 17736195},
1956
  {65197, 17736707}, {65199, 17743107}, {65201, 17706499}, {65205, 17756675},
1957
  {65209, 17708547}, {65213, 17709571}, {65217, 17711619}, {65221, 17712643},
1958
  {65225, 17713155}, {65229, 17714179}, {65233, 17715203}, {65237, 17718275},
1959
  {65241, 17720323}, {65245, 17722627}, {65249, 17694467}, {65253, 17729539},
1960
  {65257, 17732611}, {65261, 16911107}, {65263, 17688579}, {65265, 16912131},
1961
  {65269, 34648067}, {65271, 34648579}, {65273, 34649091}, {65275, 34633987},
1962
  {65277, 2}, {65279, 0}, {65280, 2}, {65281, 17042947},
1963
  {65282, 17872387}, {65283, 17864195}, {65284, 17865987}, {65285, 17866243},
1964
  {65286, 17864451}, {65287, 17872643}, {65288, 17047811}, {65289, 17048067},
1965
  {65290, 17864707}, {65291, 17047043}, {65292, 17858819}, {65293, 17864963},
1966
  {65294, 17207043}, {65295, 17048579}, {65296, 17045507}, {65297, 16786947},
1967
  {65298, 16785155}, {65299, 16785411}, {65300, 16787715}, {65301, 17045763},
1968
  {65302, 17046019}, {65303, 17046275}, {65304, 17046531}, {65305, 17046787},
1969
  {65306, 17121027}, {65307, 16848643}, {65308, 17865219}, {65309, 17047555},
1970
  {65310, 17865475}, {65311, 17043971}, {65312, 17866499}, {65313, 16777219},
1971
  {65314, 16777475}, {65315, 16777731}, {65316, 16777987}, {65317, 16778243},
1972
  {65318, 16778499}, {65319, 16778755}, {65320, 16779011}, {65321, 16779267},
1973
  {65322, 16779523}, {65323, 16779779}, {65324, 16780035}, {65325, 16780291},
1974
  {65326, 16780547}, {65327, 16780803}, {65328, 16781059}, {65329, 16781315},
1975
  {65330, 16781571}, {65331, 16781827}, {65332, 16782083}, {65333, 16782339},
1976
  {65334, 16782595}, {65335, 16782851}, {65336, 16783107}, {65337, 16783363},
1977
  {65338, 16783619}, {65339, 17863683}, {65340, 17865731}, {65341, 17863939},
1978
  {65342, 17872899}, {65343, 17860355}, {65344, 17037059}, {65345, 16777219},
1979
  {65346, 16777475}, {65347, 16777731}, {65348, 16777987}, {65349, 16778243},
1980
  {65350, 16778499}, {65351, 16778755}, {65352, 16779011}, {65353, 16779267},
1981
  {65354, 16779523}, {65355, 16779779}, {65356, 16780035}, {65357, 16780291},
1982
  {65358, 16780547}, {65359, 16780803}, {65360, 16781059}, {65361, 16781315},
1983
  {65362, 16781571}, {65363, 16781827}, {65364, 16782083}, {65365, 16782339},
1984
  {65366, 16782595}, {65367, 16782851}, {65368, 16783107}, {65369, 16783363},
1985
  {65370, 16783619}, {65371, 17860611}, {65372, 17873155}, {65373, 17860867},
1986
  {65374, 17873411}, {65375, 17873667}, {65376, 17873923}, {65377, 17207043},
1987
  {65378, 17862659}, {65379, 17862915}, {65380, 17859075}, {65381, 17874179},
1988
  {65382, 17327363}, {65383, 17329923}, {65384, 17372931}, {65385, 17874435},
1989
  {65386, 17374467}, {65387, 17334019}, {65388, 17874691}, {65389, 17344259},
1990
  {65390, 17390083}, {65391, 17339651}, {65392, 17328643}, {65393, 17316099},
1991
  {65394, 17316355}, {65395, 17316611}, {65396, 17316867}, {65397, 17317123},
1992
  {65398, 17317379}, {65399, 17317635}, {65400, 17317891}, {65401, 17318147},
1993
  {65402, 17209603}, {65403, 17318403}, {65404, 17318659}, {65405, 17318915},
1994
  {65406, 17319171}, {65407, 17319427}, {65408, 17319683}, {65409, 17319939},
1995
  {65410, 17320195}, {65411, 17320451}, {65412, 17209859}, {65413, 17320707},
1996
  {65414, 17320963}, {65415, 17321219}, {65416, 17321475}, {65417, 17321731},
1997
  {65418, 17321987}, {65419, 17322243}, {65420, 17322499}, {65421, 17322755},
1998
  {65422, 17323011}, {65423, 17323267}, {65424, 17323523}, {65425, 17323779},
1999
  {65426, 17324035}, {65427, 17324291}, {65428, 17324547}, {65429, 17324803},
2000
  {65430, 17325059}, {65431, 17325315}, {65432, 17325571}, {65433, 17325827},
2001
  {65434, 17326083}, {65435, 17326339}, {65436, 17326595}, {65437, 17330435},
2002
  {65438, 17208323}, {65439, 17208835}, {65440, 0}, {65441, 17210115},
2003
  {65442, 17210371}, {65443, 17210627}, {65444, 17210883}, {65445, 17211139},
2004
  {65446, 17211395}, {65447, 17211651}, {65448, 17211907}, {65449, 17212163},
2005
  {65450, 17212419}, {65451, 17212675}, {65452, 17212931}, {65453, 17213187},
2006
  {65454, 17213443}, {65455, 17213699}, {65456, 17213955}, {65457, 17214211},
2007
  {65458, 17214467}, {65459, 17214723}, {65460, 17214979}, {65461, 17215235},
2008
  {65462, 17215491}, {65463, 17215747}, {65464, 17216003}, {65465, 17216259},
2009
  {65466, 17216515}, {65467, 17216771}, {65468, 17217027}, {65469, 17217283},
2010
  {65470, 17217539}, {65471, 2}, {65474, 17217795}, {65475, 17218051},
2011
  {65476, 17218307}, {65477, 17218563}, {65478, 17218819}, {65479, 17219075},
2012
  {65480, 2}, {65482, 17219331}, {65483, 17219587}, {65484, 17219843},
2013
  {65485, 17220099}, {65486, 17220355}, {65487, 17220611}, {65488, 2},
2014
  {65490, 17220867}, {65491, 17221123}, {65492, 17221379}, {65493, 17221635},
2015
  {65494, 17221891}, {65495, 17222147}, {65496, 2}, {65498, 17222403},
2016
  {65499, 17222659}, {65500, 17222915}, {65501, 2}, {65504, 17874947},
2017
  {65505, 17875203}, {65506, 17875459}, {65507, 33561859}, {65508, 17875715},
2018
  {65509, 17875971}, {65510, 17876227}, {65511, 2}, {65512, 17876483},
2019
  {65513, 17876739}, {65514, 17876995}, {65515, 17877251}, {65516, 17877507},
2020
  {65517, 17877763}, {65518, 17878019}, {65519, 2}, {65536, 1},
2021
  {65548, 2}, {65549, 1}, {65575, 2}, {65576, 1},
2022
  {65595, 2}, {65596, 1}, {65598, 2}, {65599, 1},
2023
  {65614, 2}, {65616, 1}, {65630, 2}, {65664, 1},
2024
  {65787, 2}, {65792, 1}, {65795, 2}, {65799, 1},
2025
  {65844, 2}, {65847, 1}, {65935, 2}, {65936, 1},
2026
  {65949, 2}, {65952, 1}, {65953, 2}, {66000, 1},
2027
  {66046, 2}, {66176, 1}, {66205, 2}, {66208, 1},
2028
  {66257, 2}, {66272, 1}, {66300, 2}, {66304, 1},
2029
  {66340, 2}, {66349, 1}, {66379, 2}, {66384, 1},
2030
  {66427, 2}, {66432, 1}, {66462, 2}, {66463, 1},
2031
  {66500, 2}, {66504, 1}, {66518, 2}, {66560, 17878275},
2032
  {66561, 17878531}, {66562, 17878787}, {66563, 17879043}, {66564, 17879299},
2033
  {66565, 17879555}, {66566, 17879811}, {66567, 17880067}, {66568, 17880323},
2034
  {66569, 17880579}, {66570, 17880835}, {66571, 17881091}, {66572, 17881347},
2035
  {66573, 17881603}, {66574, 17881859}, {66575, 17882115}, {66576, 17882371},
2036
  {66577, 17882627}, {66578, 17882883}, {66579, 17883139}, {66580, 17883395},
2037
  {66581, 17883651}, {66582, 17883907}, {66583, 17884163}, {66584, 17884419},
2038
  {66585, 17884675}, {66586, 17884931}, {66587, 17885187}, {66588, 17885443},
2039
  {66589, 17885699}, {66590, 17885955}, {66591, 17886211}, {66592, 17886467},
2040
  {66593, 17886723}, {66594, 17886979}, {66595, 17887235}, {66596, 17887491},
2041
  {66597, 17887747}, {66598, 17888003}, {66599, 17888259}, {66600, 1},
2042
  {66718, 2}, {66720, 1}, {66730, 2}, {66736, 17888515},
2043
  {66737, 17888771}, {66738, 17889027}, {66739, 17889283}, {66740, 17889539},
2044
  {66741, 17889795}, {66742, 17890051}, {66743, 17890307}, {66744, 17890563},
2045
  {66745, 17890819}, {66746, 17891075}, {66747, 17891331}, {66748, 17891587},
2046
  {66749, 17891843}, {66750, 17892099}, {66751, 17892355}, {66752, 17892611},
2047
  {66753, 17892867}, {66754, 17893123}, {66755, 17893379}, {66756, 17893635},
2048
  {66757, 17893891}, {66758, 17894147}, {66759, 17894403}, {66760, 17894659},
2049
  {66761, 17894915}, {66762, 17895171}, {66763, 17895427}, {66764, 17895683},
2050
  {66765, 17895939}, {66766, 17896195}, {66767, 17896451}, {66768, 17896707},
2051
  {66769, 17896963}, {66770, 17897219}, {66771, 17897475}, {66772, 2},
2052
  {66776, 1}, {66812, 2}, {66816, 1}, {66856, 2},
2053
  {66864, 1}, {66916, 2}, {66927, 1}, {66928, 17897731},
2054
  {66929, 17897987}, {66930, 17898243}, {66931, 17898499}, {66932, 17898755},
2055
  {66933, 17899011}, {66934, 17899267}, {66935, 17899523}, {66936, 17899779},
2056
  {66937, 17900035}, {66938, 17900291}, {66939, 2}, {66940, 17900547},
2057
  {66941, 17900803}, {66942, 17901059}, {66943, 17901315}, {66944, 17901571},
2058
  {66945, 17901827}, {66946, 17902083}, {66947, 17902339}, {66948, 17902595},
2059
  {66949, 17902851}, {66950, 17903107}, {66951, 17903363}, {66952, 17903619},
2060
  {66953, 17903875}, {66954, 17904131}, {66955, 2}, {66956, 17904387},
2061
  {66957, 17904643}, {66958, 17904899}, {66959, 17905155}, {66960, 17905411},
2062
  {66961, 17905667}, {66962, 17905923}, {66963, 2}, {66964, 17906179},
2063
  {66965, 17906435}, {66966, 2}, {66967, 1}, {66978, 2},
2064
  {66979, 1}, {66994, 2}, {66995, 1}, {67002, 2},
2065
  {67003, 1}, {67005, 2}, {67008, 1}, {67060, 2},
2066
  {67072, 1}, {67383, 2}, {67392, 1}, {67414, 2},
2067
  {67424, 1}, {67432, 2}, {67456, 1}, {67457, 17906691},
2068
  {67458, 17906947}, {67459, 16791043}, {67460, 17907203}, {67461, 16814083},
2069
  {67462, 2}, {67463, 17907459}, {67464, 17907715}, {67465, 17907971},
2070
  {67466, 17908227}, {67467, 16815363}, {67468, 16815619}, {67469, 17908483},
2071
  {67470, 17908739}, {67471, 17908995}, {67472, 17909251}, {67473, 17527555},
2072
  {67474, 17909507}, {67475, 16817155}, {67476, 17909763}, {67477, 16802051},
2073
  {67478, 17910019}, {67479, 17910275}, {67480, 17910531}, {67481, 17910787},
2074
  {67482, 17911043}, {67483, 17523459}, {67484, 17911299}, {67485, 17911555},
2075
  {67486, 17911811}, {67487, 17912067}, {67488, 17912323}, {67489, 17912579},
2076
  {67490, 16795395}, {67491, 17912835}, {67492, 17913091}, {67493, 16781315},
2077
  {67494, 17913347}, {67495, 17913603}, {67496, 17135875}, {67497, 17913859},
2078
  {67498, 16819971}, {67499, 17914115}, {67500, 17914371}, {67501, 17914627},
2079
  {67502, 17914883}, {67503, 16820995}, {67504, 17915139}, {67505, 2},
2080
  {67506, 17915395}, {67507, 17915651}, {67508, 17915907}, {67509, 17916163},
2081
  {67510, 17916419}, {67511, 17916675}, {67512, 17916931}, {67513, 17917187},
2082
  {67514, 17917443}, {67515, 2}, {67584, 1}, {67590, 2},
2083
  {67592, 1}, {67593, 2}, {67594, 1}, {67638, 2},
2084
  {67639, 1}, {67641, 2}, {67644, 1}, {67645, 2},
2085
  {67647, 1}, {67670, 2}, {67671, 1}, {67743, 2},
2086
  {67751, 1}, {67760, 2}, {67808, 1}, {67827, 2},
2087
  {67828, 1}, {67830, 2}, {67835, 1}, {67868, 2},
2088
  {67871, 1}, {67898, 2}, {67903, 1}, {67904, 2},
2089
  {67968, 1}, {68024, 2}, {68028, 1}, {68048, 2},
2090
  {68050, 1}, {68100, 2}, {68101, 1}, {68103, 2},
2091
  {68108, 1}, {68116, 2}, {68117, 1}, {68120, 2},
2092
  {68121, 1}, {68150, 2}, {68152, 1}, {68155, 2},
2093
  {68159, 1}, {68169, 2}, {68176, 1}, {68185, 2},
2094
  {68192, 1}, {68256, 2}, {68288, 1}, {68327, 2},
2095
  {68331, 1}, {68343, 2}, {68352, 1}, {68406, 2},
2096
  {68409, 1}, {68438, 2}, {68440, 1}, {68467, 2},
2097
  {68472, 1}, {68498, 2}, {68505, 1}, {68509, 2},
2098
  {68521, 1}, {68528, 2}, {68608, 1}, {68681, 2},
2099
  {68736, 17917699}, {68737, 17917955}, {68738, 17918211}, {68739, 17918467},
2100
  {68740, 17918723}, {68741, 17918979}, {68742, 17919235}, {68743, 17919491},
2101
  {68744, 17919747}, {68745, 17920003}, {68746, 17920259}, {68747, 17920515},
2102
  {68748, 17920771}, {68749, 17921027}, {68750, 17921283}, {68751, 17921539},
2103
  {68752, 17921795}, {68753, 17922051}, {68754, 17922307}, {68755, 17922563},
2104
  {68756, 17922819}, {68757, 17923075}, {68758, 17923331}, {68759, 17923587},
2105
  {68760, 17923843}, {68761, 17924099}, {68762, 17924355}, {68763, 17924611},
2106
  {68764, 17924867}, {68765, 17925123}, {68766, 17925379}, {68767, 17925635},
2107
  {68768, 17925891}, {68769, 17926147}, {68770, 17926403}, {68771, 17926659},
2108
  {68772, 17926915}, {68773, 17927171}, {68774, 17927427}, {68775, 17927683},
2109
  {68776, 17927939}, {68777, 17928195}, {68778, 17928451}, {68779, 17928707},
2110
  {68780, 17928963}, {68781, 17929219}, {68782, 17929475}, {68783, 17929731},
2111
  {68784, 17929987}, {68785, 17930243}, {68786, 17930499}, {68787, 2},
2112
  {68800, 1}, {68851, 2}, {68858, 1}, {68904, 2},
2113
  {68912, 1}, {68922, 2}, {68928, 1}, {68944, 17930755},
2114
  {68945, 17931011}, {68946, 17931267}, {68947, 17931523}, {68948, 17931779},
2115
  {68949, 17932035}, {68950, 17932291}, {68951, 17932547}, {68952, 17932803},
2116
  {68953, 17933059}, {68954, 17933315}, {68955, 17933571}, {68956, 17933827},
2117
  {68957, 17934083}, {68958, 17934339}, {68959, 17934595}, {68960, 17934851},
2118
  {68961, 17935107}, {68962, 17935363}, {68963, 17935619}, {68964, 17935875},
2119
  {68965, 17936131}, {68966, 2}, {68969, 1}, {68998, 2},
2120
  {69006, 1}, {69008, 2}, {69216, 1}, {69247, 2},
2121
  {69248, 1}, {69290, 2}, {69291, 1}, {69294, 2},
2122
  {69296, 1}, {69298, 2}, {69314, 1}, {69317, 2},
2123
  {69372, 1}, {69416, 2}, {69424, 1}, {69466, 2},
2124
  {69488, 1}, {69514, 2}, {69552, 1}, {69580, 2},
2125
  {69600, 1}, {69623, 2}, {69632, 1}, {69710, 2},
2126
  {69714, 1}, {69750, 2}, {69759, 1}, {69821, 2},
2127
  {69822, 1}, {69827, 2}, {69840, 1}, {69865, 2},
2128
  {69872, 1}, {69882, 2}, {69888, 1}, {69941, 2},
2129
  {69942, 1}, {69960, 2}, {69968, 1}, {70007, 2},
2130
  {70016, 1}, {70112, 2}, {70113, 1}, {70133, 2},
2131
  {70144, 1}, {70162, 2}, {70163, 1}, {70210, 2},
2132
  {70272, 1}, {70279, 2}, {70280, 1}, {70281, 2},
2133
  {70282, 1}, {70286, 2}, {70287, 1}, {70302, 2},
2134
  {70303, 1}, {70314, 2}, {70320, 1}, {70379, 2},
2135
  {70384, 1}, {70394, 2}, {70400, 1}, {70404, 2},
2136
  {70405, 1}, {70413, 2}, {70415, 1}, {70417, 2},
2137
  {70419, 1}, {70441, 2}, {70442, 1}, {70449, 2},
2138
  {70450, 1}, {70452, 2}, {70453, 1}, {70458, 2},
2139
  {70459, 1}, {70469, 2}, {70471, 1}, {70473, 2},
2140
  {70475, 1}, {70478, 2}, {70480, 1}, {70481, 2},
2141
  {70487, 1}, {70488, 2}, {70493, 1}, {70500, 2},
2142
  {70502, 1}, {70509, 2}, {70512, 1}, {70517, 2},
2143
  {70528, 1}, {70538, 2}, {70539, 1}, {70540, 2},
2144
  {70542, 1}, {70543, 2}, {70544, 1}, {70582, 2},
2145
  {70583, 1}, {70593, 2}, {70594, 1}, {70595, 2},
2146
  {70597, 1}, {70598, 2}, {70599, 1}, {70603, 2},
2147
  {70604, 1}, {70614, 2}, {70615, 1}, {70617, 2},
2148
  {70625, 1}, {70627, 2}, {70656, 1}, {70748, 2},
2149
  {70749, 1}, {70754, 2}, {70784, 1}, {70856, 2},
2150
  {70864, 1}, {70874, 2}, {71040, 1}, {71094, 2},
2151
  {71096, 1}, {71134, 2}, {71168, 1}, {71237, 2},
2152
  {71248, 1}, {71258, 2}, {71264, 1}, {71277, 2},
2153
  {71296, 1}, {71354, 2}, {71360, 1}, {71370, 2},
2154
  {71376, 1}, {71396, 2}, {71424, 1}, {71451, 2},
2155
  {71453, 1}, {71468, 2}, {71472, 1}, {71495, 2},
2156
  {71680, 1}, {71740, 2}, {71840, 17936387}, {71841, 17936643},
2157
  {71842, 17936899}, {71843, 17937155}, {71844, 17937411}, {71845, 17937667},
2158
  {71846, 17937923}, {71847, 17938179}, {71848, 17938435}, {71849, 17938691},
2159
  {71850, 17938947}, {71851, 17939203}, {71852, 17939459}, {71853, 17939715},
2160
  {71854, 17939971}, {71855, 17940227}, {71856, 17940483}, {71857, 17940739},
2161
  {71858, 17940995}, {71859, 17941251}, {71860, 17941507}, {71861, 17941763},
2162
  {71862, 17942019}, {71863, 17942275}, {71864, 17942531}, {71865, 17942787},
2163
  {71866, 17943043}, {71867, 17943299}, {71868, 17943555}, {71869, 17943811},
2164
  {71870, 17944067}, {71871, 17944323}, {71872, 1}, {71923, 2},
2165
  {71935, 1}, {71943, 2}, {71945, 1}, {71946, 2},
2166
  {71948, 1}, {71956, 2}, {71957, 1}, {71959, 2},
2167
  {71960, 1}, {71990, 2}, {71991, 1}, {71993, 2},
2168
  {71995, 1}, {72007, 2}, {72016, 1}, {72026, 2},
2169
  {72096, 1}, {72104, 2}, {72106, 1}, {72152, 2},
2170
  {72154, 1}, {72165, 2}, {72192, 1}, {72264, 2},
2171
  {72272, 1}, {72355, 2}, {72368, 1}, {72441, 2},
2172
  {72448, 1}, {72458, 2}, {72640, 1}, {72674, 2},
2173
  {72688, 1}, {72698, 2}, {72704, 1}, {72713, 2},
2174
  {72714, 1}, {72759, 2}, {72760, 1}, {72774, 2},
2175
  {72784, 1}, {72813, 2}, {72816, 1}, {72848, 2},
2176
  {72850, 1}, {72872, 2}, {72873, 1}, {72887, 2},
2177
  {72960, 1}, {72967, 2}, {72968, 1}, {72970, 2},
2178
  {72971, 1}, {73015, 2}, {73018, 1}, {73019, 2},
2179
  {73020, 1}, {73022, 2}, {73023, 1}, {73032, 2},
2180
  {73040, 1}, {73050, 2}, {73056, 1}, {73062, 2},
2181
  {73063, 1}, {73065, 2}, {73066, 1}, {73103, 2},
2182
  {73104, 1}, {73106, 2}, {73107, 1}, {73113, 2},
2183
  {73120, 1}, {73130, 2}, {73440, 1}, {73465, 2},
2184
  {73472, 1}, {73489, 2}, {73490, 1}, {73531, 2},
2185
  {73534, 1}, {73563, 2}, {73648, 1}, {73649, 2},
2186
  {73664, 1}, {73714, 2}, {73727, 1}, {74650, 2},
2187
  {74752, 1}, {74863, 2}, {74864, 1}, {74869, 2},
2188
  {74880, 1}, {75076, 2}, {77712, 1}, {77811, 2},
2189
  {77824, 1}, {78896, 2}, {78912, 1}, {78934, 2},
2190
  {78944, 1}, {82939, 2}, {82944, 1}, {83527, 2},
2191
  {90368, 1}, {90426, 2}, {92160, 1}, {92729, 2},
2192
  {92736, 1}, {92767, 2}, {92768, 1}, {92778, 2},
2193
  {92782, 1}, {92863, 2}, {92864, 1}, {92874, 2},
2194
  {92880, 1}, {92910, 2}, {92912, 1}, {92918, 2},
2195
  {92928, 1}, {92998, 2}, {93008, 1}, {93018, 2},
2196
  {93019, 1}, {93026, 2}, {93027, 1}, {93048, 2},
2197
  {93053, 1}, {93072, 2}, {93504, 1}, {93562, 2},
2198
  {93760, 17944579}, {93761, 17944835}, {93762, 17945091}, {93763, 17945347},
2199
  {93764, 17945603}, {93765, 17945859}, {93766, 17946115}, {93767, 17946371},
2200
  {93768, 17946627}, {93769, 17946883}, {93770, 17947139}, {93771, 17947395},
2201
  {93772, 17947651}, {93773, 17947907}, {93774, 17948163}, {93775, 17948419},
2202
  {93776, 17948675}, {93777, 17948931}, {93778, 17949187}, {93779, 17949443},
2203
  {93780, 17949699}, {93781, 17949955}, {93782, 17950211}, {93783, 17950467},
2204
  {93784, 17950723}, {93785, 17950979}, {93786, 17951235}, {93787, 17951491},
2205
  {93788, 17951747}, {93789, 17952003}, {93790, 17952259}, {93791, 17952515},
2206
  {93792, 1}, {93851, 2}, {93952, 1}, {94027, 2},
2207
  {94031, 1}, {94088, 2}, {94095, 1}, {94112, 2},
2208
  {94176, 1}, {94181, 2}, {94192, 1}, {94194, 2},
2209
  {94208, 1}, {100344, 2}, {100352, 1}, {101590, 2},
2210
  {101631, 1}, {101641, 2}, {110576, 1}, {110580, 2},
2211
  {110581, 1}, {110588, 2}, {110589, 1}, {110591, 2},
2212
  {110592, 1}, {110883, 2}, {110898, 1}, {110899, 2},
2213
  {110928, 1}, {110931, 2}, {110933, 1}, {110934, 2},
2214
  {110948, 1}, {110952, 2}, {110960, 1}, {111356, 2},
2215
  {113664, 1}, {113771, 2}, {113776, 1}, {113789, 2},
2216
  {113792, 1}, {113801, 2}, {113808, 1}, {113818, 2},
2217
  {113820, 1}, {113824, 0}, {113828, 2}, {117760, 1},
2218
  {117974, 16777219}, {117975, 16777475}, {117976, 16777731}, {117977, 16777987},
2219
  {117978, 16778243}, {117979, 16778499}, {117980, 16778755}, {117981, 16779011},
2220
  {117982, 16779267}, {117983, 16779523}, {117984, 16779779}, {117985, 16780035},
2221
  {117986, 16780291}, {117987, 16780547}, {117988, 16780803}, {117989, 16781059},
2222
  {117990, 16781315}, {117991, 16781571}, {117992, 16781827}, {117993, 16782083},
2223
  {117994, 16782339}, {117995, 16782595}, {117996, 16782851}, {117997, 16783107},
2224
  {117998, 16783363}, {117999, 16783619}, {118000, 17045507}, {118001, 16786947},
2225
  {118002, 16785155}, {118003, 16785411}, {118004, 16787715}, {118005, 17045763},
2226
  {118006, 17046019}, {118007, 17046275}, {118008, 17046531}, {118009, 17046787},
2227
  {118010, 2}, {118016, 1}, {118452, 2}, {118528, 1},
2228
  {118574, 2}, {118576, 1}, {118599, 2}, {118608, 1},
2229
  {118724, 2}, {118784, 1}, {119030, 2}, {119040, 1},
2230
  {119079, 2}, {119081, 1}, {119134, 34729987}, {119135, 34730499},
2231
  {119136, 51508227}, {119137, 51508995}, {119138, 51509763}, {119139, 51510531},
2232
  {119140, 51511299}, {119141, 1}, {119155, 0}, {119163, 1},
2233
  {119227, 34734851}, {119228, 34735363}, {119229, 51513091}, {119230, 51513859},
2234
  {119231, 51514627}, {119232, 51515395}, {119233, 1}, {119275, 2},
2235
  {119296, 1}, {119366, 2}, {119488, 1}, {119508, 2},
2236
  {119520, 1}, {119540, 2}, {119552, 1}, {119639, 2},
2237
  {119648, 1}, {119673, 2}, {119808, 16777219}, {119809, 16777475},
2238
  {119810, 16777731}, {119811, 16777987}, {119812, 16778243}, {119813, 16778499},
2239
  {119814, 16778755}, {119815, 16779011}, {119816, 16779267}, {119817, 16779523},
2240
  {119818, 16779779}, {119819, 16780035}, {119820, 16780291}, {119821, 16780547},
2241
  {119822, 16780803}, {119823, 16781059}, {119824, 16781315}, {119825, 16781571},
2242
  {119826, 16781827}, {119827, 16782083}, {119828, 16782339}, {119829, 16782595},
2243
  {119830, 16782851}, {119831, 16783107}, {119832, 16783363}, {119833, 16783619},
2244
  {119834, 16777219}, {119835, 16777475}, {119836, 16777731}, {119837, 16777987},
2245
  {119838, 16778243}, {119839, 16778499}, {119840, 16778755}, {119841, 16779011},
2246
  {119842, 16779267}, {119843, 16779523}, {119844, 16779779}, {119845, 16780035},
2247
  {119846, 16780291}, {119847, 16780547}, {119848, 16780803}, {119849, 16781059},
2248
  {119850, 16781315}, {119851, 16781571}, {119852, 16781827}, {119853, 16782083},
2249
  {119854, 16782339}, {119855, 16782595}, {119856, 16782851}, {119857, 16783107},
2250
  {119858, 16783363}, {119859, 16783619}, {119860, 16777219}, {119861, 16777475},
2251
  {119862, 16777731}, {119863, 16777987}, {119864, 16778243}, {119865, 16778499},
2252
  {119866, 16778755}, {119867, 16779011}, {119868, 16779267}, {119869, 16779523},
2253
  {119870, 16779779}, {119871, 16780035}, {119872, 16780291}, {119873, 16780547},
2254
  {119874, 16780803}, {119875, 16781059}, {119876, 16781315}, {119877, 16781571},
2255
  {119878, 16781827}, {119879, 16782083}, {119880, 16782339}, {119881, 16782595},
2256
  {119882, 16782851}, {119883, 16783107}, {119884, 16783363}, {119885, 16783619},
2257
  {119886, 16777219}, {119887, 16777475}, {119888, 16777731}, {119889, 16777987},
2258
  {119890, 16778243}, {119891, 16778499}, {119892, 16778755}, {119893, 2},
2259
  {119894, 16779267}, {119895, 16779523}, {119896, 16779779}, {119897, 16780035},
2260
  {119898, 16780291}, {119899, 16780547}, {119900, 16780803}, {119901, 16781059},
2261
  {119902, 16781315}, {119903, 16781571}, {119904, 16781827}, {119905, 16782083},
2262
  {119906, 16782339}, {119907, 16782595}, {119908, 16782851}, {119909, 16783107},
2263
  {119910, 16783363}, {119911, 16783619}, {119912, 16777219}, {119913, 16777475},
2264
  {119914, 16777731}, {119915, 16777987}, {119916, 16778243}, {119917, 16778499},
2265
  {119918, 16778755}, {119919, 16779011}, {119920, 16779267}, {119921, 16779523},
2266
  {119922, 16779779}, {119923, 16780035}, {119924, 16780291}, {119925, 16780547},
2267
  {119926, 16780803}, {119927, 16781059}, {119928, 16781315}, {119929, 16781571},
2268
  {119930, 16781827}, {119931, 16782083}, {119932, 16782339}, {119933, 16782595},
2269
  {119934, 16782851}, {119935, 16783107}, {119936, 16783363}, {119937, 16783619},
2270
  {119938, 16777219}, {119939, 16777475}, {119940, 16777731}, {119941, 16777987},
2271
  {119942, 16778243}, {119943, 16778499}, {119944, 16778755}, {119945, 16779011},
2272
  {119946, 16779267}, {119947, 16779523}, {119948, 16779779}, {119949, 16780035},
2273
  {119950, 16780291}, {119951, 16780547}, {119952, 16780803}, {119953, 16781059},
2274
  {119954, 16781315}, {119955, 16781571}, {119956, 16781827}, {119957, 16782083},
2275
  {119958, 16782339}, {119959, 16782595}, {119960, 16782851}, {119961, 16783107},
2276
  {119962, 16783363}, {119963, 16783619}, {119964, 16777219}, {119965, 2},
2277
  {119966, 16777731}, {119967, 16777987}, {119968, 2}, {119970, 16778755},
2278
  {119971, 2}, {119973, 16779523}, {119974, 16779779}, {119975, 2},
2279
  {119977, 16780547}, {119978, 16780803}, {119979, 16781059}, {119980, 16781315},
2280
  {119981, 2}, {119982, 16781827}, {119983, 16782083}, {119984, 16782339},
2281
  {119985, 16782595}, {119986, 16782851}, {119987, 16783107}, {119988, 16783363},
2282
  {119989, 16783619}, {119990, 16777219}, {119991, 16777475}, {119992, 16777731},
2283
  {119993, 16777987}, {119994, 2}, {119995, 16778499}, {119996, 2},
2284
  {119997, 16779011}, {119998, 16779267}, {119999, 16779523}, {120000, 16779779},
2285
  {120001, 16780035}, {120002, 16780291}, {120003, 16780547}, {120004, 2},
2286
  {120005, 16781059}, {120006, 16781315}, {120007, 16781571}, {120008, 16781827},
2287
  {120009, 16782083}, {120010, 16782339}, {120011, 16782595}, {120012, 16782851},
2288
  {120013, 16783107}, {120014, 16783363}, {120015, 16783619}, {120016, 16777219},
2289
  {120017, 16777475}, {120018, 16777731}, {120019, 16777987}, {120020, 16778243},
2290
  {120021, 16778499}, {120022, 16778755}, {120023, 16779011}, {120024, 16779267},
2291
  {120025, 16779523}, {120026, 16779779}, {120027, 16780035}, {120028, 16780291},
2292
  {120029, 16780547}, {120030, 16780803}, {120031, 16781059}, {120032, 16781315},
2293
  {120033, 16781571}, {120034, 16781827}, {120035, 16782083}, {120036, 16782339},
2294
  {120037, 16782595}, {120038, 16782851}, {120039, 16783107}, {120040, 16783363},
2295
  {120041, 16783619}, {120042, 16777219}, {120043, 16777475}, {120044, 16777731},
2296
  {120045, 16777987}, {120046, 16778243}, {120047, 16778499}, {120048, 16778755},
2297
  {120049, 16779011}, {120050, 16779267}, {120051, 16779523}, {120052, 16779779},
2298
  {120053, 16780035}, {120054, 16780291}, {120055, 16780547}, {120056, 16780803},
2299
  {120057, 16781059}, {120058, 16781315}, {120059, 16781571}, {120060, 16781827},
2300
  {120061, 16782083}, {120062, 16782339}, {120063, 16782595}, {120064, 16782851},
2301
  {120065, 16783107}, {120066, 16783363}, {120067, 16783619}, {120068, 16777219},
2302
  {120069, 16777475}, {120070, 2}, {120071, 16777987}, {120072, 16778243},
2303
  {120073, 16778499}, {120074, 16778755}, {120075, 2}, {120077, 16779523},
2304
  {120078, 16779779}, {120079, 16780035}, {120080, 16780291}, {120081, 16780547},
2305
  {120082, 16780803}, {120083, 16781059}, {120084, 16781315}, {120085, 2},
2306
  {120086, 16781827}, {120087, 16782083}, {120088, 16782339}, {120089, 16782595},
2307
  {120090, 16782851}, {120091, 16783107}, {120092, 16783363}, {120093, 2},
2308
  {120094, 16777219}, {120095, 16777475}, {120096, 16777731}, {120097, 16777987},
2309
  {120098, 16778243}, {120099, 16778499}, {120100, 16778755}, {120101, 16779011},
2310
  {120102, 16779267}, {120103, 16779523}, {120104, 16779779}, {120105, 16780035},
2311
  {120106, 16780291}, {120107, 16780547}, {120108, 16780803}, {120109, 16781059},
2312
  {120110, 16781315}, {120111, 16781571}, {120112, 16781827}, {120113, 16782083},
2313
  {120114, 16782339}, {120115, 16782595}, {120116, 16782851}, {120117, 16783107},
2314
  {120118, 16783363}, {120119, 16783619}, {120120, 16777219}, {120121, 16777475},
2315
  {120122, 2}, {120123, 16777987}, {120124, 16778243}, {120125, 16778499},
2316
  {120126, 16778755}, {120127, 2}, {120128, 16779267}, {120129, 16779523},
2317
  {120130, 16779779}, {120131, 16780035}, {120132, 16780291}, {120133, 2},
2318
  {120134, 16780803}, {120135, 2}, {120138, 16781827}, {120139, 16782083},
2319
  {120140, 16782339}, {120141, 16782595}, {120142, 16782851}, {120143, 16783107},
2320
  {120144, 16783363}, {120145, 2}, {120146, 16777219}, {120147, 16777475},
2321
  {120148, 16777731}, {120149, 16777987}, {120150, 16778243}, {120151, 16778499},
2322
  {120152, 16778755}, {120153, 16779011}, {120154, 16779267}, {120155, 16779523},
2323
  {120156, 16779779}, {120157, 16780035}, {120158, 16780291}, {120159, 16780547},
2324
  {120160, 16780803}, {120161, 16781059}, {120162, 16781315}, {120163, 16781571},
2325
  {120164, 16781827}, {120165, 16782083}, {120166, 16782339}, {120167, 16782595},
2326
  {120168, 16782851}, {120169, 16783107}, {120170, 16783363}, {120171, 16783619},
2327
  {120172, 16777219}, {120173, 16777475}, {120174, 16777731}, {120175, 16777987},
2328
  {120176, 16778243}, {120177, 16778499}, {120178, 16778755}, {120179, 16779011},
2329
  {120180, 16779267}, {120181, 16779523}, {120182, 16779779}, {120183, 16780035},
2330
  {120184, 16780291}, {120185, 16780547}, {120186, 16780803}, {120187, 16781059},
2331
  {120188, 16781315}, {120189, 16781571}, {120190, 16781827}, {120191, 16782083},
2332
  {120192, 16782339}, {120193, 16782595}, {120194, 16782851}, {120195, 16783107},
2333
  {120196, 16783363}, {120197, 16783619}, {120198, 16777219}, {120199, 16777475},
2334
  {120200, 16777731}, {120201, 16777987}, {120202, 16778243}, {120203, 16778499},
2335
  {120204, 16778755}, {120205, 16779011}, {120206, 16779267}, {120207, 16779523},
2336
  {120208, 16779779}, {120209, 16780035}, {120210, 16780291}, {120211, 16780547},
2337
  {120212, 16780803}, {120213, 16781059}, {120214, 16781315}, {120215, 16781571},
2338
  {120216, 16781827}, {120217, 16782083}, {120218, 16782339}, {120219, 16782595},
2339
  {120220, 16782851}, {120221, 16783107}, {120222, 16783363}, {120223, 16783619},
2340
  {120224, 16777219}, {120225, 16777475}, {120226, 16777731}, {120227, 16777987},
2341
  {120228, 16778243}, {120229, 16778499}, {120230, 16778755}, {120231, 16779011},
2342
  {120232, 16779267}, {120233, 16779523}, {120234, 16779779}, {120235, 16780035},
2343
  {120236, 16780291}, {120237, 16780547}, {120238, 16780803}, {120239, 16781059},
2344
  {120240, 16781315}, {120241, 16781571}, {120242, 16781827}, {120243, 16782083},
2345
  {120244, 16782339}, {120245, 16782595}, {120246, 16782851}, {120247, 16783107},
2346
  {120248, 16783363}, {120249, 16783619}, {120250, 16777219}, {120251, 16777475},
2347
  {120252, 16777731}, {120253, 16777987}, {120254, 16778243}, {120255, 16778499},
2348
  {120256, 16778755}, {120257, 16779011}, {120258, 16779267}, {120259, 16779523},
2349
  {120260, 16779779}, {120261, 16780035}, {120262, 16780291}, {120263, 16780547},
2350
  {120264, 16780803}, {120265, 16781059}, {120266, 16781315}, {120267, 16781571},
2351
  {120268, 16781827}, {120269, 16782083}, {120270, 16782339}, {120271, 16782595},
2352
  {120272, 16782851}, {120273, 16783107}, {120274, 16783363}, {120275, 16783619},
2353
  {120276, 16777219}, {120277, 16777475}, {120278, 16777731}, {120279, 16777987},
2354
  {120280, 16778243}, {120281, 16778499}, {120282, 16778755}, {120283, 16779011},
2355
  {120284, 16779267}, {120285, 16779523}, {120286, 16779779}, {120287, 16780035},
2356
  {120288, 16780291}, {120289, 16780547}, {120290, 16780803}, {120291, 16781059},
2357
  {120292, 16781315}, {120293, 16781571}, {120294, 16781827}, {120295, 16782083},
2358
  {120296, 16782339}, {120297, 16782595}, {120298, 16782851}, {120299, 16783107},
2359
  {120300, 16783363}, {120301, 16783619}, {120302, 16777219}, {120303, 16777475},
2360
  {120304, 16777731}, {120305, 16777987}, {120306, 16778243}, {120307, 16778499},
2361
  {120308, 16778755}, {120309, 16779011}, {120310, 16779267}, {120311, 16779523},
2362
  {120312, 16779779}, {120313, 16780035}, {120314, 16780291}, {120315, 16780547},
2363
  {120316, 16780803}, {120317, 16781059}, {120318, 16781315}, {120319, 16781571},
2364
  {120320, 16781827}, {120321, 16782083}, {120322, 16782339}, {120323, 16782595},
2365
  {120324, 16782851}, {120325, 16783107}, {120326, 16783363}, {120327, 16783619},
2366
  {120328, 16777219}, {120329, 16777475}, {120330, 16777731}, {120331, 16777987},
2367
  {120332, 16778243}, {120333, 16778499}, {120334, 16778755}, {120335, 16779011},
2368
  {120336, 16779267}, {120337, 16779523}, {120338, 16779779}, {120339, 16780035},
2369
  {120340, 16780291}, {120341, 16780547}, {120342, 16780803}, {120343, 16781059},
2370
  {120344, 16781315}, {120345, 16781571}, {120346, 16781827}, {120347, 16782083},
2371
  {120348, 16782339}, {120349, 16782595}, {120350, 16782851}, {120351, 16783107},
2372
  {120352, 16783363}, {120353, 16783619}, {120354, 16777219}, {120355, 16777475},
2373
  {120356, 16777731}, {120357, 16777987}, {120358, 16778243}, {120359, 16778499},
2374
  {120360, 16778755}, {120361, 16779011}, {120362, 16779267}, {120363, 16779523},
2375
  {120364, 16779779}, {120365, 16780035}, {120366, 16780291}, {120367, 16780547},
2376
  {120368, 16780803}, {120369, 16781059}, {120370, 16781315}, {120371, 16781571},
2377
  {120372, 16781827}, {120373, 16782083}, {120374, 16782339}, {120375, 16782595},
2378
  {120376, 16782851}, {120377, 16783107}, {120378, 16783363}, {120379, 16783619},
2379
  {120380, 16777219}, {120381, 16777475}, {120382, 16777731}, {120383, 16777987},
2380
  {120384, 16778243}, {120385, 16778499}, {120386, 16778755}, {120387, 16779011},
2381
  {120388, 16779267}, {120389, 16779523}, {120390, 16779779}, {120391, 16780035},
2382
  {120392, 16780291}, {120393, 16780547}, {120394, 16780803}, {120395, 16781059},
2383
  {120396, 16781315}, {120397, 16781571}, {120398, 16781827}, {120399, 16782083},
2384
  {120400, 16782339}, {120401, 16782595}, {120402, 16782851}, {120403, 16783107},
2385
  {120404, 16783363}, {120405, 16783619}, {120406, 16777219}, {120407, 16777475},
2386
  {120408, 16777731}, {120409, 16777987}, {120410, 16778243}, {120411, 16778499},
2387
  {120412, 16778755}, {120413, 16779011}, {120414, 16779267}, {120415, 16779523},
2388
  {120416, 16779779}, {120417, 16780035}, {120418, 16780291}, {120419, 16780547},
2389
  {120420, 16780803}, {120421, 16781059}, {120422, 16781315}, {120423, 16781571},
2390
  {120424, 16781827}, {120425, 16782083}, {120426, 16782339}, {120427, 16782595},
2391
  {120428, 16782851}, {120429, 16783107}, {120430, 16783363}, {120431, 16783619},
2392
  {120432, 16777219}, {120433, 16777475}, {120434, 16777731}, {120435, 16777987},
2393
  {120436, 16778243}, {120437, 16778499}, {120438, 16778755}, {120439, 16779011},
2394
  {120440, 16779267}, {120441, 16779523}, {120442, 16779779}, {120443, 16780035},
2395
  {120444, 16780291}, {120445, 16780547}, {120446, 16780803}, {120447, 16781059},
2396
  {120448, 16781315}, {120449, 16781571}, {120450, 16781827}, {120451, 16782083},
2397
  {120452, 16782339}, {120453, 16782595}, {120454, 16782851}, {120455, 16783107},
2398
  {120456, 16783363}, {120457, 16783619}, {120458, 16777219}, {120459, 16777475},
2399
  {120460, 16777731}, {120461, 16777987}, {120462, 16778243}, {120463, 16778499},
2400
  {120464, 16778755}, {120465, 16779011}, {120466, 16779267}, {120467, 16779523},
2401
  {120468, 16779779}, {120469, 16780035}, {120470, 16780291}, {120471, 16780547},
2402
  {120472, 16780803}, {120473, 16781059}, {120474, 16781315}, {120475, 16781571},
2403
  {120476, 16781827}, {120477, 16782083}, {120478, 16782339}, {120479, 16782595},
2404
  {120480, 16782851}, {120481, 16783107}, {120482, 16783363}, {120483, 16783619},
2405
  {120484, 17961731}, {120485, 17961987}, {120486, 2}, {120488, 16851715},
2406
  {120489, 16851971}, {120490, 16852227}, {120491, 16852483}, {120492, 16852739},
2407
  {120493, 16852995}, {120494, 16853251}, {120495, 16853507}, {120496, 16846851},
2408
  {120497, 16853763}, {120498, 16854019}, {120499, 16786179}, {120500, 16854275},
2409
  {120501, 16854531}, {120502, 16854787}, {120503, 16855043}, {120504, 16855299},
2410
  {120505, 16853507}, {120506, 16855555}, {120507, 16855811}, {120508, 16856067},
2411
  {120509, 16856323}, {120510, 16856579}, {120511, 16856835}, {120512, 16857091},
2412
  {120513, 17962243}, {120514, 16851715}, {120515, 16851971}, {120516, 16852227},
2413
  {120517, 16852483}, {120518, 16852739}, {120519, 16852995}, {120520, 16853251},
2414
  {120521, 16853507}, {120522, 16846851}, {120523, 16853763}, {120524, 16854019},
2415
  {120525, 16786179}, {120526, 16854275}, {120527, 16854531}, {120528, 16854787},
2416
  {120529, 16855043}, {120530, 16855299}, {120531, 16855555}, {120533, 16855811},
2417
  {120534, 16856067}, {120535, 16856323}, {120536, 16856579}, {120537, 16856835},
2418
  {120538, 16857091}, {120539, 17962499}, {120540, 16852739}, {120541, 16853507},
2419
  {120542, 16853763}, {120543, 16856323}, {120544, 16855299}, {120545, 16855043},
2420
  {120546, 16851715}, {120547, 16851971}, {120548, 16852227}, {120549, 16852483},
2421
  {120550, 16852739}, {120551, 16852995}, {120552, 16853251}, {120553, 16853507},
2422
  {120554, 16846851}, {120555, 16853763}, {120556, 16854019}, {120557, 16786179},
2423
  {120558, 16854275}, {120559, 16854531}, {120560, 16854787}, {120561, 16855043},
2424
  {120562, 16855299}, {120563, 16853507}, {120564, 16855555}, {120565, 16855811},
2425
  {120566, 16856067}, {120567, 16856323}, {120568, 16856579}, {120569, 16856835},
2426
  {120570, 16857091}, {120571, 17962243}, {120572, 16851715}, {120573, 16851971},
2427
  {120574, 16852227}, {120575, 16852483}, {120576, 16852739}, {120577, 16852995},
2428
  {120578, 16853251}, {120579, 16853507}, {120580, 16846851}, {120581, 16853763},
2429
  {120582, 16854019}, {120583, 16786179}, {120584, 16854275}, {120585, 16854531},
2430
  {120586, 16854787}, {120587, 16855043}, {120588, 16855299}, {120589, 16855555},
2431
  {120591, 16855811}, {120592, 16856067}, {120593, 16856323}, {120594, 16856579},
2432
  {120595, 16856835}, {120596, 16857091}, {120597, 17962499}, {120598, 16852739},
2433
  {120599, 16853507}, {120600, 16853763}, {120601, 16856323}, {120602, 16855299},
2434
  {120603, 16855043}, {120604, 16851715}, {120605, 16851971}, {120606, 16852227},
2435
  {120607, 16852483}, {120608, 16852739}, {120609, 16852995}, {120610, 16853251},
2436
  {120611, 16853507}, {120612, 16846851}, {120613, 16853763}, {120614, 16854019},
2437
  {120615, 16786179}, {120616, 16854275}, {120617, 16854531}, {120618, 16854787},
2438
  {120619, 16855043}, {120620, 16855299}, {120621, 16853507}, {120622, 16855555},
2439
  {120623, 16855811}, {120624, 16856067}, {120625, 16856323}, {120626, 16856579},
2440
  {120627, 16856835}, {120628, 16857091}, {120629, 17962243}, {120630, 16851715},
2441
  {120631, 16851971}, {120632, 16852227}, {120633, 16852483}, {120634, 16852739},
2442
  {120635, 16852995}, {120636, 16853251}, {120637, 16853507}, {120638, 16846851},
2443
  {120639, 16853763}, {120640, 16854019}, {120641, 16786179}, {120642, 16854275},
2444
  {120643, 16854531}, {120644, 16854787}, {120645, 16855043}, {120646, 16855299},
2445
  {120647, 16855555}, {120649, 16855811}, {120650, 16856067}, {120651, 16856323},
2446
  {120652, 16856579}, {120653, 16856835}, {120654, 16857091}, {120655, 17962499},
2447
  {120656, 16852739}, {120657, 16853507}, {120658, 16853763}, {120659, 16856323},
2448
  {120660, 16855299}, {120661, 16855043}, {120662, 16851715}, {120663, 16851971},
2449
  {120664, 16852227}, {120665, 16852483}, {120666, 16852739}, {120667, 16852995},
2450
  {120668, 16853251}, {120669, 16853507}, {120670, 16846851}, {120671, 16853763},
2451
  {120672, 16854019}, {120673, 16786179}, {120674, 16854275}, {120675, 16854531},
2452
  {120676, 16854787}, {120677, 16855043}, {120678, 16855299}, {120679, 16853507},
2453
  {120680, 16855555}, {120681, 16855811}, {120682, 16856067}, {120683, 16856323},
2454
  {120684, 16856579}, {120685, 16856835}, {120686, 16857091}, {120687, 17962243},
2455
  {120688, 16851715}, {120689, 16851971}, {120690, 16852227}, {120691, 16852483},
2456
  {120692, 16852739}, {120693, 16852995}, {120694, 16853251}, {120695, 16853507},
2457
  {120696, 16846851}, {120697, 16853763}, {120698, 16854019}, {120699, 16786179},
2458
  {120700, 16854275}, {120701, 16854531}, {120702, 16854787}, {120703, 16855043},
2459
  {120704, 16855299}, {120705, 16855555}, {120707, 16855811}, {120708, 16856067},
2460
  {120709, 16856323}, {120710, 16856579}, {120711, 16856835}, {120712, 16857091},
2461
  {120713, 17962499}, {120714, 16852739}, {120715, 16853507}, {120716, 16853763},
2462
  {120717, 16856323}, {120718, 16855299}, {120719, 16855043}, {120720, 16851715},
2463
  {120721, 16851971}, {120722, 16852227}, {120723, 16852483}, {120724, 16852739},
2464
  {120725, 16852995}, {120726, 16853251}, {120727, 16853507}, {120728, 16846851},
2465
  {120729, 16853763}, {120730, 16854019}, {120731, 16786179}, {120732, 16854275},
2466
  {120733, 16854531}, {120734, 16854787}, {120735, 16855043}, {120736, 16855299},
2467
  {120737, 16853507}, {120738, 16855555}, {120739, 16855811}, {120740, 16856067},
2468
  {120741, 16856323}, {120742, 16856579}, {120743, 16856835}, {120744, 16857091},
2469
  {120745, 17962243}, {120746, 16851715}, {120747, 16851971}, {120748, 16852227},
2470
  {120749, 16852483}, {120750, 16852739}, {120751, 16852995}, {120752, 16853251},
2471
  {120753, 16853507}, {120754, 16846851}, {120755, 16853763}, {120756, 16854019},
2472
  {120757, 16786179}, {120758, 16854275}, {120759, 16854531}, {120760, 16854787},
2473
  {120761, 16855043}, {120762, 16855299}, {120763, 16855555}, {120765, 16855811},
2474
  {120766, 16856067}, {120767, 16856323}, {120768, 16856579}, {120769, 16856835},
2475
  {120770, 16857091}, {120771, 17962499}, {120772, 16852739}, {120773, 16853507},
2476
  {120774, 16853763}, {120775, 16856323}, {120776, 16855299}, {120777, 16855043},
2477
  {120778, 16858627}, {120780, 2}, {120782, 17045507}, {120783, 16786947},
2478
  {120784, 16785155}, {120785, 16785411}, {120786, 16787715}, {120787, 17045763},
2479
  {120788, 17046019}, {120789, 17046275}, {120790, 17046531}, {120791, 17046787},
2480
  {120792, 17045507}, {120793, 16786947}, {120794, 16785155}, {120795, 16785411},
2481
  {120796, 16787715}, {120797, 17045763}, {120798, 17046019}, {120799, 17046275},
2482
  {120800, 17046531}, {120801, 17046787}, {120802, 17045507}, {120803, 16786947},
2483
  {120804, 16785155}, {120805, 16785411}, {120806, 16787715}, {120807, 17045763},
2484
  {120808, 17046019}, {120809, 17046275}, {120810, 17046531}, {120811, 17046787},
2485
  {120812, 17045507}, {120813, 16786947}, {120814, 16785155}, {120815, 16785411},
2486
  {120816, 16787715}, {120817, 17045763}, {120818, 17046019}, {120819, 17046275},
2487
  {120820, 17046531}, {120821, 17046787}, {120822, 17045507}, {120823, 16786947},
2488
  {120824, 16785155}, {120825, 16785411}, {120826, 16787715}, {120827, 17045763},
2489
  {120828, 17046019}, {120829, 17046275}, {120830, 17046531}, {120831, 17046787},
2490
  {120832, 1}, {121484, 2}, {121499, 1}, {121504, 2},
2491
  {121505, 1}, {121520, 2}, {122624, 1}, {122655, 2},
2492
  {122661, 1}, {122667, 2}, {122880, 1}, {122887, 2},
2493
  {122888, 1}, {122905, 2}, {122907, 1}, {122914, 2},
2494
  {122915, 1}, {122917, 2}, {122918, 1}, {122923, 2},
2495
  {122928, 16866563}, {122929, 16866819}, {122930, 16867075}, {122931, 16867331},
2496
  {122932, 16867587}, {122933, 16867843}, {122934, 16868099}, {122935, 16868355},
2497
  {122936, 16868611}, {122937, 16869123}, {122938, 16869379}, {122939, 16869635},
2498
  {122940, 16870147}, {122941, 16870403}, {122942, 16870659}, {122943, 16870915},
2499
  {122944, 16871171}, {122945, 16871427}, {122946, 16871683}, {122947, 16871939},
2500
  {122948, 16872195}, {122949, 16872451}, {122950, 16872707}, {122951, 16873475},
2501
  {122952, 16873987}, {122953, 16874243}, {122954, 17505795}, {122955, 16889091},
2502
  {122956, 16864003}, {122957, 16864515}, {122958, 16891139}, {122959, 16883715},
2503
  {122960, 16886019}, {122961, 16866563}, {122962, 16866819}, {122963, 16867075},
2504
  {122964, 16867331}, {122965, 16867587}, {122966, 16867843}, {122967, 16868099},
2505
  {122968, 16868355}, {122969, 16868611}, {122970, 16869123}, {122971, 16869379},
2506
  {122972, 16870147}, {122973, 16870403}, {122974, 16870915}, {122975, 16871427},
2507
  {122976, 16871683}, {122977, 16871939}, {122978, 16872195}, {122979, 16872451},
2508
  {122980, 16872707}, {122981, 16873219}, {122982, 16873475}, {122983, 16879875},
2509
  {122984, 16864003}, {122985, 16863747}, {122986, 16866307}, {122987, 16883203},
2510
  {122988, 17500931}, {122989, 16883971}, {122990, 2}, {123023, 1},
2511
  {123024, 2}, {123136, 1}, {123181, 2}, {123184, 1},
2512
  {123198, 2}, {123200, 1}, {123210, 2}, {123214, 1},
2513
  {123216, 2}, {123536, 1}, {123567, 2}, {123584, 1},
2514
  {123642, 2}, {123647, 1}, {123648, 2}, {124112, 1},
2515
  {124154, 2}, {124368, 1}, {124411, 2}, {124415, 1},
2516
  {124416, 2}, {124896, 1}, {124903, 2}, {124904, 1},
2517
  {124908, 2}, {124909, 1}, {124911, 2}, {124912, 1},
2518
  {124927, 2}, {124928, 1}, {125125, 2}, {125127, 1},
2519
  {125143, 2}, {125184, 17962755}, {125185, 17963011}, {125186, 17963267},
2520
  {125187, 17963523}, {125188, 17963779}, {125189, 17964035}, {125190, 17964291},
2521
  {125191, 17964547}, {125192, 17964803}, {125193, 17965059}, {125194, 17965315},
2522
  {125195, 17965571}, {125196, 17965827}, {125197, 17966083}, {125198, 17966339},
2523
  {125199, 17966595}, {125200, 17966851}, {125201, 17967107}, {125202, 17967363},
2524
  {125203, 17967619}, {125204, 17967875}, {125205, 17968131}, {125206, 17968387},
2525
  {125207, 17968643}, {125208, 17968899}, {125209, 17969155}, {125210, 17969411},
2526
  {125211, 17969667}, {125212, 17969923}, {125213, 17970179}, {125214, 17970435},
2527
  {125215, 17970691}, {125216, 17970947}, {125217, 17971203}, {125218, 1},
2528
  {125260, 2}, {125264, 1}, {125274, 2}, {125278, 1},
2529
  {125280, 2}, {126065, 1}, {126133, 2}, {126209, 1},
2530
  {126270, 2}, {126464, 16910595}, {126465, 17695235}, {126466, 17693443},
2531
  {126467, 17846019}, {126468, 2}, {126469, 16911107}, {126470, 17743107},
2532
  {126471, 17693955}, {126472, 17711619}, {126473, 16912131}, {126474, 17720323},
2533
  {126475, 17722627}, {126476, 17694467}, {126477, 17729539}, {126478, 17706499},
2534
  {126479, 17713155}, {126480, 17715203}, {126481, 17708547}, {126482, 17718275},
2535
  {126483, 17736707}, {126484, 17756675}, {126485, 17698307}, {126486, 17701379},
2536
  {126487, 17696515}, {126488, 17736195}, {126489, 17709571}, {126490, 17712643},
2537
  {126491, 17714179}, {126492, 17971459}, {126493, 17684995}, {126494, 17971715},
2538
  {126495, 17971971}, {126496, 2}, {126497, 17695235}, {126498, 17693443},
2539
  {126499, 2}, {126500, 17732611}, {126501, 2}, {126503, 17693955},
2540
  {126504, 2}, {126505, 16912131}, {126506, 17720323}, {126507, 17722627},
2541
  {126508, 17694467}, {126509, 17729539}, {126510, 17706499}, {126511, 17713155},
2542
  {126512, 17715203}, {126513, 17708547}, {126514, 17718275}, {126515, 2},
2543
  {126516, 17756675}, {126517, 17698307}, {126518, 17701379}, {126519, 17696515},
2544
  {126520, 2}, {126521, 17709571}, {126522, 2}, {126523, 17714179},
2545
  {126524, 2}, {126530, 17693443}, {126531, 2}, {126535, 17693955},
2546
  {126536, 2}, {126537, 16912131}, {126538, 2}, {126539, 17722627},
2547
  {126540, 2}, {126541, 17729539}, {126542, 17706499}, {126543, 17713155},
2548
  {126544, 2}, {126545, 17708547}, {126546, 17718275}, {126547, 2},
2549
  {126548, 17756675}, {126549, 2}, {126551, 17696515}, {126552, 2},
2550
  {126553, 17709571}, {126554, 2}, {126555, 17714179}, {126556, 2},
2551
  {126557, 17684995}, {126558, 2}, {126559, 17971971}, {126560, 2},
2552
  {126561, 17695235}, {126562, 17693443}, {126563, 2}, {126564, 17732611},
2553
  {126565, 2}, {126567, 17693955}, {126568, 17711619}, {126569, 16912131},
2554
  {126570, 17720323}, {126571, 2}, {126572, 17694467}, {126573, 17729539},
2555
  {126574, 17706499}, {126575, 17713155}, {126576, 17715203}, {126577, 17708547},
2556
  {126578, 17718275}, {126579, 2}, {126580, 17756675}, {126581, 17698307},
2557
  {126582, 17701379}, {126583, 17696515}, {126584, 2}, {126585, 17709571},
2558
  {126586, 17712643}, {126587, 17714179}, {126588, 17971459}, {126589, 2},
2559
  {126590, 17971715}, {126591, 2}, {126592, 16910595}, {126593, 17695235},
2560
  {126594, 17693443}, {126595, 17846019}, {126596, 17732611}, {126597, 16911107},
2561
  {126598, 17743107}, {126599, 17693955}, {126600, 17711619}, {126601, 16912131},
2562
  {126602, 2}, {126603, 17722627}, {126604, 17694467}, {126605, 17729539},
2563
  {126606, 17706499}, {126607, 17713155}, {126608, 17715203}, {126609, 17708547},
2564
  {126610, 17718275}, {126611, 17736707}, {126612, 17756675}, {126613, 17698307},
2565
  {126614, 17701379}, {126615, 17696515}, {126616, 17736195}, {126617, 17709571},
2566
  {126618, 17712643}, {126619, 17714179}, {126620, 2}, {126625, 17695235},
2567
  {126626, 17693443}, {126627, 17846019}, {126628, 2}, {126629, 16911107},
2568
  {126630, 17743107}, {126631, 17693955}, {126632, 17711619}, {126633, 16912131},
2569
  {126634, 2}, {126635, 17722627}, {126636, 17694467}, {126637, 17729539},
2570
  {126638, 17706499}, {126639, 17713155}, {126640, 17715203}, {126641, 17708547},
2571
  {126642, 17718275}, {126643, 17736707}, {126644, 17756675}, {126645, 17698307},
2572
  {126646, 17701379}, {126647, 17696515}, {126648, 17736195}, {126649, 17709571},
2573
  {126650, 17712643}, {126651, 17714179}, {126652, 2}, {126704, 1},
2574
  {126706, 2}, {126976, 1}, {127020, 2}, {127024, 1},
2575
  {127124, 2}, {127136, 1}, {127151, 2}, {127153, 1},
2576
  {127168, 2}, {127169, 1}, {127184, 2}, {127185, 1},
2577
  {127222, 2}, {127233, 34749443}, {127234, 34749955}, {127235, 34750467},
2578
  {127236, 34750979}, {127237, 34751491}, {127238, 34752003}, {127239, 34752515},
2579
  {127240, 34753027}, {127241, 34753539}, {127242, 34754051}, {127243, 1},
2580
  {127248, 50655491}, {127249, 50656259}, {127250, 50657027}, {127251, 50657795},
2581
  {127252, 50658563}, {127253, 50659331}, {127254, 50660099}, {127255, 50660867},
2582
  {127256, 50661635}, {127257, 50662403}, {127258, 50663171}, {127259, 50663939},
2583
  {127260, 50664707}, {127261, 50665475}, {127262, 50666243}, {127263, 50667011},
2584
  {127264, 50667779}, {127265, 50668547}, {127266, 50669315}, {127267, 50670083},
2585
  {127268, 50670851}, {127269, 50671619}, {127270, 50672387}, {127271, 50673155},
2586
  {127272, 50673923}, {127273, 50674691}, {127274, 51531779}, {127275, 16777731},
2587
  {127276, 16781571}, {127277, 33554947}, {127278, 34755331}, {127279, 1},
2588
  {127280, 16777219}, {127281, 16777475}, {127282, 16777731}, {127283, 16777987},
2589
  {127284, 16778243}, {127285, 16778499}, {127286, 16778755}, {127287, 16779011},
2590
  {127288, 16779267}, {127289, 16779523}, {127290, 16779779}, {127291, 16780035},
2591
  {127292, 16780291}, {127293, 16780547}, {127294, 16780803}, {127295, 16781059},
2592
  {127296, 16781315}, {127297, 16781571}, {127298, 16781827}, {127299, 16782083},
2593
  {127300, 16782339}, {127301, 16782595}, {127302, 16782851}, {127303, 16783107},
2594
  {127304, 16783363}, {127305, 16783619}, {127306, 34755843}, {127307, 34237187},
2595
  {127308, 34756355}, {127309, 34756867}, {127310, 51534595}, {127311, 34758147},
2596
  {127312, 1}, {127338, 34220035}, {127339, 34200067}, {127340, 34758659},
2597
  {127341, 1}, {127376, 34759171}, {127377, 1}, {127406, 2},
2598
  {127462, 1}, {127488, 34759683}, {127489, 34760195}, {127490, 17318403},
2599
  {127491, 2}, {127504, 17168387}, {127505, 17983491}, {127506, 17983747},
2600
  {127507, 17362179}, {127508, 17153795}, {127509, 17984003}, {127510, 17984259},
2601
  {127511, 17235971}, {127512, 17984515}, {127513, 17984771}, {127514, 17985027},
2602
  {127515, 17596163}, {127516, 17985283}, {127517, 17985539}, {127518, 17985795},
2603
  {127519, 17986051}, {127520, 17986307}, {127521, 17986563}, {127522, 17177603},
2604
  {127523, 17986819}, {127524, 17987075}, {127525, 17987331}, {127526, 17987587},
2605
  {127527, 17987843}, {127528, 17988099}, {127529, 17152259}, {127530, 17233923},
2606
  {127531, 17988355}, {127532, 17299203}, {127533, 17234691}, {127534, 17299459},
2607
  {127535, 17988611}, {127536, 17191939}, {127537, 17988867}, {127538, 17989123},
2608
  {127539, 17989379}, {127540, 17989635}, {127541, 17989891}, {127542, 17274883},
2609
  {127543, 17170947}, {127544, 17990147}, {127545, 17990403}, {127546, 17990659},
2610
  {127547, 17990915}, {127548, 2}, {127552, 51545603}, {127553, 51546371},
2611
  {127554, 51547139}, {127555, 51547907}, {127556, 51548675}, {127557, 51549443},
2612
  {127558, 51550211}, {127559, 51550979}, {127560, 51551747}, {127561, 2},
2613
  {127568, 17998083}, {127569, 17998339}, {127570, 2}, {127584, 1},
2614
  {127590, 2}, {127744, 1}, {128728, 2}, {128732, 1},
2615
  {128749, 2}, {128752, 1}, {128765, 2}, {128768, 1},
2616
  {128887, 2}, {128891, 1}, {128986, 2}, {128992, 1},
2617
  {129004, 2}, {129008, 1}, {129009, 2}, {129024, 1},
2618
  {129036, 2}, {129040, 1}, {129096, 2}, {129104, 1},
2619
  {129114, 2}, {129120, 1}, {129160, 2}, {129168, 1},
2620
  {129198, 2}, {129200, 1}, {129212, 2}, {129216, 1},
2621
  {129218, 2}, {129280, 1}, {129620, 2}, {129632, 1},
2622
  {129646, 2}, {129648, 1}, {129661, 2}, {129664, 1},
2623
  {129674, 2}, {129679, 1}, {129735, 2}, {129742, 1},
2624
  {129757, 2}, {129759, 1}, {129770, 2}, {129776, 1},
2625
  {129785, 2}, {129792, 1}, {129939, 2}, {129940, 1},
2626
  {130032, 17045507}, {130033, 16786947}, {130034, 16785155}, {130035, 16785411},
2627
  {130036, 16787715}, {130037, 17045763}, {130038, 17046019}, {130039, 17046275},
2628
  {130040, 17046531}, {130041, 17046787}, {130042, 2}, {131072, 1},
2629
  {173792, 2}, {173824, 1}, {177978, 2}, {177984, 1},
2630
  {178206, 2}, {178208, 1}, {183970, 2}, {183984, 1},
2631
  {191457, 2}, {191472, 1}, {192094, 2}, {194560, 17998595},
2632
  {194561, 17998851}, {194562, 17999107}, {194563, 17999363}, {194564, 17999619},
2633
  {194565, 17619971}, {194566, 17999875}, {194567, 18000131}, {194568, 18000387},
2634
  {194569, 18000643}, {194570, 17620227}, {194571, 18000899}, {194572, 18001155},
2635
  {194573, 18001411}, {194574, 17620483}, {194575, 18001667}, {194576, 18001923},
2636
  {194577, 18002179}, {194578, 18002435}, {194579, 18002691}, {194580, 18002947},
2637
  {194581, 17985795}, {194582, 18003203}, {194583, 18003459}, {194584, 18003715},
2638
  {194585, 18003971}, {194586, 18004227}, {194587, 17634563}, {194588, 18004483},
2639
  {194589, 17156355}, {194590, 18004739}, {194591, 18004995}, {194592, 18005251},
2640
  {194593, 18005507}, {194594, 17990403}, {194595, 18005763}, {194596, 18006019},
2641
  {194597, 17635843}, {194598, 17620739}, {194599, 17620995}, {194600, 17636099},
2642
  {194601, 18006275}, {194602, 18006531}, {194603, 17574403}, {194604, 18006787},
2643
  {194605, 17621251}, {194606, 18007043}, {194607, 18007299}, {194608, 18007555},
2644
  {194609, 18007811}, {194612, 18008067}, {194613, 18008323}, {194614, 18008579},
2645
  {194615, 18008835}, {194616, 18009091}, {194617, 18009347}, {194618, 18009603},
2646
  {194619, 18009859}, {194620, 18010115}, {194621, 18010371}, {194622, 18010627},
2647
  {194623, 18010883}, {194624, 18011139}, {194625, 18011395}, {194626, 18011651},
2648
  {194627, 18011907}, {194628, 18012163}, {194629, 18012419}, {194631, 17636611},
2649
  {194632, 18012675}, {194633, 18012931}, {194634, 18013187}, {194635, 18013443},
2650
  {194636, 17621763}, {194637, 18013699}, {194638, 18013955}, {194639, 18014211},
2651
  {194640, 17611523}, {194641, 18014467}, {194642, 18014723}, {194643, 18014979},
2652
  {194644, 18015235}, {194645, 18015491}, {194646, 18015747}, {194647, 18016003},
2653
  {194648, 18016259}, {194649, 18016515}, {194650, 18016771}, {194651, 18017027},
2654
  {194652, 18017283}, {194653, 17984003}, {194654, 18017539}, {194655, 18017795},
2655
  {194656, 18018051}, {194657, 18018307}, {194658, 18018563}, {194659, 18018819},
2656
  {194660, 18019075}, {194661, 18019331}, {194662, 18019587}, {194663, 18019843},
2657
  {194664, 18020099}, {194665, 18020355}, {194666, 18020611}, {194668, 18020867},
2658
  {194669, 18021123}, {194670, 18021379}, {194671, 17573379}, {194672, 18021635},
2659
  {194673, 18021891}, {194674, 18022147}, {194675, 18022403}, {194676, 18022659},
2660
  {194677, 17163011}, {194678, 18022915}, {194679, 18023171}, {194680, 17163523},
2661
  {194681, 18023427}, {194682, 18023683}, {194683, 18023939}, {194684, 18024195},
2662
  {194685, 18024451}, {194686, 18024707}, {194687, 18024963}, {194688, 18025219},
2663
  {194689, 18025475}, {194690, 18025731}, {194691, 18025987}, {194692, 18026243},
2664
  {194693, 18026499}, {194694, 18026755}, {194695, 18027011}, {194696, 18027267},
2665
  {194697, 18027523}, {194698, 18027779}, {194699, 18028035}, {194700, 18028291},
2666
  {194701, 18028547}, {194702, 17560067}, {194703, 18028803}, {194704, 17166083},
2667
  {194705, 18029059}, {194707, 18029315}, {194708, 18029571}, {194710, 18029827},
2668
  {194711, 18030083}, {194712, 18030339}, {194713, 18030595}, {194714, 18030851},
2669
  {194715, 18031107}, {194716, 18031363}, {194717, 18031619}, {194718, 18031875},
2670
  {194719, 18032131}, {194720, 18032387}, {194721, 18032643}, {194722, 18032899},
2671
  {194723, 17623043}, {194724, 18033155}, {194725, 18033411}, {194726, 18033667},
2672
  {194727, 18033923}, {194728, 17639683}, {194729, 18033923}, {194730, 18034179},
2673
  {194731, 17623555}, {194732, 18034435}, {194733, 18034691}, {194734, 18034947},
2674
  {194735, 18035203}, {194736, 17623811}, {194737, 17553155}, {194738, 17425411},
2675
  {194739, 18035459}, {194740, 18035715}, {194741, 18035971}, {194742, 18036227},
2676
  {194743, 18036483}, {194744, 18036739}, {194745, 18036995}, {194746, 18037251},
2677
  {194747, 18037507}, {194748, 18037763}, {194749, 18038019}, {194750, 18038275},
2678
  {194751, 18038531}, {194752, 18038787}, {194753, 18039043}, {194754, 18039299},
2679
  {194755, 18039555}, {194756, 18039811}, {194757, 18040067}, {194758, 18040323},
2680
  {194759, 18040579}, {194760, 17624067}, {194761, 18040835}, {194762, 18041091},
2681
  {194763, 18041347}, {194764, 18041603}, {194765, 18041859}, {194766, 18042115},
2682
  {194767, 17624579}, {194768, 18042371}, {194769, 18042627}, {194770, 18042883},
2683
  {194771, 18043139}, {194772, 18043395}, {194773, 18043651}, {194774, 18043907},
2684
  {194775, 18044163}, {194776, 17560323}, {194777, 17641731}, {194778, 18044419},
2685
  {194779, 18044675}, {194780, 18044931}, {194781, 18045187}, {194782, 18045443},
2686
  {194783, 18045699}, {194784, 18045955}, {194785, 18046211}, {194786, 17624835},
2687
  {194787, 18046467}, {194788, 18046723}, {194789, 18046979}, {194790, 18047235},
2688
  {194791, 17652483}, {194792, 18047491}, {194793, 18047747}, {194794, 18048003},
2689
  {194795, 18048259}, {194796, 18048515}, {194797, 18048771}, {194798, 18049027},
2690
  {194799, 18049283}, {194800, 18049539}, {194801, 18049795}, {194802, 18050051},
2691
  {194803, 18050307}, {194804, 18050563}, {194805, 17577731}, {194806, 18050819},
2692
  {194807, 18051075}, {194808, 18051331}, {194809, 18051587}, {194810, 18051843},
2693
  {194811, 18052099}, {194812, 18052355}, {194813, 18052611}, {194814, 18052867},
2694
  {194815, 18053123}, {194816, 18053379}, {194817, 17625091}, {194818, 17598723},
2695
  {194819, 18053635}, {194820, 18053891}, {194821, 18054147}, {194822, 18054403},
2696
  {194823, 18054659}, {194824, 18054915}, {194825, 18055171}, {194826, 18055427},
2697
  {194827, 17642499}, {194828, 18055683}, {194829, 18055939}, {194830, 18056195},
2698
  {194831, 18056451}, {194832, 18056707}, {194833, 18056963}, {194834, 18057219},
2699
  {194835, 18057475}, {194836, 17642755}, {194837, 18057731}, {194838, 18057987},
2700
  {194839, 18058243}, {194840, 18058499}, {194841, 18058755}, {194842, 18059011},
2701
  {194843, 18059267}, {194844, 18059523}, {194845, 18059779}, {194846, 18060035},
2702
  {194847, 18060291}, {194848, 18060547}, {194849, 17643267}, {194850, 18060803},
2703
  {194851, 18061059}, {194852, 18061315}, {194853, 18061571}, {194854, 18061827},
2704
  {194855, 18062083}, {194856, 18062339}, {194857, 18062595}, {194858, 18062851},
2705
  {194859, 18063107}, {194860, 18063363}, {194862, 18063619}, {194863, 18063875},
2706
  {194864, 17643779}, {194865, 18064131}, {194866, 18064387}, {194867, 18064643},
2707
  {194868, 18064899}, {194869, 18065155}, {194870, 18065411}, {194871, 18065667},
2708
  {194872, 17574147}, {194873, 18065923}, {194874, 18066179}, {194875, 18066435},
2709
  {194876, 18066691}, {194877, 18066947}, {194878, 18067203}, {194879, 18067459},
2710
  {194880, 17645315}, {194881, 18067715}, {194882, 18067971}, {194883, 18068227},
2711
  {194884, 18068483}, {194885, 18068739}, {194886, 18068995}, {194888, 17645571},
2712
  {194889, 17652995}, {194890, 18069251}, {194891, 18069507}, {194892, 18069763},
2713
  {194893, 18070019}, {194894, 18070275}, {194895, 17564675}, {194896, 17646083},
2714
  {194897, 18070531}, {194898, 18070787}, {194899, 17627651}, {194900, 18071043},
2715
  {194901, 18071299}, {194902, 17616643}, {194903, 18071555}, {194904, 18071811},
2716
  {194905, 17628419}, {194906, 18072067}, {194907, 18072323}, {194908, 18072579},
2717
  {194909, 18072835}, {194911, 18073091}, {194912, 18073347}, {194913, 18073603},
2718
  {194914, 18073859}, {194915, 18074115}, {194916, 18074371}, {194917, 18074627},
2719
  {194918, 18074883}, {194919, 18075139}, {194920, 18075395}, {194921, 18075651},
2720
  {194922, 18075907}, {194923, 18076163}, {194924, 18076419}, {194925, 18076675},
2721
  {194926, 18076931}, {194927, 18077187}, {194928, 18077443}, {194929, 18077699},
2722
  {194930, 18077955}, {194931, 18078211}, {194932, 18078467}, {194933, 18078723},
2723
  {194934, 18078979}, {194935, 18079235}, {194936, 18079491}, {194937, 18079747},
2724
  {194938, 17629955}, {194939, 18080003}, {194940, 18080259}, {194941, 18080515},
2725
  {194942, 18080771}, {194943, 18081027}, {194944, 18081283}, {194945, 18081539},
2726
  {194946, 18081795}, {194947, 18082051}, {194948, 18082307}, {194949, 18082563},
2727
  {194950, 18082819}, {194951, 18083075}, {194952, 18083331}, {194953, 18083587},
2728
  {194954, 18083843}, {194955, 18029315}, {194956, 18084099}, {194957, 18084355},
2729
  {194958, 18084611}, {194959, 18084867}, {194960, 18085123}, {194961, 18085379},
2730
  {194962, 18085635}, {194963, 18085891}, {194964, 18086147}, {194965, 18086403},
2731
  {194966, 18086659}, {194967, 18086915}, {194968, 17578499}, {194969, 18087171},
2732
  {194970, 18087427}, {194971, 18087683}, {194972, 18087939}, {194973, 18088195},
2733
  {194974, 18088451}, {194975, 17630723}, {194976, 18088707}, {194977, 18088963},
2734
  {194978, 18089219}, {194979, 18089475}, {194980, 18089731}, {194981, 18089987},
2735
  {194982, 18090243}, {194983, 18090499}, {194984, 18090755}, {194985, 18091011},
2736
  {194986, 18091267}, {194987, 18091523}, {194988, 18091779}, {194989, 18092035},
2737
  {194990, 18092291}, {194991, 18092547}, {194992, 18092803}, {194993, 18093059},
2738
  {194994, 18093315}, {194995, 18093571}, {194996, 17563395}, {194997, 18093827},
2739
  {194998, 18094083}, {194999, 18094339}, {195000, 18094595}, {195001, 18094851},
2740
  {195002, 18095107}, {195003, 17647875}, {195004, 18095363}, {195005, 18095619},
2741
  {195006, 18095875}, {195007, 18096131}, {195008, 18096387}, {195009, 18096643},
2742
  {195010, 18096899}, {195011, 18097155}, {195012, 17189123}, {195013, 18097411},
2743
  {195014, 18097667}, {195015, 18097923}, {195016, 18098179}, {195017, 18098435},
2744
  {195018, 18098691}, {195019, 18098947}, {195020, 18099203}, {195021, 18099459},
2745
  {195022, 18099715}, {195023, 18099971}, {195024, 17649155}, {195025, 17649411},
2746
  {195026, 17190915}, {195027, 18100227}, {195028, 18100483}, {195029, 18100739},
2747
  {195030, 18100995}, {195031, 18101251}, {195032, 18101507}, {195033, 18101763},
2748
  {195034, 18102019}, {195035, 18102275}, {195036, 18102531}, {195037, 18102787},
2749
  {195038, 18103043}, {195039, 17649667}, {195040, 18103299}, {195041, 18103555},
2750
  {195042, 18103811}, {195043, 18104067}, {195044, 18104323}, {195045, 18104579},
2751
  {195046, 18104835}, {195047, 18105091}, {195048, 18105347}, {195049, 18105603},
2752
  {195050, 18105859}, {195051, 18106115}, {195052, 18106371}, {195053, 18106627},
2753
  {195054, 18106883}, {195055, 18107139}, {195056, 18107395}, {195057, 18107651},
2754
  {195058, 18107907}, {195059, 18108163}, {195060, 18108419}, {195061, 18108675},
2755
  {195062, 18108931}, {195063, 18109187}, {195064, 18109443}, {195065, 18109699},
2756
  {195066, 18109955}, {195067, 18110211}, {195068, 18110467}, {195069, 18110723},
2757
  {195070, 17651203}, {195072, 18110979}, {195073, 18111235}, {195074, 18111491},
2758
  {195075, 18111747}, {195076, 18112003}, {195077, 18112259}, {195078, 18112515},
2759
  {195079, 18112771}, {195080, 18113027}, {195081, 18113283}, {195082, 17651459},
2760
  {195083, 18113539}, {195084, 18113795}, {195085, 18114051}, {195086, 18114307},
2761
  {195087, 18114563}, {195088, 18114819}, {195089, 18115075}, {195090, 18115331},
2762
  {195091, 18115587}, {195092, 18115843}, {195093, 17203203}, {195094, 18116099},
2763
  {195095, 17204227}, {195096, 18116355}, {195097, 18116611}, {195098, 18116867},
2764
  {195099, 18117123}, {195100, 17205507}, {195101, 18117379}, {195102, 2},
2765
  {196608, 1}, {201547, 2}, {201552, 1}, {205744, 2},
2766
  {917760, 0}, {918000, 2}
2767
};
2768
2769
2770
} // namespace ada::idna
2771
#endif // ADA_IDNA_TABLES_H
2772
/* end file src/mapping_tables.cpp */
2773
2774
namespace ada::idna {
2775
2776
// This can be greatly accelerated. For now we just use a simply
2777
// binary search. In practice, you should *not* do that.
2778
0
uint32_t find_range_index(uint32_t key) {
2779
  ////////////////
2780
  // This could be implemented with std::lower_bound, but we roll our own
2781
  // because we want to allow further optimizations in the future.
2782
  ////////////////
2783
0
  uint32_t len = std::size(table);
2784
0
  uint32_t low = 0;
2785
0
  uint32_t high = len - 1;
2786
0
  while (low <= high) {
2787
0
    uint32_t middle_index = (low + high) >> 1;  // cannot overflow
2788
0
    uint32_t middle_value = table[middle_index][0];
2789
0
    if (middle_value < key) {
2790
0
      low = middle_index + 1;
2791
0
    } else if (middle_value > key) {
2792
0
      high = middle_index - 1;
2793
0
    } else {
2794
0
      return middle_index;  // perfect match
2795
0
    }
2796
0
  }
2797
0
  return low == 0 ? 0 : low - 1;
2798
0
}
2799
2800
0
void ascii_map(char* input, size_t length) {
2801
0
  auto broadcast = [](uint8_t v) -> uint64_t {
2802
0
    return 0x101010101010101ull * v;
2803
0
  };
2804
0
  uint64_t broadcast_80 = broadcast(0x80);
2805
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2806
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2807
0
  size_t i = 0;
2808
2809
0
  for (; i + 7 < length; i += 8) {
2810
0
    uint64_t word{};
2811
0
    memcpy(&word, input + i, sizeof(word));
2812
0
    word ^=
2813
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2814
0
    memcpy(input + i, &word, sizeof(word));
2815
0
  }
2816
0
  if (i < length) {
2817
0
    uint64_t word{};
2818
0
    memcpy(&word, input + i, length - i);
2819
0
    word ^=
2820
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2821
0
    memcpy(input + i, &word, length - i);
2822
0
  }
2823
0
}
2824
2825
// Map the characters according to IDNA, returning the empty string on error.
2826
0
std::u32string map(std::u32string_view input) {
2827
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2828
  //  For each code point in the domain_name string, look up the status
2829
  //  value in Section 5, [IDNA Mapping
2830
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2831
  //  and take the following actions:
2832
  //    * disallowed: Leave the code point unchanged in the string, and
2833
  //    record that there was an error.
2834
  //    * ignored: Remove the code point from the string. This is
2835
  //    equivalent to mapping the code point to an empty string.
2836
  //    * mapped: Replace the code point in the string by the value for
2837
  //    the mapping in Section 5, [IDNA Mapping
2838
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2839
  //    * valid: Leave the code point unchanged in the string.
2840
0
  static std::u32string error = U"";
2841
0
  std::u32string answer;
2842
0
  answer.reserve(input.size());
2843
0
  for (char32_t x : input) {
2844
0
    size_t index = find_range_index(x);
2845
0
    uint32_t descriptor = table[index][1];
2846
0
    uint8_t code = uint8_t(descriptor);
2847
0
    switch (code) {
2848
0
      case 0:
2849
0
        break;  // nothing to do, ignored
2850
0
      case 1:
2851
0
        answer.push_back(x);  // valid, we just copy it to output
2852
0
        break;
2853
0
      case 2:
2854
0
        return error;  // disallowed
2855
      // case 3 :
2856
0
      default:
2857
        // We have a mapping
2858
0
        {
2859
0
          size_t char_count = (descriptor >> 24);
2860
0
          uint16_t char_index = uint16_t(descriptor >> 8);
2861
0
          for (size_t idx = char_index; idx < char_index + char_count; idx++) {
2862
0
            answer.push_back(mappings[idx]);
2863
0
          }
2864
0
        }
2865
0
    }
2866
0
  }
2867
0
  return answer;
2868
0
}
2869
}  // namespace ada::idna
2870
/* end file src/mapping.cpp */
2871
/* begin file src/normalization.cpp */
2872
/* begin file src/normalization_tables.cpp */
2873
// IDNA  15.0.0
2874
2875
// clang-format off
2876
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2877
#define ADA_IDNA_NORMALIZATION_TABLES_H
2878
#include <cstdint>
2879
2880
/**
2881
 * Unicode Standard Annex #15
2882
 *
2883
 * UNICODE NORMALIZATION FORMS
2884
 * https://www.unicode.org/reports/tr15/
2885
 *
2886
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2887
 */
2888
2889
namespace ada::idna {
2890
2891
const uint8_t decomposition_index[4352] = {
2892
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2893
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2894
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 7,  7,  7,  7,  7,
2895
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  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,  34, 35, 7,  7,  7,
2901
    36, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2902
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2903
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2904
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2905
    7,  7,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2906
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 7,  7,  7,
2907
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2908
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2909
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2910
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2911
    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,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2917
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2918
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 7,  7,  7,  7,  7,
2919
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2920
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2921
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2922
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2923
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2924
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2925
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2926
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2927
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2928
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2929
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2930
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2931
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2932
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2933
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2934
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2935
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2936
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2937
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2938
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2939
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2940
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2941
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2942
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2943
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2944
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2945
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2946
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2947
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2948
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2949
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2950
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2951
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2952
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2953
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2954
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2955
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2956
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2957
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2958
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2959
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2960
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2961
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2962
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2963
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2964
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2965
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2966
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2967
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2968
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2969
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2970
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2971
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2972
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2973
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  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};
3122
3123
const uint16_t decomposition_block[67][257] = {
3124
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
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,   5,   8,   8,   8,   8,
3135
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3136
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3137
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3138
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3139
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3140
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3141
     516, 524},
3142
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3143
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3144
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3145
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3146
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3147
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3148
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3149
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3150
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3151
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3152
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3153
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3154
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3155
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3156
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3157
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3158
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3159
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3160
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3161
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3162
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3163
     1948, 1956, 1964, 1972, 1980},
3164
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3165
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3166
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3167
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3168
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3169
     2356, 2356, 2356, 2356, 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, 2357, 2361, 2365, 2369,
3179
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3180
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3181
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3182
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3183
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3184
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3185
     2460, 2460, 2460, 2460, 2460},
3186
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 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, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3192
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 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, 2484, 2484, 2484,
3196
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3197
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3198
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3199
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3200
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3201
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3202
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3203
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3204
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3205
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3206
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3207
     2744, 2744, 2744, 2744, 2744},
3208
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3209
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3210
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3211
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3212
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3213
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3214
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3215
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3216
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3217
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3218
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
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, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3225
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3226
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3227
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3228
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3229
     3160, 3160, 3160, 3160, 3160},
3230
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 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, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3242
     3168, 3168, 3168, 3168, 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},
3252
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 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, 3176,
3255
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3256
     3208, 3208, 3208, 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, 3209, 3217, 3225,
3262
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3263
     3240, 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, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3269
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3270
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 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},
3274
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
3285
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3286
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3287
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3288
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3289
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3290
     3288, 3288, 3288, 3288, 3288, 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, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3293
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
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
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3303
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3304
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3305
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3306
     3392, 3392, 3392, 3392, 3392},
3307
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 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, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3312
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 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, 3416, 3424, 3432, 3432, 3432, 3440,
3315
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 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},
3329
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 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, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3336
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3337
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 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, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3342
     3488, 3488, 3488, 3488, 3488, 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, 3496,
3346
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3347
     3512, 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},
3351
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 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, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3358
     3520, 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, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3368
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
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},
3373
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 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, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3380
     3588, 3588, 3588, 3588, 3588, 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, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3392
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3393
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3394
     3624, 3624, 3624, 3624, 3624},
3395
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 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, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3400
     3632, 3632, 3632, 3632, 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, 3633,
3410
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
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, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3414
     3656, 3656, 3656, 3656, 3656, 3656, 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},
3417
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3418
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3419
     3660, 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, 3668, 3668, 3668, 3668,
3423
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3424
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3425
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3426
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3427
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3428
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3429
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3430
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3431
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3432
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3433
     3820, 3820, 3820, 3820, 3820, 3820, 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},
3439
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 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, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3443
     3828, 3828, 3828, 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
     3829, 3832, 3832, 3832, 3832},
3461
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3462
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3463
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 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
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3467
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 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},
3483
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3484
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3485
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3486
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3487
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3488
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3489
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3490
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3491
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3492
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3493
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3494
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3495
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3496
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3497
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3498
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3499
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
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},
3505
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3506
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3507
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3508
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3509
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3510
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3511
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3512
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3513
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3514
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3515
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3516
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3517
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3518
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3519
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3520
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3521
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3522
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3523
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3524
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3525
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3526
     6648, 6648, 6648, 6648, 6648},
3527
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3528
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3529
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3530
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3531
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3532
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3533
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3534
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3535
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3536
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3537
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3538
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3539
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3540
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3541
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3542
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3543
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3544
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3545
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3546
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3547
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3548
     9168, 9178, 9181, 9188, 9190},
3549
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3550
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3551
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3552
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3553
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3554
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3555
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3556
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3557
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3558
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3559
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3560
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3561
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3562
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3563
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3564
     9548, 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, 9549},
3571
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3572
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3573
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3574
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3575
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3576
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3577
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3578
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3579
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3580
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3581
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3582
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3583
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3584
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3585
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3586
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3587
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3588
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3589
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3590
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3591
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3592
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 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},
3597
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3598
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3599
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3600
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3601
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3602
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3603
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3604
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3605
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3606
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3607
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3608
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3609
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3610
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3611
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 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, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3615
     10616, 10616, 10616, 10616, 10616, 10616, 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, 10624, 10632, 10640, 10648, 10648,
3620
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3621
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3622
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3623
    {10680, 10680, 10680, 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, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3628
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3629
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3630
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3631
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3632
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3633
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3634
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3635
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3636
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3637
     10688, 10688, 10688, 10688, 10688, 10688, 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},
3649
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3650
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3651
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3652
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3653
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3654
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3655
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3656
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3657
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3658
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3659
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3660
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3661
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3662
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3663
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3664
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3665
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3666
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3667
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3668
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3669
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3670
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3671
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3672
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3673
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3674
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3675
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3676
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3677
     11840, 11840, 11840, 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, 11841, 11853, 11861, 11872,
3687
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 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, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3698
     11880, 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},
3701
    {11880, 11880, 11880, 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, 11881, 11885, 11888, 11888, 11888, 11888,
3714
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3715
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3716
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3717
     11888, 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},
3727
    {11888, 11888, 11888, 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, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3739
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3740
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3741
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3742
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3743
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3744
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3745
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3746
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3747
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 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},
3753
    {11892, 11892, 11892, 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, 11893,
3769
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
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, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3778
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3779
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3780
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3781
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3782
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3783
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3784
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3785
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3786
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3787
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3788
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3789
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3790
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3791
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3792
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3793
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3794
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3795
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3796
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3797
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3798
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3799
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3800
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3801
     12756, 12756, 12756, 12756, 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, 12757},
3805
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3806
     12760, 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, 12761, 12764, 12765, 12769, 12773, 12776,
3811
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3812
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3813
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3814
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3815
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3816
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3817
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3818
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3819
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3820
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3821
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3822
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3823
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3824
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3825
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3826
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3827
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3828
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3829
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3830
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3831
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 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, 13273,
3836
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3837
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3838
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3839
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3840
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3841
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3842
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3843
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3844
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3845
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3846
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3847
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
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, 13705},
3857
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3858
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3859
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3860
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3861
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3862
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3863
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3864
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3865
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3866
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3867
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3868
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3869
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3870
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3871
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3872
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3873
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3874
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3875
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3876
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3877
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3878
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3879
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3880
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3881
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3882
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3883
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3884
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3885
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3886
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3887
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3888
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3889
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3890
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3891
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3892
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3893
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3894
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3895
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3896
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3897
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3898
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3899
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3900
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3901
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3902
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3903
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3904
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3905
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3906
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3907
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3908
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3909
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 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, 18689, 18693, 18696, 18696,
3925
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 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},
3935
    {18696, 18696, 18696, 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, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3947
     18700, 18700, 18700, 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, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
3960
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
3961
    {18720, 18720, 18720, 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, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
3971
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
3972
     18740, 18740, 18740, 18740, 18740, 18740, 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},
3987
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
3988
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
3989
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
3990
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
3991
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
3992
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
3993
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
3994
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
3995
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
3996
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
3997
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
3998
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
3999
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4000
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4001
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4002
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4003
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4004
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4005
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4006
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4007
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4008
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4009
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4010
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4011
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4012
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4013
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4014
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4015
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4016
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4017
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4018
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4019
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4020
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4021
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4022
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4023
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4024
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4025
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4026
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4027
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4028
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4029
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4030
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4031
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4032
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4033
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4034
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4035
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 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, 20581},
4039
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4040
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4041
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4042
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4043
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4044
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4045
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4046
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4047
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4048
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4049
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4050
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4051
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4052
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4053
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4054
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4055
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4056
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4057
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 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, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4061
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4062
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4063
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4064
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4065
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4066
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4067
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4068
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4069
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4070
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4071
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4072
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4073
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4074
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4075
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4076
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4077
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4078
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4079
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4080
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4081
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4082
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4083
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4084
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4085
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4086
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4087
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4088
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4089
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4090
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4091
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4092
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4093
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4094
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4095
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4096
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4097
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4098
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4099
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4100
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4101
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4102
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4103
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4104
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4105
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4106
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4107
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4108
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4109
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4110
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4111
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
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
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4116
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4117
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4118
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4119
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4120
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4121
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4122
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4123
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4124
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4125
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4126
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4127
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4128
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4129
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4130
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4131
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4132
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4133
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4134
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4135
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4136
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4137
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4138
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4139
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4140
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4141
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4142
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4143
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4144
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4145
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4146
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4147
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4148
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4149
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4150
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4151
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4152
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4153
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4154
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4155
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4156
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4157
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4158
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4159
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4160
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4161
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4162
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4163
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4164
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4165
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4166
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4167
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4168
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4169
    {27996, 27996, 27996, 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, 27997,
4182
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4183
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4184
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4185
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4186
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4187
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4188
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 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},
4195
    {28220, 28220, 28220, 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, 28228, 28228, 28236, 28236, 28236,
4211
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4212
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4213
     28244, 28244, 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},
4221
    {28244, 28244, 28244, 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, 28252, 28260, 28260,
4226
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4227
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4228
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4229
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4230
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4231
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4232
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4233
     28260, 28260, 28260, 28260, 28260, 28260, 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},
4247
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4248
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4249
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4250
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4251
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4252
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4253
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4254
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4255
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4256
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4257
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4258
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4259
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4260
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4261
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4262
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4263
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4264
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4265
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4266
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4267
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4268
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4269
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4270
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4271
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4272
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4273
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4274
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4275
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4276
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4277
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4278
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4279
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4280
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4281
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4282
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4283
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4284
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4285
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4286
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4287
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4288
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 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, 28284, 28292,
4292
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4293
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4294
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4295
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4296
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4297
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4298
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4299
    {28300, 28300, 28300, 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, 28308, 28316, 28316,
4318
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 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},
4325
    {28316, 28316, 28316, 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, 28324, 28324, 28324,
4331
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4332
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4333
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4334
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4335
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4336
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4337
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4338
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4339
     28324, 28324, 28324, 28324, 28324, 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},
4351
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4352
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4353
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4354
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4355
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4356
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4357
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4358
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4359
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4360
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4361
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4362
     28400, 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, 28408, 28416,
4370
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4371
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4372
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4373
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4374
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4375
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4376
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4377
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4378
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4379
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4380
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4381
     28464, 28464, 28464, 28464, 28464, 28464, 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, 28465},
4403
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4404
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4405
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4406
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4407
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4408
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4409
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4410
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4411
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4412
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4413
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4414
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4415
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4416
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4417
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4418
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4419
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4420
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4421
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4422
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4423
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4424
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4425
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4426
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4427
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4428
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4429
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4430
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4431
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4432
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4433
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4434
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4435
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4436
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4437
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4438
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4439
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4440
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4441
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4442
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4443
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4444
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4445
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4446
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4447
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4448
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4449
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4450
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4451
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4452
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4453
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4454
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4455
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4456
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4457
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4458
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4459
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4460
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4461
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4462
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4463
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4464
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4465
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4466
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4467
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4468
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4469
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4470
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4471
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4472
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4473
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4474
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4475
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4476
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4477
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4478
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4479
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4480
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4481
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4482
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4483
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4484
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4485
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4486
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4487
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4488
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4489
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4490
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4491
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4492
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4493
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4494
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4495
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4496
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4497
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4498
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4499
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4500
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4501
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4502
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4503
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4504
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4505
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4506
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4507
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 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, 32449, 32453,
4512
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4513
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4514
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4515
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4516
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4517
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4518
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4519
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4520
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4521
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4522
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4523
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4524
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4525
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4526
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4527
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4528
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4529
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4530
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4531
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4532
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4533
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4534
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4535
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4536
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4537
     32696, 32696, 32696, 32696, 32696, 32696, 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, 32697},
4559
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4560
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4561
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4562
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4563
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4564
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4565
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4566
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4567
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4568
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4569
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4570
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4571
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4572
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4573
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4574
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4575
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4576
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4577
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4578
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4579
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4580
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4581
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4582
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4583
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4584
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4585
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4586
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4587
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4588
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4589
     33260, 33260, 33260, 33260, 33260, 33260, 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, 33261},
4611
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4612
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4613
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4614
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4615
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4616
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4617
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4618
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4619
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4620
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4621
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4622
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 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, 33877, 33884, 33884, 33884, 33884, 33884,
4626
     33884, 33884, 33884, 33884, 33884, 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, 33885},
4637
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4638
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4639
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4640
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4641
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4642
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4643
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4644
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4645
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4646
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4647
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4648
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4649
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4650
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4651
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4652
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4653
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4654
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4655
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4656
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4657
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4658
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4659
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4660
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4661
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4662
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4663
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4664
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4665
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4666
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4667
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4668
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4669
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4670
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4671
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4672
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4673
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4674
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4675
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4676
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4677
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4678
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 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
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4688
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4689
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4690
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4691
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4692
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4693
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4694
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4695
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4696
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4697
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4698
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4699
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4700
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4701
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4702
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4703
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4704
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4705
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4706
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4707
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4708
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4709
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4710
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4711
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4712
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4713
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4714
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4715
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4716
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4717
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4718
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4719
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4720
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4721
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4722
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4723
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4724
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4725
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4726
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4727
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4728
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4729
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4730
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4731
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4732
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4733
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4734
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4735
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4736
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4737
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4738
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4739
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4740
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4741
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4742
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4743
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4744
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
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}};
4767
const char32_t decomposition_data[9102] = {
4768
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4769
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4770
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4771
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4772
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4773
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4774
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4775
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4776
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4777
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4778
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4779
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4780
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4781
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4782
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4783
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4784
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4785
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4786
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4787
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4788
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4789
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4790
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4791
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4792
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4793
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4794
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4795
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4796
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4797
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4798
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4799
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4800
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4801
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4802
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4803
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4804
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4805
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4806
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4807
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4808
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4809
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4810
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4811
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4812
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4813
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4814
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4815
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4816
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4817
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4818
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4819
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4820
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4821
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4822
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4823
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4824
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4825
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4826
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4827
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4828
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4829
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4830
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4831
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4832
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4833
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4834
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4835
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4836
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4837
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4838
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4839
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4840
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4841
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4842
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4843
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4844
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4845
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4846
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4847
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4848
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4849
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4850
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4851
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4852
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4853
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4854
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4855
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4856
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4857
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4858
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4859
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4860
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4861
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4862
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4863
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4864
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4865
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4866
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4867
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4868
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4869
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4870
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4871
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4872
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4873
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4874
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4875
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4876
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4877
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4878
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4879
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4880
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4881
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4882
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4883
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4884
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4885
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4886
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4887
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4888
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4889
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4890
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4891
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4892
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4893
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4894
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4895
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4896
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4897
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4898
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4899
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4900
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4901
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4902
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4903
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4904
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4905
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4906
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4907
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4908
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4909
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4910
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4911
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4912
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4913
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4914
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4915
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4916
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4917
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4918
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4919
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4920
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4921
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4922
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4923
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4924
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4925
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4926
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4927
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4928
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4929
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4930
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4931
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4932
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4933
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4934
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4935
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4936
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4937
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4938
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4939
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4940
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4941
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4942
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4943
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4944
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4945
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4946
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4947
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4948
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4949
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4950
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4951
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4952
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4953
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4954
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4955
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4956
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4957
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4958
    949,    787,    768,    949,    788,    768,    949,    787,    769,
4959
    949,    788,    769,    917,    787,    917,    788,    917,    787,
4960
    768,    917,    788,    768,    917,    787,    769,    917,    788,
4961
    769,    951,    787,    951,    788,    951,    787,    768,    951,
4962
    788,    768,    951,    787,    769,    951,    788,    769,    951,
4963
    787,    834,    951,    788,    834,    919,    787,    919,    788,
4964
    919,    787,    768,    919,    788,    768,    919,    787,    769,
4965
    919,    788,    769,    919,    787,    834,    919,    788,    834,
4966
    953,    787,    953,    788,    953,    787,    768,    953,    788,
4967
    768,    953,    787,    769,    953,    788,    769,    953,    787,
4968
    834,    953,    788,    834,    921,    787,    921,    788,    921,
4969
    787,    768,    921,    788,    768,    921,    787,    769,    921,
4970
    788,    769,    921,    787,    834,    921,    788,    834,    959,
4971
    787,    959,    788,    959,    787,    768,    959,    788,    768,
4972
    959,    787,    769,    959,    788,    769,    927,    787,    927,
4973
    788,    927,    787,    768,    927,    788,    768,    927,    787,
4974
    769,    927,    788,    769,    965,    787,    965,    788,    965,
4975
    787,    768,    965,    788,    768,    965,    787,    769,    965,
4976
    788,    769,    965,    787,    834,    965,    788,    834,    933,
4977
    788,    933,    788,    768,    933,    788,    769,    933,    788,
4978
    834,    969,    787,    969,    788,    969,    787,    768,    969,
4979
    788,    768,    969,    787,    769,    969,    788,    769,    969,
4980
    787,    834,    969,    788,    834,    937,    787,    937,    788,
4981
    937,    787,    768,    937,    788,    768,    937,    787,    769,
4982
    937,    788,    769,    937,    787,    834,    937,    788,    834,
4983
    945,    768,    945,    769,    949,    768,    949,    769,    951,
4984
    768,    951,    769,    953,    768,    953,    769,    959,    768,
4985
    959,    769,    965,    768,    965,    769,    969,    768,    969,
4986
    769,    945,    787,    837,    945,    788,    837,    945,    787,
4987
    768,    837,    945,    788,    768,    837,    945,    787,    769,
4988
    837,    945,    788,    769,    837,    945,    787,    834,    837,
4989
    945,    788,    834,    837,    913,    787,    837,    913,    788,
4990
    837,    913,    787,    768,    837,    913,    788,    768,    837,
4991
    913,    787,    769,    837,    913,    788,    769,    837,    913,
4992
    787,    834,    837,    913,    788,    834,    837,    951,    787,
4993
    837,    951,    788,    837,    951,    787,    768,    837,    951,
4994
    788,    768,    837,    951,    787,    769,    837,    951,    788,
4995
    769,    837,    951,    787,    834,    837,    951,    788,    834,
4996
    837,    919,    787,    837,    919,    788,    837,    919,    787,
4997
    768,    837,    919,    788,    768,    837,    919,    787,    769,
4998
    837,    919,    788,    769,    837,    919,    787,    834,    837,
4999
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5000
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5001
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5002
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5003
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5004
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5005
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5006
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5007
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5008
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5009
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5010
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5011
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5012
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5013
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5014
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5015
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5016
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5017
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5018
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5019
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5020
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5021
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5022
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5023
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5024
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5025
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5026
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5027
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5028
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5029
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5030
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5031
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5032
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5033
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5034
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5035
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5036
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5037
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5038
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5039
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5040
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5041
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5042
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5043
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5044
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5045
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5046
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5047
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5048
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5049
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5050
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5051
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5052
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5053
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5054
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5055
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5056
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5057
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5058
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5059
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5060
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5061
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5062
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5063
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5064
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5065
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5066
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5067
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5068
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5069
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5070
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5071
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5072
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5073
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5074
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5075
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5076
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5077
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5078
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5079
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5080
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5081
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5082
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5083
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5084
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5085
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5086
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5087
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5088
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5089
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5090
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5091
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5092
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5093
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5094
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5095
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5096
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5097
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5098
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5099
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5100
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5101
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5102
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5103
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5104
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5105
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5106
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5107
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5108
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5109
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5110
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5111
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5112
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5113
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5114
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5115
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5116
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5117
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5118
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5119
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5120
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5121
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5122
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5123
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5124
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5125
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5126
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5127
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5128
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5129
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5130
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5131
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5132
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5133
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5134
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5135
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5136
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5137
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5138
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5139
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5140
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5141
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5142
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5143
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5144
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5145
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5146
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5147
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5148
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5149
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5150
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5151
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5152
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5153
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5154
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5155
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5156
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5157
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5158
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5159
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5160
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5161
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5162
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5163
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5164
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5165
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5166
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5167
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5168
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5169
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5170
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5171
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5172
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5173
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5174
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5175
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5176
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5177
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5178
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5179
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5180
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5181
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5182
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5183
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5184
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5185
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5186
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5187
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5188
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5189
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5190
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5191
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5192
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5193
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5194
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5195
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5196
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5197
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5198
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5199
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5200
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5201
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5202
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5203
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5204
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5205
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5206
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5207
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5208
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5209
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5210
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5211
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5212
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5213
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5214
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5215
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5216
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5217
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5218
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5219
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5220
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5221
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5222
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5223
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5224
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5225
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5226
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5227
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5228
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5229
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5230
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5231
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5232
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5233
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5234
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5235
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5236
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5237
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5238
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5239
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5240
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5241
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5242
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5243
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5244
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5245
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5246
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5247
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5248
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5249
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5250
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5251
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5252
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5253
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5254
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5255
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5256
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5257
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5258
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5259
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5260
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5261
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5262
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5263
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5264
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5265
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5266
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5267
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5268
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5269
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5270
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5271
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5272
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5273
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5274
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5275
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5276
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5277
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5278
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5279
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5280
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5281
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5282
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5283
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5284
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5285
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5286
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5287
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5288
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5289
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5290
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5291
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5292
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5293
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5294
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5295
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5296
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5297
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5298
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5299
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5300
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5301
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5302
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5303
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5304
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5305
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5306
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5307
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5308
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5309
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5310
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5311
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5312
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5313
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5314
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5315
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5316
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5317
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5318
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5319
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5320
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5321
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5322
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5323
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5324
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5325
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5326
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5327
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5328
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5329
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5330
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5331
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5332
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5333
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5334
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5335
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5336
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5337
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5338
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5339
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5340
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5341
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5342
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5343
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5344
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5345
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5346
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5347
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5348
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5349
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5350
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5351
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5352
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5353
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5354
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5355
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5356
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5357
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5358
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5359
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5360
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5361
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5362
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5363
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5364
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5365
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5366
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5367
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5368
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5369
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5370
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5371
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5372
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5373
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5374
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5375
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5376
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5377
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5378
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5379
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5380
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5381
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5382
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5383
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5384
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5385
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5386
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5387
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5388
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5389
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5390
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5391
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5392
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5393
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5394
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5395
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5396
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5397
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5398
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5399
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5400
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5401
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5402
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5403
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5404
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5405
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5406
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5407
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5408
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5409
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5410
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5411
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5412
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5413
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5414
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5415
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5416
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5417
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5418
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5419
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5420
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5421
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5422
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5423
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5424
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5425
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5426
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5427
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5428
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5429
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5430
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5431
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5432
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5433
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5434
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5435
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5436
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5437
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5438
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5439
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5440
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5441
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5442
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5443
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5444
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5445
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5446
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5447
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5448
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5449
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5450
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5451
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5452
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5453
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5454
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5455
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5456
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5457
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5458
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5459
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5460
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5461
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5462
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5463
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5464
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5465
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5466
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5467
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5468
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5469
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5470
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5471
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5472
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5473
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5474
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5475
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5476
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5477
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5478
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5479
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5480
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5481
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5482
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5483
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5484
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5485
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5486
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5487
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5488
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5489
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5490
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5491
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5492
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5493
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5494
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5495
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5496
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5497
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5498
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5499
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5500
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5501
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5502
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5503
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5504
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5505
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5506
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5507
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5508
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5509
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5510
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5511
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5512
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5513
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5514
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5515
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5516
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5517
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5518
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5519
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5520
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5521
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5522
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5523
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5524
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5525
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5526
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5527
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5528
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5529
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5530
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5531
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5532
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5533
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5534
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5535
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5536
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5537
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5538
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5539
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5540
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5541
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5542
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5543
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5544
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5545
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5546
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5547
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5548
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5549
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5550
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5551
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5552
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5553
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5554
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5555
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5556
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5557
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5558
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5559
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5560
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5561
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5562
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5563
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5564
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5565
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5566
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5567
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5568
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5569
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5570
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5571
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5572
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5573
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5574
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5575
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5576
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5577
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5578
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5579
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5580
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5581
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5582
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5583
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5584
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5585
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5586
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5587
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5588
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5589
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5590
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5591
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5592
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5593
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5594
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5595
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5596
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5597
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5598
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5599
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5600
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5601
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5602
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5603
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5604
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5605
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5606
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5607
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5608
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5609
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5610
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5611
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5612
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5613
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5614
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5615
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5616
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5617
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5618
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5619
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5620
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5621
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5622
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5623
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5624
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5625
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5626
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5627
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5628
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5629
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5630
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5631
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5632
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5633
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5634
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5635
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5636
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5637
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5638
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5639
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5640
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5641
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5642
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5643
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5644
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5645
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5646
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5647
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5648
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5649
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5650
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5651
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5652
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5653
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5654
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5655
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5656
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5657
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5658
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5659
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5660
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5661
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5662
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5663
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5664
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5665
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5666
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5667
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5668
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5669
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5670
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5671
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5672
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5673
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5674
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5675
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5676
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5677
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5678
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5679
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5680
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5681
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5682
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5683
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5684
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5685
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5686
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5687
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5688
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5689
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5690
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5691
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5692
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5693
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5694
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5695
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5696
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5697
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5698
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5699
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5700
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5701
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5702
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5703
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5704
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5705
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5706
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5707
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5708
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5709
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5710
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5711
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5712
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5713
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5714
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5715
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5716
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5717
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5718
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5719
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5720
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5721
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5722
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5723
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5724
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5725
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5726
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5727
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5728
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5729
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5730
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5731
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5732
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5733
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5734
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5735
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5736
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5737
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5738
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5739
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5740
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5741
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5742
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5743
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5744
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5745
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5746
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5747
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5748
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5749
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5750
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5751
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5752
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5753
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5754
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5755
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5756
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5757
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5758
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5759
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5760
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5761
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5762
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5763
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5764
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5765
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5766
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5767
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5768
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5769
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5770
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5771
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5772
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5773
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5774
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5775
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5776
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5777
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5778
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5779
    40726,  40763,  173568};
5780
5781
const uint8_t canonical_combining_class_index[4352] = {
5782
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5783
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5784
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 0,  0,  0,  0,  0,  0,  0,  0,
5785
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5786
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5787
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5788
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5789
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5790
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  27, 0,  28, 29, 30,
5791
    31, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5792
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5793
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5794
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5795
    0,  0,  0,  0,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5796
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5797
    53, 0,  54, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5798
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5799
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5800
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5801
    0,  55, 56, 0,  0,  0,  57, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5802
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5803
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5804
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5805
    0,  0,  0,  0,  0,  0,  0,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5806
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5807
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5808
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5809
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5810
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5811
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5812
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5813
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5814
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5815
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5816
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5817
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5818
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5819
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5820
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5821
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5822
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5823
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5824
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5826
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5827
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5828
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5829
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5830
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5831
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5832
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5833
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5834
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5835
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5836
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5837
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5838
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5839
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5840
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5841
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5842
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5843
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5844
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5845
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5846
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  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};
6012
const uint8_t canonical_combining_class_block[67][256] = {
6013
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6014
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6024
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6025
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6026
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6027
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6028
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6029
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6030
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6031
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6032
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6033
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6034
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6035
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6036
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6037
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6038
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6039
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6040
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6041
     0},
6042
    {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 230,
6048
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6049
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6054
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6055
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6056
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6057
     0,   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,   220, 230, 230, 230, 230,
6064
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6065
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6066
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6067
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6068
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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},
6072
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6073
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6074
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6075
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6076
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6077
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6078
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6079
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6080
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6081
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6082
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6083
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6084
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6087
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6088
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6089
     0},
6090
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6091
     0,   0,   36,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6092
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6093
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6094
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6095
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6096
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6097
     0,   0,   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,   230, 230, 230, 230, 230,
6106
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6107
     0},
6108
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6109
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6110
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6111
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6112
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6113
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220,
6114
     220, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6115
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6116
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6117
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6118
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6119
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6120
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6121
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6122
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6123
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6124
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6125
     230},
6126
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6127
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6128
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6129
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6130
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
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, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6135
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6136
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6137
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6138
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6139
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6141
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6142
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6143
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6144
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0,
6146
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6147
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6148
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6149
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6150
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6152
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6153
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6154
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6155
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6156
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6158
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6159
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6160
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6161
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6162
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6163
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6164
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 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, 7, 0, 0, 0,
6168
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0},
6171
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6172
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6174
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6175
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6182
    {0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6183
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6184
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6185
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6186
     107, 107, 107, 107, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6187
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6193
     0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6194
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6195
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6196
     0,   0,   0,   0},
6197
    {0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6198
     0,   0, 0,   0,   0,   0,   0, 0, 0,   220, 220, 0,   0,   0, 0,
6199
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6200
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6201
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6202
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
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, 129, 130, 0,   132, 0,   0, 0,
6205
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6206
     230, 0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6207
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
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,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6211
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
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},
6215
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6216
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6217
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6218
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6219
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6220
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6221
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6222
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6223
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6224
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6225
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6226
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6227
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6231
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
6238
    {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6239
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6240
     0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6241
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0, 0, 0, 0,
6247
     0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6248
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6249
    {0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6250
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6257
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6258
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6259
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6260
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6261
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6262
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6263
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6264
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   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},
6272
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6273
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6274
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6275
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6279
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6280
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6281
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6282
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6283
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6284
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6285
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6286
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6287
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6288
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6289
     0},
6290
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6291
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6292
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6293
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0,   0,   0,   0,   0,   0,
6294
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6295
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6296
     230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6297
     0,   0,   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,   9,
6299
     9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6300
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   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,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6303
     0,   0,   0, 0, 0, 0, 0, 0, 0},
6304
    {0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6305
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6306
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6307
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,
6308
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6309
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6310
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6311
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6312
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6313
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230,
6318
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6319
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6320
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6321
     0},
6322
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6323
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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,   230, 230, 220,
6335
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6336
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6337
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6338
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6339
     220},
6340
    {0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6341
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
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
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6354
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6355
     230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6356
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 230, 230, 230,
6367
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6368
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   9,   0,   0,   0,   0,   0,   0,   0,
6377
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6378
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   230,
6383
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6384
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6385
     230},
6386
    {0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6387
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6388
     0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6389
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 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, 8, 8, 0, 0, 0, 0, 0,
6394
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6395
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 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},
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,   230,
6406
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,
6407
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6408
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230,
6409
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6415
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6416
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   9,
6418
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6419
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6429
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6430
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6431
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6432
     0},
6433
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6434
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6435
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6436
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6437
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6442
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
6445
    {0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6446
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
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, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6455
     230, 230, 0, 230, 0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6456
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6457
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6458
     0,   0,   0, 0,   0, 0,   0, 0,   0},
6459
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0,
6469
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6470
    {0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6471
     0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6472
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6481
    {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,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6484
     220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6485
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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},
6499
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6500
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 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, 220, 0, 0},
6510
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6520
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0},
6521
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6522
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6527
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6528
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6529
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6530
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6531
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6532
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0},
6533
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 220, 0, 230, 0,   0, 0,   0,
6534
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6535
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   230, 1, 220, 0,
6536
     0, 0, 0, 9, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
6537
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0,   0,   0, 0,   0,
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, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6546
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6547
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6549
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   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},
6558
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6559
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 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, 230, 230, 0, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6567
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6568
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6570
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6571
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
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, 220, 220,
6574
     230, 230, 230, 220, 230, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6575
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6576
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6577
     0,   0,   0,   0,   230, 220, 230, 220, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6578
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
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},
6585
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6586
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6587
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
6588
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6589
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
6590
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6591
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6592
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0,
6593
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6594
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6596
    {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6597
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6598
     0,   0,   0,   0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6599
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6602
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 9, 0, 0, 0, 0, 0,
6605
     0,   0,   0,   0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6606
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6607
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6608
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6611
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 9, 0, 0, 0, 0, 0,
6618
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6619
    {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
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,   7,   7,   0, 0, 0,
6623
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6624
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6625
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6626
     230, 230, 230, 230, 230, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6627
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
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, 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, 9, 0, 0, 0, 7,   0,
6638
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6639
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6640
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6641
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6642
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6643
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6644
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6645
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6646
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9,
6654
     7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6655
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6656
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6657
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6658
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6659
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6660
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6661
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6662
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6663
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6664
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6665
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6666
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6667
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6668
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6669
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6670
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6671
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6672
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6673
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6674
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6675
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6676
     0, 0, 0, 0, 0, 0, 0, 0, 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},
6679
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6680
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6682
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6683
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6684
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6690
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6691
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6692
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6693
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6694
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6695
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6696
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6697
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6698
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6699
     0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6700
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6701
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6702
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6703
     0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6704
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6706
     0, 0, 0, 0, 0, 0, 0, 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, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6709
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6710
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6712
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6713
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6714
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
6715
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6716
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6717
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6720
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6721
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6723
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6724
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6725
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0,
6726
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6727
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6728
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6729
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6730
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6731
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6732
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6733
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6734
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6735
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6736
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0,
6737
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6738
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6745
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6746
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
     1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6756
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
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, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6759
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
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},
6769
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6770
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     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
     6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6780
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6788
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6789
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6790
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6798
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6799
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6800
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6801
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   0,
6802
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6803
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   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, 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
     230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6811
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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},
6819
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6820
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6821
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6822
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6823
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   230, 0,   0,   0,   0,   0,   0,
6829
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6830
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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},
6837
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6838
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,   230, 0,
6845
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6846
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6847
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6848
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6849
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   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, 232, 232, 220, 230, 0, 0,
6860
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6861
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6862
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6863
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6864
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6865
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 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, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6872
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6873
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6874
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
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, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6878
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6879
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6880
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6881
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6882
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6883
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6884
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6885
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6886
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6887
6888
const uint8_t composition_index[4352] = {
6889
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6890
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6891
    5, 5, 5, 5, 17, 5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6892
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6893
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6894
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6895
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6896
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6897
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6898
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6899
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6900
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6901
    5, 5, 5, 5, 5,  5,  5, 5, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6902
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6903
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6904
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6905
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6906
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6907
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6908
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6909
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6910
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6911
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6912
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6913
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6914
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6915
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6916
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6917
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6918
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6919
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6920
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6921
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6922
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6923
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6924
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6925
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6926
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6927
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6928
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6929
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6930
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6933
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6934
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6935
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6936
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6937
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6938
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6939
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6940
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6941
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6942
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  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};
7087
const uint16_t composition_block[67][257] = {
7088
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
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,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7093
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7094
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7095
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7096
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7097
     755, 755, 755, 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, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7100
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7101
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7102
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7103
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7104
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7105
     869, 869},
7106
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7107
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7108
     893, 893, 893, 893, 893, 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, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7112
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7113
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7114
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7115
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7116
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7117
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7118
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7119
     961, 961, 961, 961, 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, 963, 965, 965, 965, 965,
7122
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7123
     965, 965},
7124
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 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, 967, 969, 971, 973, 973, 973,
7127
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7128
     977, 977, 977, 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, 979, 979, 979,
7134
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 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},
7142
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  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,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7155
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7156
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7157
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7158
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7159
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7160
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 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},
7164
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7165
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7166
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7167
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7168
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7169
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7170
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7171
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7172
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7173
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7174
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 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, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7183
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7184
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7185
     1275, 1275, 1275, 1275, 1275},
7186
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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},
7197
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
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, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7201
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7202
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7203
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7204
     1285, 1285, 1285, 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, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7214
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7215
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 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},
7219
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 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, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7223
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7224
     1297, 1297, 1297, 1297, 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, 1301, 1301, 1301, 1301,
7236
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 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},
7241
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 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
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
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, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7254
     1309, 1309, 1309, 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, 1313, 1315, 1315, 1315, 1315,
7258
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 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},
7263
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 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, 1317,
7269
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 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
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7280
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 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},
7285
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 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, 1331,
7291
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
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, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7304
     1341, 1341, 1341, 1341, 1341, 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},
7307
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 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, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7311
     1343, 1343, 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},
7329
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7330
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7331
     1355, 1355, 1355, 1355, 1355, 1355, 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, 1357,
7334
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7335
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 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},
7351
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7352
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7353
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7354
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7355
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7356
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 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, 1371, 1373, 1373, 1373, 1373,
7359
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7360
     1377, 1377, 1377, 1377, 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, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7365
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7366
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7367
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7368
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7369
     1393, 1393, 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},
7373
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7374
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7375
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7376
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7377
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7378
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7379
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7380
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7381
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7382
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7383
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7384
     1641, 1641, 1641, 1641, 1641, 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, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7389
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7390
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 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, 1653, 1653, 1653, 1653, 1653,
7394
     1653, 1653, 1653, 1659, 1659},
7395
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 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, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7408
     1665, 1665, 1665, 1665, 1665, 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, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7413
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 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},
7417
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7418
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7419
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7420
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7421
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7422
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7423
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7424
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7425
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7426
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7427
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7428
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7429
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7430
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7431
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7432
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7433
     1741, 1741, 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},
7439
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 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, 1743,
7445
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7446
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7447
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7448
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7449
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7450
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7451
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7452
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7453
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7454
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7455
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7456
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7457
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7458
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7459
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7460
     1855, 1855, 1857, 1857, 1857},
7461
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 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, 1859, 1859,
7474
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7475
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 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},
7483
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 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, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7488
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7489
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7490
     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},
7505
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7506
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7507
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7508
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7509
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7510
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7511
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7512
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7513
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7514
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7515
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7516
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7517
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7518
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7519
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7520
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7521
     1871, 1871, 1871, 1871, 1871, 1871, 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},
7527
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7528
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7529
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7530
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7531
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7532
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7533
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7534
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7535
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7536
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7537
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7538
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7539
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7540
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7541
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7542
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7543
     1877, 1877, 1877, 1877, 1877, 1877, 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},
7549
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 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, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7565
     1881, 1881, 1881, 1881, 1881, 1881, 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},
7571
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 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, 1883, 1883, 1883, 1883, 1883, 1883,
7576
     1883, 1883, 1883, 1883, 1883, 1883, 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}};
7593
const char32_t composition_data[1883] = {
7594
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7595
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7596
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7597
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7598
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7599
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7600
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7601
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7602
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7603
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7604
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7605
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7606
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7607
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7608
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7609
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7610
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7611
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7612
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7613
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7614
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7615
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7616
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7617
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7618
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7619
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7620
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7621
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7622
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7623
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7624
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7625
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7626
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7627
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7628
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7629
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7630
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7631
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7632
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7633
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7634
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7635
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7636
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7637
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7638
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7639
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7640
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7641
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7642
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7643
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7644
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7645
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7646
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7647
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7648
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7649
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7650
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7651
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7652
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7653
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7654
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7655
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7656
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7657
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7658
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7659
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7660
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7661
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7662
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7663
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7664
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7665
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7666
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7667
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7668
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7669
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7670
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7671
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7672
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7673
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7674
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7675
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7676
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7677
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7678
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7679
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7680
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7681
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7682
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7683
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7684
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7685
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7686
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7687
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7688
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7689
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7690
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7691
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7692
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7693
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7694
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7695
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7696
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7697
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7698
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7699
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7700
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7701
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7702
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7703
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7704
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7705
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7706
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7707
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7708
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7709
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7710
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7711
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7712
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7713
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7714
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7715
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7716
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7717
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7718
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7719
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7720
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7721
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7722
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7723
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7724
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7725
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7726
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7727
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7728
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7729
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7730
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7731
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7732
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7733
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7734
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7735
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7736
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7737
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7738
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7739
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7740
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7741
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7742
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7743
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7744
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7745
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7746
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7747
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7748
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7749
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7750
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7751
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7752
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7753
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7754
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7755
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7756
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7757
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7758
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7759
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7760
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7761
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7762
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7763
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7764
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7765
    71984, 71992};
7766
7767
}  // namespace ada::idna
7768
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7769
/* end file src/normalization_tables.cpp */
7770
7771
namespace ada::idna {
7772
7773
// See
7774
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7775
constexpr char32_t hangul_sbase = 0xAC00;
7776
constexpr char32_t hangul_tbase = 0x11A7;
7777
constexpr char32_t hangul_vbase = 0x1161;
7778
constexpr char32_t hangul_lbase = 0x1100;
7779
constexpr char32_t hangul_lcount = 19;
7780
constexpr char32_t hangul_vcount = 21;
7781
constexpr char32_t hangul_tcount = 28;
7782
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7783
constexpr char32_t hangul_scount =
7784
    hangul_lcount * hangul_vcount * hangul_tcount;
7785
7786
std::pair<bool, size_t> compute_decomposition_length(
7787
0
    const std::u32string_view input) noexcept {
7788
0
  bool decomposition_needed{false};
7789
0
  size_t additional_elements{0};
7790
0
  for (char32_t current_character : input) {
7791
0
    size_t decomposition_length{0};
7792
7793
0
    if (current_character >= hangul_sbase &&
7794
0
        current_character < hangul_sbase + hangul_scount) {
7795
0
      decomposition_length = 2;
7796
0
      if ((current_character - hangul_sbase) % hangul_tcount) {
7797
0
        decomposition_length = 3;
7798
0
      }
7799
0
    } else if (current_character < 0x110000) {
7800
0
      const uint8_t di = decomposition_index[current_character >> 8];
7801
0
      const uint16_t* const decomposition =
7802
0
          decomposition_block[di] + (current_character % 256);
7803
0
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7804
0
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7805
0
        decomposition_length = 0;
7806
0
      }
7807
0
    }
7808
0
    if (decomposition_length != 0) {
7809
0
      decomposition_needed = true;
7810
0
      additional_elements += decomposition_length - 1;
7811
0
    }
7812
0
  }
7813
0
  return {decomposition_needed, additional_elements};
7814
0
}
7815
7816
0
void decompose(std::u32string& input, size_t additional_elements) {
7817
0
  input.resize(input.size() + additional_elements);
7818
0
  for (size_t descending_idx = input.size(),
7819
0
              input_count = descending_idx - additional_elements;
7820
0
       input_count--;) {
7821
0
    if (input[input_count] >= hangul_sbase &&
7822
0
        input[input_count] < hangul_sbase + hangul_scount) {
7823
      // Hangul decomposition.
7824
0
      char32_t s_index = input[input_count] - hangul_sbase;
7825
0
      if (s_index % hangul_tcount != 0) {
7826
0
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7827
0
      }
7828
0
      input[--descending_idx] =
7829
0
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7830
0
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7831
0
    } else if (input[input_count] < 0x110000) {
7832
      // Check decomposition_data.
7833
0
      const uint16_t* decomposition =
7834
0
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7835
0
          (input[input_count] % 256);
7836
0
      uint16_t decomposition_length =
7837
0
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7838
0
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7839
0
        decomposition_length = 0;
7840
0
      }
7841
0
      if (decomposition_length > 0) {
7842
        // Non-recursive decomposition.
7843
0
        while (decomposition_length-- > 0) {
7844
0
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7845
0
                                                       decomposition_length];
7846
0
        }
7847
0
      } else {
7848
        // No decomposition.
7849
0
        input[--descending_idx] = input[input_count];
7850
0
      }
7851
0
    } else {
7852
      // Non-Unicode character.
7853
0
      input[--descending_idx] = input[input_count];
7854
0
    }
7855
0
  }
7856
0
}
7857
7858
0
uint8_t get_ccc(char32_t c) noexcept {
7859
0
  return c < 0x110000 ? canonical_combining_class_block
7860
0
                            [canonical_combining_class_index[c >> 8]][c % 256]
7861
0
                      : 0;
7862
0
}
7863
7864
0
void sort_marks(std::u32string& input) {
7865
0
  for (size_t idx = 1; idx < input.size(); idx++) {
7866
0
    uint8_t ccc = get_ccc(input[idx]);
7867
0
    if (ccc == 0) {
7868
0
      continue;
7869
0
    }  // Skip non-combining characters.
7870
0
    auto current_character = input[idx];
7871
0
    size_t back_idx = idx;
7872
0
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7873
0
      input[back_idx] = input[back_idx - 1];
7874
0
      back_idx--;
7875
0
    }
7876
0
    input[back_idx] = current_character;
7877
0
  }
7878
0
}
7879
7880
0
void decompose_nfc(std::u32string& input) {
7881
  /**
7882
   * Decompose the domain_name string to Unicode Normalization Form C.
7883
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7884
   */
7885
0
  auto [decomposition_needed, additional_elements] =
7886
0
      compute_decomposition_length(input);
7887
0
  if (decomposition_needed) {
7888
0
    decompose(input, additional_elements);
7889
0
  }
7890
0
  sort_marks(input);
7891
0
}
7892
7893
0
void compose(std::u32string& input) {
7894
  /**
7895
   * Compose the domain_name string to Unicode Normalization Form C.
7896
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7897
   */
7898
0
  size_t input_count{0};
7899
0
  size_t composition_count{0};
7900
0
  for (; input_count < input.size(); input_count++, composition_count++) {
7901
0
    input[composition_count] = input[input_count];
7902
0
    if (input[input_count] >= hangul_lbase &&
7903
0
        input[input_count] < hangul_lbase + hangul_lcount) {
7904
0
      if (input_count + 1 < input.size() &&
7905
0
          input[input_count + 1] >= hangul_vbase &&
7906
0
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7907
0
        input[composition_count] =
7908
0
            hangul_sbase +
7909
0
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7910
0
             input[input_count + 1] - hangul_vbase) *
7911
0
                hangul_tcount;
7912
0
        input_count++;
7913
0
        if (input_count + 1 < input.size() &&
7914
0
            input[input_count + 1] > hangul_tbase &&
7915
0
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7916
0
          input[composition_count] += input[++input_count] - hangul_tbase;
7917
0
        }
7918
0
      }
7919
0
    } else if (input[input_count] >= hangul_sbase &&
7920
0
               input[input_count] < hangul_sbase + hangul_scount) {
7921
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7922
0
          input_count + 1 < input.size() &&
7923
0
          input[input_count + 1] > hangul_tbase &&
7924
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7925
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7926
0
      }
7927
0
    } else if (input[input_count] < 0x110000) {
7928
0
      const uint16_t* composition =
7929
0
          &composition_block[composition_index[input[input_count] >> 8]]
7930
0
                            [input[input_count] % 256];
7931
0
      size_t initial_composition_count = composition_count;
7932
0
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7933
0
           input_count++) {
7934
0
        uint8_t ccc = get_ccc(input[input_count + 1]);
7935
7936
0
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7937
          // Try finding a composition.
7938
0
          int left = composition[0];
7939
0
          int right = composition[1];
7940
0
          while (left + 2 < right) {
7941
            // mean without overflow
7942
0
            int middle = left + (((right - left) >> 1) & ~1);
7943
0
            if (composition_data[middle] <= input[input_count + 1]) {
7944
0
              left = middle;
7945
0
            }
7946
0
            if (composition_data[middle] >= input[input_count + 1]) {
7947
0
              right = middle;
7948
0
            }
7949
0
          }
7950
0
          if (composition_data[left] == input[input_count + 1]) {
7951
0
            input[initial_composition_count] = composition_data[left + 1];
7952
0
            composition =
7953
0
                &composition_block
7954
0
                    [composition_index[composition_data[left + 1] >> 8]]
7955
0
                    [composition_data[left + 1] % 256];
7956
0
            continue;
7957
0
          }
7958
0
        }
7959
7960
0
        if (ccc == 0) {
7961
0
          break;
7962
0
        }  // Not a combining character.
7963
0
        previous_ccc = ccc;
7964
0
        input[++composition_count] = input[input_count + 1];
7965
0
      }
7966
0
    }
7967
0
  }
7968
7969
0
  if (composition_count < input_count) {
7970
0
    input.resize(composition_count);
7971
0
  }
7972
0
}
7973
7974
0
void normalize(std::u32string& input) {
7975
  /**
7976
   * Normalize the domain_name string to Unicode Normalization Form C.
7977
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
7978
   */
7979
0
  decompose_nfc(input);
7980
0
  compose(input);
7981
0
}
7982
7983
}  // namespace ada::idna
7984
/* end file src/normalization.cpp */
7985
/* begin file src/punycode.cpp */
7986
7987
#include <cstdint>
7988
7989
namespace ada::idna {
7990
7991
constexpr int32_t base = 36;
7992
constexpr int32_t tmin = 1;
7993
constexpr int32_t tmax = 26;
7994
constexpr int32_t skew = 38;
7995
constexpr int32_t damp = 700;
7996
constexpr int32_t initial_bias = 72;
7997
constexpr uint32_t initial_n = 128;
7998
7999
0
static constexpr int32_t char_to_digit_value(char value) {
8000
0
  if (value >= 'a' && value <= 'z') return value - 'a';
8001
0
  if (value >= '0' && value <= '9') return value - '0' + 26;
8002
0
  return -1;
8003
0
}
8004
8005
0
static constexpr char digit_to_char(int32_t digit) {
8006
0
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8007
0
}
8008
8009
0
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8010
0
  if (firsttime) {
8011
0
    d = d / damp;
8012
0
  } else {
8013
0
    d = d / 2;
8014
0
  }
8015
0
  d += d / n;
8016
0
  int32_t k = 0;
8017
0
  while (d > ((base - tmin) * tmax) / 2) {
8018
0
    d /= base - tmin;
8019
0
    k += base;
8020
0
  }
8021
0
  return k + (((base - tmin + 1) * d) / (d + skew));
8022
0
}
8023
8024
0
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8025
  // See https://github.com/whatwg/url/issues/803
8026
0
  if (input.starts_with("xn--")) {
8027
0
    return false;
8028
0
  }
8029
0
  int32_t written_out{0};
8030
0
  out.reserve(out.size() + input.size());
8031
0
  uint32_t n = initial_n;
8032
0
  int32_t i = 0;
8033
0
  int32_t bias = initial_bias;
8034
  // grab ascii content
8035
0
  size_t end_of_ascii = input.find_last_of('-');
8036
0
  if (end_of_ascii != std::string_view::npos) {
8037
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8038
0
      if (c >= 0x80) {
8039
0
        return false;
8040
0
      }
8041
0
      out.push_back(c);
8042
0
      written_out++;
8043
0
    }
8044
0
    input.remove_prefix(end_of_ascii + 1);
8045
0
  }
8046
0
  while (!input.empty()) {
8047
0
    int32_t oldi = i;
8048
0
    int32_t w = 1;
8049
0
    for (int32_t k = base;; k += base) {
8050
0
      if (input.empty()) {
8051
0
        return false;
8052
0
      }
8053
0
      uint8_t code_point = input.front();
8054
0
      input.remove_prefix(1);
8055
0
      int32_t digit = char_to_digit_value(code_point);
8056
0
      if (digit < 0) {
8057
0
        return false;
8058
0
      }
8059
0
      if (digit > (0x7fffffff - i) / w) {
8060
0
        return false;
8061
0
      }
8062
0
      i = i + digit * w;
8063
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8064
0
      if (digit < t) {
8065
0
        break;
8066
0
      }
8067
0
      if (w > 0x7fffffff / (base - t)) {
8068
0
        return false;
8069
0
      }
8070
0
      w = w * (base - t);
8071
0
    }
8072
0
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8073
0
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8074
0
      return false;
8075
0
    }
8076
0
    n = n + i / (written_out + 1);
8077
0
    i = i % (written_out + 1);
8078
0
    if (n < 0x80) {
8079
0
      return false;
8080
0
    }
8081
0
    out.insert(out.begin() + i, n);
8082
0
    written_out++;
8083
0
    ++i;
8084
0
  }
8085
0
  return true;
8086
0
}
8087
8088
0
bool verify_punycode(std::string_view input) {
8089
0
  if (input.starts_with("xn--")) {
8090
0
    return false;
8091
0
  }
8092
0
  size_t written_out{0};
8093
0
  uint32_t n = initial_n;
8094
0
  int32_t i = 0;
8095
0
  int32_t bias = initial_bias;
8096
  // grab ascii content
8097
0
  size_t end_of_ascii = input.find_last_of('-');
8098
0
  if (end_of_ascii != std::string_view::npos) {
8099
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8100
0
      if (c >= 0x80) {
8101
0
        return false;
8102
0
      }
8103
0
      written_out++;
8104
0
    }
8105
0
    input.remove_prefix(end_of_ascii + 1);
8106
0
  }
8107
0
  while (!input.empty()) {
8108
0
    int32_t oldi = i;
8109
0
    int32_t w = 1;
8110
0
    for (int32_t k = base;; k += base) {
8111
0
      if (input.empty()) {
8112
0
        return false;
8113
0
      }
8114
0
      uint8_t code_point = input.front();
8115
0
      input.remove_prefix(1);
8116
0
      int32_t digit = char_to_digit_value(code_point);
8117
0
      if (digit < 0) {
8118
0
        return false;
8119
0
      }
8120
0
      if (digit > (0x7fffffff - i) / w) {
8121
0
        return false;
8122
0
      }
8123
0
      i = i + digit * w;
8124
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8125
0
      if (digit < t) {
8126
0
        break;
8127
0
      }
8128
0
      if (w > 0x7fffffff / (base - t)) {
8129
0
        return false;
8130
0
      }
8131
0
      w = w * (base - t);
8132
0
    }
8133
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8134
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
8135
0
      return false;
8136
0
    }
8137
0
    n = n + i / int32_t(written_out + 1);
8138
0
    i = i % int32_t(written_out + 1);
8139
0
    if (n < 0x80) {
8140
0
      return false;
8141
0
    }
8142
0
    written_out++;
8143
0
    ++i;
8144
0
  }
8145
8146
0
  return true;
8147
0
}
8148
8149
0
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8150
0
  out.reserve(input.size() + out.size());
8151
0
  uint32_t n = initial_n;
8152
0
  int32_t d = 0;
8153
0
  int32_t bias = initial_bias;
8154
0
  size_t h = 0;
8155
  // first push the ascii content
8156
0
  for (uint32_t c : input) {
8157
0
    if (c < 0x80) {
8158
0
      ++h;
8159
0
      out.push_back(char(c));
8160
0
    }
8161
0
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8162
0
      return false;
8163
0
    }
8164
0
  }
8165
0
  size_t b = h;
8166
0
  if (b > 0) {
8167
0
    out.push_back('-');
8168
0
  }
8169
0
  while (h < input.size()) {
8170
0
    uint32_t m = 0x10FFFF;
8171
0
    for (auto code_point : input) {
8172
0
      if (code_point >= n && code_point < m) m = code_point;
8173
0
    }
8174
8175
0
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8176
0
      return false;
8177
0
    }
8178
0
    d = d + int32_t((m - n) * (h + 1));
8179
0
    n = m;
8180
0
    for (auto c : input) {
8181
0
      if (c < n) {
8182
0
        if (d == 0x7fffffff) {
8183
0
          return false;
8184
0
        }
8185
0
        ++d;
8186
0
      }
8187
0
      if (c == n) {
8188
0
        int32_t q = d;
8189
0
        for (int32_t k = base;; k += base) {
8190
0
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8191
8192
0
          if (q < t) {
8193
0
            break;
8194
0
          }
8195
0
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8196
0
          q = (q - t) / (base - t);
8197
0
        }
8198
0
        out.push_back(digit_to_char(q));
8199
0
        bias = adapt(d, int32_t(h + 1), h == b);
8200
0
        d = 0;
8201
0
        ++h;
8202
0
      }
8203
0
    }
8204
0
    ++d;
8205
0
    ++n;
8206
0
  }
8207
0
  return true;
8208
0
}
8209
8210
}  // namespace ada::idna
8211
/* end file src/punycode.cpp */
8212
/* begin file src/validity.cpp */
8213
#include <algorithm>
8214
#include <string_view>
8215
8216
namespace ada::idna {
8217
8218
enum direction : uint8_t {
8219
  NONE,
8220
  BN,
8221
  CS,
8222
  ES,
8223
  ON,
8224
  EN,
8225
  L,
8226
  R,
8227
  NSM,
8228
  AL,
8229
  AN,
8230
  ET,
8231
  WS,
8232
  RLO,
8233
  LRO,
8234
  PDF,
8235
  RLE,
8236
  RLI,
8237
  FSI,
8238
  PDI,
8239
  LRI,
8240
  B,
8241
  S,
8242
  LRE
8243
};
8244
8245
struct directions {
8246
  uint32_t start_code;
8247
  uint32_t final_code;
8248
  direction direct;
8249
};
8250
8251
static directions dir_table[] = {
8252
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8253
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8254
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8255
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8256
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8257
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8258
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8259
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8260
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8261
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8262
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8263
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8264
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8265
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8266
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8267
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8268
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8269
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8270
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8271
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8272
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8273
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8274
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8275
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8276
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8277
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8278
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8279
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8280
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8281
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8282
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8283
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8284
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8285
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8286
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8287
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8288
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8289
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8290
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8291
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8292
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8293
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8294
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8295
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8296
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8297
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8298
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8299
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8300
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8301
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8302
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8303
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8304
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8305
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8306
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8307
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8308
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8309
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8310
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8311
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8312
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8313
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8314
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8315
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8316
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8317
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8318
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8319
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8320
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8321
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8322
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8323
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8324
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8325
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8326
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8327
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8328
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8329
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8330
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8331
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8332
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8333
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8334
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8335
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8336
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8337
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8338
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8339
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8340
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8341
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8342
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8343
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8344
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8345
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8346
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8347
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8348
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8349
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8350
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8351
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8352
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8353
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8354
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8355
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8356
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8357
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8358
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8359
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8360
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8361
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8362
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8363
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8364
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8365
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8366
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8367
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8368
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8369
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8370
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8371
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8372
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8373
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8374
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8375
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8376
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8377
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8378
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8379
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8380
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8381
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8382
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8383
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8384
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8385
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8386
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8387
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8388
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8389
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8390
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8391
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8392
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8393
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8394
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8395
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8396
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8397
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8398
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8399
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8400
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8401
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8402
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8403
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8404
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8405
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8406
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8407
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8408
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8409
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8410
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8411
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8412
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8413
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8414
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8415
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8416
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8417
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8418
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8419
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8420
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8421
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8422
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8423
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8424
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8425
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8426
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8427
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8428
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8429
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8430
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8431
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8432
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8433
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8434
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8435
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8436
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8437
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8438
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8439
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8440
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8441
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8442
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8443
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8444
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8445
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8446
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8447
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8448
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8449
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8450
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8451
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8452
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8453
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8454
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8455
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8456
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8457
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8458
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8459
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8460
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8461
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8462
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8463
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8464
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8465
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8466
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8467
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8468
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8469
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8470
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8471
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8472
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8473
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8474
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8475
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8476
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8477
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8478
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8479
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8480
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8481
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8482
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8483
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8484
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8485
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8486
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8487
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8488
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8489
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8490
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8491
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8492
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8493
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8494
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8495
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8496
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8497
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8498
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8499
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8500
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8501
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8502
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8503
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8504
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8505
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8506
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8507
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8508
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8509
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8510
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8511
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8512
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8513
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8514
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8515
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8516
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8517
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8518
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8519
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8520
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8521
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8522
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8523
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8524
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8525
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8526
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8527
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8528
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8529
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8530
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8531
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8532
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8533
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8534
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8535
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8536
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8537
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8538
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8539
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8540
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8541
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8542
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8543
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8544
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8545
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8546
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8547
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8548
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8549
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8550
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8551
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8552
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8553
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8554
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8555
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8556
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8557
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8558
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8559
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8560
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8561
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8562
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8563
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8564
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8565
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8566
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8567
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8568
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8569
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8570
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8571
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8572
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8573
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8574
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8575
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8576
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8577
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8578
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8579
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8580
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8581
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8582
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8583
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8584
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8585
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8586
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8587
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8588
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8589
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8590
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8591
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8592
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8593
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8594
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8595
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8596
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8597
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8598
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8599
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8600
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8601
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8602
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8603
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8604
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8605
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8606
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8607
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8608
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8609
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8610
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8611
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8612
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8613
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8614
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8615
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8616
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8617
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8618
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8619
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8620
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8621
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8622
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8623
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8624
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8625
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8626
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8627
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8628
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8629
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8630
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8631
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8632
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8633
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8634
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8635
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8636
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8637
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8638
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8639
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8640
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8641
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8642
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8643
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8644
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8645
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8646
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8647
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8648
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8649
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8650
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8651
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8652
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8653
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8654
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8655
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8656
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8657
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8658
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8659
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8660
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8661
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8662
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8663
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8664
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8665
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8666
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8667
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8668
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8669
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8670
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8671
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8672
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8673
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8674
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8675
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8676
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8677
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8678
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8679
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8680
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8681
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8682
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8683
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8684
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8685
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8686
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8687
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8688
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8689
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8690
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8691
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8692
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8693
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8694
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8695
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8696
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8697
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8698
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8699
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8700
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8701
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8702
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8703
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8704
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8705
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8706
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8707
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8708
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8709
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8710
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8711
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8712
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8713
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8714
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8715
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8716
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8717
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8718
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8719
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8720
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8721
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8722
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8723
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8724
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8725
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8726
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8727
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8728
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8729
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8730
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8731
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8732
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8733
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8734
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8735
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8736
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8737
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8738
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8739
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8740
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8741
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8742
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8743
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8744
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8745
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8746
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8747
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8748
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8749
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8750
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8751
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8752
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8753
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8754
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8755
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8756
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8757
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8758
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8759
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8760
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8761
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8762
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8763
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8764
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8765
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8766
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8767
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8768
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8769
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8770
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8771
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8772
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8773
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8774
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8775
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8776
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8777
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8778
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8779
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8780
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8781
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8782
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8783
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8784
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8785
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8786
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8787
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8788
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8789
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8790
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8791
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8792
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8793
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8794
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8795
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8796
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8797
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8798
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8799
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8800
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8801
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8802
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8803
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8804
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8805
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8806
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8807
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8808
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8809
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8810
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8811
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8812
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8813
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8814
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8815
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8816
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8817
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8818
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8819
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8820
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8821
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8822
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8823
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8824
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8825
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8826
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8827
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8828
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8829
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8830
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8831
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8832
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8833
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8834
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8835
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8836
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8837
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8838
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8839
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8840
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8841
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8842
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8843
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8844
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8845
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8846
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8847
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8848
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8849
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8850
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8851
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8852
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8853
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8854
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8855
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8856
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8857
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8858
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8859
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8860
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8861
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8862
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8863
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8864
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8865
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8866
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8867
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8868
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8869
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8870
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8871
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8872
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8873
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8874
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8875
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8876
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8877
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8878
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8879
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8880
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8881
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8882
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8883
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8884
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8885
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8886
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8887
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8888
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8889
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8890
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8891
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8892
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8893
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8894
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8895
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8896
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8897
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8898
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8899
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8900
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8901
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8902
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8903
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8904
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8905
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8906
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8907
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8908
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8909
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8910
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8911
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8912
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8913
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8914
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8915
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8916
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8917
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8918
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8919
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8920
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8921
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8922
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8923
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8924
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8925
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8926
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8927
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8928
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8929
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8930
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8931
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8932
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8933
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8934
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8935
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8936
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8937
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8938
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8939
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
8940
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
8941
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
8942
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
8943
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
8944
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
8945
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
8946
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
8947
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
8948
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
8949
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
8950
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
8951
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
8952
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
8953
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
8954
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
8955
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
8956
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
8957
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
8958
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
8959
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
8960
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
8961
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
8962
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
8963
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
8964
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
8965
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
8966
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
8967
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
8968
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
8969
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
8970
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
8971
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
8972
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
8973
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
8974
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
8975
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
8976
    {0x100000, 0x10fffd, direction::L}};
8977
8978
// CheckJoiners and CheckBidi are true for URL specification.
8979
8980
0
inline static direction find_direction(uint32_t code_point) noexcept {
8981
0
  auto it = std::lower_bound(
8982
0
      std::begin(dir_table), std::end(dir_table), code_point,
8983
0
      [](const directions& d, uint32_t c) { return d.final_code < c; });
8984
8985
  // next check is almost surely in vain, but we use it for safety.
8986
0
  if (it == std::end(dir_table)) {
8987
0
    return direction::NONE;
8988
0
  }
8989
  // We have that d.final_code >= c.
8990
0
  if (code_point >= it->start_code) {
8991
0
    return it->direct;
8992
0
  }
8993
0
  return direction::NONE;
8994
0
}
8995
8996
inline static size_t find_last_not_of_nsm(
8997
0
    const std::u32string_view label) noexcept {
8998
0
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
8999
0
    if (find_direction(label[i]) != direction::NSM) return i;
9000
9001
0
  return std::u32string_view::npos;
9002
0
}
9003
9004
// An RTL label is a label that contains at least one character of type R, AL,
9005
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9006
0
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9007
0
  const size_t mask =
9008
0
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9009
9010
0
  size_t directions = 0;
9011
0
  for (size_t i = 0; i < label.size(); i++) {
9012
0
    directions |= 1u << find_direction(label[i]);
9013
0
  }
9014
0
  return (directions & mask) != 0;
9015
0
}
9016
9017
0
bool is_label_valid(const std::u32string_view label) {
9018
0
  if (label.empty()) {
9019
0
    return true;
9020
0
  }
9021
9022
  ///////////////
9023
  // We have a normalization step which ensures that we are in NFC.
9024
  // If we receive punycode, we normalize and check that the normalized
9025
  // version matches the original.
9026
  // --------------------------------------
9027
  // The label must be in Unicode Normalization Form NFC.
9028
9029
  // Current URL standard indicatest that CheckHyphens is set to false.
9030
  // ---------------------------------------
9031
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9032
  // in both the third and fourth positions. If CheckHyphens, the label must
9033
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9034
9035
  // This is not necessary because we segment the
9036
  // labels by '.'.
9037
  // ---------------------------------------
9038
  // The label must not contain a U+002E ( . ) FULL STOP.
9039
  // if (label.find('.') != std::string_view::npos) return false;
9040
9041
  // The label must not begin with a combining mark, that is:
9042
  // General_Category=Mark.
9043
0
  constexpr static uint32_t combining[] = {
9044
0
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9045
0
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9046
0
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9047
0
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9048
0
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9049
0
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9050
0
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9051
0
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9052
0
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9053
0
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9054
0
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9055
0
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9056
0
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9057
0
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9058
0
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9059
0
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9060
0
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9061
0
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9062
0
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9063
0
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9064
0
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9065
0
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9066
0
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9067
0
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9068
0
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9069
0
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9070
0
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9071
0
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9072
0
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9073
0
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9074
0
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9075
0
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9076
0
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9077
0
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9078
0
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9079
0
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9080
0
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9081
0
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9082
0
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9083
0
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9084
0
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9085
0
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9086
0
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9087
0
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9088
0
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9089
0
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9090
0
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9091
0
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9092
0
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9093
0
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9094
0
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9095
0
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9096
0
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9097
0
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9098
0
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9099
0
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9100
0
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9101
0
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9102
0
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9103
0
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9104
0
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9105
0
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9106
0
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9107
0
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9108
0
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9109
0
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9110
0
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9111
0
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9112
0
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9113
0
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9114
0
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9115
0
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9116
0
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9117
0
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9118
0
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9119
0
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9120
0
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9121
0
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9122
0
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9123
0
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9124
0
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9125
0
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9126
0
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9127
0
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9128
0
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9129
0
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9130
0
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9131
0
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9132
0
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9133
0
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9134
0
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9135
0
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9136
0
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9137
0
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9138
0
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9139
0
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9140
0
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9141
0
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9142
0
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9143
0
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9144
0
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9145
0
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9146
0
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9147
0
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9148
0
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9149
0
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9150
0
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9151
0
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9152
0
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9153
0
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9154
0
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9155
0
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9156
0
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9157
0
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9158
0
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9159
0
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9160
0
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9161
0
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9162
0
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9163
0
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9164
0
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9165
0
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9166
0
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9167
0
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9168
0
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9169
0
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9170
0
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9171
0
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9172
0
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9173
0
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9174
0
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9175
0
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9176
0
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9177
0
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9178
0
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9179
0
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9180
0
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9181
0
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9182
0
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9183
0
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9184
0
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9185
0
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9186
0
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9187
0
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9188
0
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9189
0
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9190
0
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9191
0
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9192
0
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9193
0
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9194
0
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9195
0
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9196
0
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9197
0
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9198
0
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9199
0
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9200
0
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9201
0
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9202
0
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9203
0
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9204
0
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9205
0
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9206
0
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9207
0
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9208
0
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9209
0
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9210
0
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9211
0
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9212
0
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9213
0
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9214
0
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9215
0
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9216
0
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9217
0
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9218
0
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9219
0
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9220
0
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9221
0
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9222
0
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9223
0
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9224
0
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9225
0
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9226
0
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9227
0
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9228
0
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9229
0
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9230
0
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9231
0
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9232
0
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9233
0
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9234
0
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9235
0
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9236
0
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9237
0
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9238
0
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9239
0
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9240
0
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9241
0
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9242
0
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9243
0
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9244
0
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9245
0
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9246
0
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9247
0
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9248
0
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9249
0
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9250
0
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9251
0
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9252
0
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9253
0
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9254
0
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9255
0
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9256
0
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9257
0
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9258
0
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9259
0
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9260
0
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9261
0
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9262
0
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9263
0
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9264
0
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9265
0
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9266
0
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9267
0
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9268
0
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9269
0
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9270
0
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9271
0
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9272
0
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9273
0
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9274
0
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9275
0
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9276
0
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9277
0
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9278
0
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9279
0
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9280
0
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9281
0
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9282
0
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9283
0
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9284
0
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9285
0
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9286
0
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9287
0
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9288
0
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9289
0
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9290
0
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9291
0
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9292
0
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9293
0
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9294
0
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9295
0
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9296
0
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9297
0
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9298
0
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9299
0
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9300
0
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9301
0
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9302
0
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9303
0
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9304
0
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9305
0
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9306
0
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9307
0
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9308
0
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9309
0
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9310
0
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9311
0
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9312
0
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9313
0
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9314
0
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9315
0
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9316
0
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9317
0
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9318
0
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9319
0
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9320
0
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9321
0
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9322
0
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9323
0
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9324
0
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9325
0
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9326
0
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9327
0
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9328
0
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9329
0
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9330
0
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9331
0
  if (std::binary_search(std::begin(combining), std::end(combining),
9332
0
                         label.front())) {
9333
0
    return false;
9334
0
  }
9335
  // We verify this next step as part of the mapping:
9336
  // ---------------------------------------------
9337
  // Each code point in the label must only have certain status values
9338
  // according to Section 5, IDNA Mapping Table:
9339
  // - For Transitional Processing, each value must be valid.
9340
  // - For Nontransitional Processing, each value must be either valid or
9341
  // deviation.
9342
9343
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9344
  // A, in The Unicode Code Points and Internationalized Domain Names for
9345
  // Applications (IDNA) [IDNA2008].
9346
0
  constexpr static uint32_t virama[] = {
9347
0
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9348
0
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9349
0
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9350
0
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9351
0
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9352
0
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9353
0
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9354
0
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9355
0
  constexpr static uint32_t R[] = {
9356
0
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9357
0
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9358
0
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9359
0
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9360
0
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9361
0
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9362
0
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9363
0
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9364
0
  constexpr static uint32_t L[] = {0xa872};
9365
0
  constexpr static uint32_t D[] = {
9366
0
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9367
0
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9368
0
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9369
0
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9370
0
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9371
0
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9372
0
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9373
0
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9374
0
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9375
0
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9376
0
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9377
0
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9378
0
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9379
0
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9380
0
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9381
0
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9382
0
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9383
0
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9384
0
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9385
0
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9386
0
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9387
0
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9388
0
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9389
0
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9390
0
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9391
0
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9392
0
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9393
0
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9394
0
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9395
0
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9396
0
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9397
0
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9398
0
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9399
0
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9400
0
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9401
0
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9402
0
      0xa870, 0xa871};
9403
9404
0
  for (size_t i = 0; i < label.size(); i++) {
9405
0
    uint32_t c = label[i];
9406
0
    if (c == 0x200c) {
9407
0
      if (i > 0) {
9408
0
        if (std::binary_search(std::begin(virama), std::end(virama),
9409
0
                               label[i - 1])) {
9410
0
          return true;
9411
0
        }
9412
0
      }
9413
0
      if ((i == 0) || (i + 1 >= label.size())) {
9414
0
        return false;
9415
0
      }
9416
      // we go backward looking for L or D
9417
0
      auto is_l_or_d = [](uint32_t code) {
9418
0
        return std::binary_search(std::begin(L), std::end(L), code) ||
9419
0
               std::binary_search(std::begin(D), std::end(D), code);
9420
0
      };
9421
0
      auto is_r_or_d = [](uint32_t code) {
9422
0
        return std::binary_search(std::begin(R), std::end(R), code) ||
9423
0
               std::binary_search(std::begin(D), std::end(D), code);
9424
0
      };
9425
0
      std::u32string_view before = label.substr(0, i);
9426
0
      std::u32string_view after = label.substr(i + 1);
9427
0
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9428
0
              before.end()) &&
9429
0
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9430
0
              after.end());
9431
0
    } else if (c == 0x200d) {
9432
0
      if (i > 0) {
9433
0
        if (std::binary_search(std::begin(virama), std::end(virama),
9434
0
                               label[i - 1])) {
9435
0
          return true;
9436
0
        }
9437
0
      }
9438
0
      return false;
9439
0
    }
9440
0
  }
9441
9442
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9443
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9444
  // Section 2.
9445
9446
  // The following rule, consisting of six conditions, applies to labels
9447
  // in Bidi domain names.  The requirements that this rule satisfies are
9448
  // described in Section 3.  All of the conditions must be satisfied for
9449
  // the rule to be satisfied.
9450
  //
9451
  //  1.  The first character must be a character with Bidi property L, R,
9452
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9453
  //     has the L property, it is an LTR label.
9454
  //
9455
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9456
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9457
  //
9458
  //   3.  In an RTL label, the end of the label must be a character with
9459
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9460
  //       characters with Bidi property NSM.
9461
  //
9462
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9463
  //       vice versa.
9464
  //
9465
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9466
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9467
  //
9468
  //   6.  In an LTR label, the end of the label must be a character with
9469
  //       Bidi property L or EN, followed by zero or more characters with
9470
  //       Bidi property NSM.
9471
9472
0
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9473
0
  if (last_non_nsm_char == std::u32string_view::npos) {
9474
0
    return false;
9475
0
  }
9476
9477
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9478
  // The following rule, consisting of six conditions, applies to labels in Bidi
9479
  // domain names.
9480
0
  if (is_rtl_label(label)) {
9481
    // The first character must be a character with Bidi property L, R,
9482
    // or AL. If it has the R or AL property, it is an RTL label; if it
9483
    // has the L property, it is an LTR label.
9484
9485
0
    if (find_direction(label[0]) == direction::L) {
9486
      // Eval as LTR
9487
9488
      // In an LTR label, only characters with the Bidi properties L, EN,
9489
      // ES, CS, ET, ON, BN, or NSM are allowed.
9490
0
      for (size_t i = 0; i < last_non_nsm_char; i++) {
9491
0
        const direction d = find_direction(label[i]);
9492
0
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9493
0
              d == direction::CS || d == direction::ET || d == direction::ON ||
9494
0
              d == direction::BN || d == direction::NSM)) {
9495
0
          return false;
9496
0
        }
9497
9498
0
        if ((i == last_non_nsm_char) &&
9499
0
            !(d == direction::L || d == direction::EN)) {
9500
0
          return false;
9501
0
        }
9502
0
      }
9503
9504
0
      return true;
9505
9506
0
    } else {
9507
      // Eval as RTL
9508
9509
0
      bool has_an = false;
9510
0
      bool has_en = false;
9511
0
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9512
0
        const direction d = find_direction(label[i]);
9513
9514
        // NOLINTBEGIN(bugprone-assignment-in-if-condition)
9515
        // In an RTL label, if an EN is present, no AN may be present, and vice
9516
        // versa.
9517
0
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9518
0
            (d == direction::AN && ((has_an = true) && has_en))) {
9519
0
          return false;
9520
0
        }
9521
        // NOLINTEND(bugprone-assignment-in-if-condition)
9522
9523
0
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9524
0
              d == direction::EN || d == direction::ES || d == direction::CS ||
9525
0
              d == direction::ET || d == direction::ON || d == direction::BN ||
9526
0
              d == direction::NSM)) {
9527
0
          return false;
9528
0
        }
9529
9530
0
        if (i == last_non_nsm_char &&
9531
0
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9532
0
              d == direction::EN)) {
9533
0
          return false;
9534
0
        }
9535
0
      }
9536
9537
0
      return true;
9538
0
    }
9539
0
  }
9540
9541
0
  return true;
9542
0
}
9543
9544
}  // namespace ada::idna
9545
/* end file src/validity.cpp */
9546
/* begin file src/to_ascii.cpp */
9547
9548
#include <algorithm>
9549
#include <cstdint>
9550
#include <ranges>
9551
9552
9553
#ifdef ADA_USE_SIMDUTF
9554
#include "simdutf.h"
9555
#endif
9556
9557
namespace ada::idna {
9558
9559
0
bool constexpr is_ascii(std::u32string_view view) {
9560
0
  for (uint32_t c : view) {
9561
0
    if (c >= 0x80) {
9562
0
      return false;
9563
0
    }
9564
0
  }
9565
0
  return true;
9566
0
}
9567
9568
0
bool constexpr is_ascii(std::string_view view) {
9569
0
  for (uint8_t c : view) {
9570
0
    if (c >= 0x80) {
9571
0
      return false;
9572
0
    }
9573
0
  }
9574
0
  return true;
9575
0
}
9576
9577
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9578
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9579
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9580
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9581
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9582
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9583
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9584
    1, 1, 1, 1, 1, 1, 1, 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};
9589
9590
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9591
9592
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9593
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9594
0
}
9595
9596
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9597
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9598
0
}
9599
9600
// We return "" on error.
9601
0
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9602
0
  static const std::string error = "";
9603
  // copy and map
9604
  // we could be more efficient by avoiding the copy when unnecessary.
9605
0
  std::string mapped_string = std::string(ut8_string);
9606
0
  ascii_map(mapped_string.data(), mapped_string.size());
9607
0
  std::string out;
9608
0
  size_t label_start = 0;
9609
9610
0
  while (label_start != mapped_string.size()) {
9611
0
    size_t loc_dot = mapped_string.find('.', label_start);
9612
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9613
0
    size_t label_size = is_last_label ? mapped_string.size() - label_start
9614
0
                                      : loc_dot - label_start;
9615
0
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9616
0
    std::string_view label_view(mapped_string.data() + label_start, label_size);
9617
0
    label_start += label_size_with_dot;
9618
0
    if (label_size == 0) {
9619
      // empty label? Nothing to do.
9620
0
    } else if (label_view.starts_with("xn--")) {
9621
      // The xn-- part is the expensive game.
9622
0
      out.append(label_view);
9623
0
      std::string_view puny_segment_ascii(
9624
0
          out.data() + out.size() - label_view.size() + 4,
9625
0
          label_view.size() - 4);
9626
0
      std::u32string tmp_buffer;
9627
0
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9628
0
      if (!is_ok) {
9629
0
        return error;
9630
0
      }
9631
      // If the input is just ASCII, it should not have been encoded
9632
      // as punycode.
9633
      // https://github.com/whatwg/url/issues/760
9634
0
      if (is_ascii(tmp_buffer)) {
9635
0
        return error;
9636
0
      }
9637
0
      std::u32string post_map = ada::idna::map(tmp_buffer);
9638
0
      if (tmp_buffer != post_map) {
9639
0
        return error;
9640
0
      }
9641
0
      std::u32string pre_normal = post_map;
9642
0
      normalize(post_map);
9643
0
      if (post_map != pre_normal) {
9644
0
        return error;
9645
0
      }
9646
0
      if (post_map.empty()) {
9647
0
        return error;
9648
0
      }
9649
0
      if (!is_label_valid(post_map)) {
9650
0
        return error;
9651
0
      }
9652
0
    } else {
9653
0
      out.append(label_view);
9654
0
    }
9655
0
    if (!is_last_label) {
9656
0
      out.push_back('.');
9657
0
    }
9658
0
  }
9659
0
  return out;
9660
0
}
9661
9662
// We return "" on error.
9663
0
std::string to_ascii(std::string_view ut8_string) {
9664
0
  if (is_ascii(ut8_string)) {
9665
0
    return from_ascii_to_ascii(ut8_string);
9666
0
  }
9667
0
  static const std::string error = "";
9668
  // We convert to UTF-32
9669
9670
#ifdef ADA_USE_SIMDUTF
9671
  size_t utf32_length =
9672
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9673
  std::u32string utf32(utf32_length, '\0');
9674
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9675
      ut8_string.data(), ut8_string.size(), utf32.data());
9676
#else
9677
0
  size_t utf32_length =
9678
0
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9679
0
  std::u32string utf32(utf32_length, '\0');
9680
0
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9681
0
      ut8_string.data(), ut8_string.size(), utf32.data());
9682
0
#endif
9683
0
  if (actual_utf32_length == 0) {
9684
0
    return error;
9685
0
  }
9686
  // mapping
9687
0
  utf32 = ada::idna::map(utf32);
9688
0
  normalize(utf32);
9689
0
  std::string out;
9690
0
  size_t label_start = 0;
9691
9692
0
  while (label_start != utf32.size()) {
9693
0
    size_t loc_dot = utf32.find('.', label_start);
9694
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9695
0
    size_t label_size =
9696
0
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9697
0
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9698
0
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9699
0
    label_start += label_size_with_dot;
9700
0
    if (label_size == 0) {
9701
      // empty label? Nothing to do.
9702
0
    } else if (label_view.starts_with(U"xn--")) {
9703
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9704
0
      for (char32_t c : label_view) {
9705
0
        if (c >= 0x80) {
9706
0
          return error;
9707
0
        }
9708
0
        out += (unsigned char)(c);
9709
0
      }
9710
0
      std::string_view puny_segment_ascii(
9711
0
          out.data() + out.size() - label_view.size() + 4,
9712
0
          label_view.size() - 4);
9713
0
      std::u32string tmp_buffer;
9714
0
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9715
0
      if (!is_ok) {
9716
0
        return error;
9717
0
      }
9718
      // If the input is just ASCII, it should not have been encoded
9719
      // as punycode.
9720
      // https://github.com/whatwg/url/issues/760
9721
0
      if (is_ascii(tmp_buffer)) {
9722
0
        return error;
9723
0
      }
9724
0
      std::u32string post_map = ada::idna::map(tmp_buffer);
9725
0
      if (tmp_buffer != post_map) {
9726
0
        return error;
9727
0
      }
9728
0
      std::u32string pre_normal = post_map;
9729
0
      normalize(post_map);
9730
0
      if (post_map != pre_normal) {
9731
0
        return error;
9732
0
      }
9733
0
      if (post_map.empty()) {
9734
0
        return error;
9735
0
      }
9736
0
      if (!is_label_valid(post_map)) {
9737
0
        return error;
9738
0
      }
9739
0
    } else {
9740
      // The fast path here is an ascii label.
9741
0
      if (is_ascii(label_view)) {
9742
        // no validation needed.
9743
0
        for (char32_t c : label_view) {
9744
0
          out += (unsigned char)(c);
9745
0
        }
9746
0
      } else {
9747
        // slow path.
9748
        // first check validity.
9749
0
        if (!is_label_valid(label_view)) {
9750
0
          return error;
9751
0
        }
9752
        // It is valid! So now we must encode it as punycode...
9753
0
        out.append("xn--");
9754
0
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9755
0
        if (!is_ok) {
9756
0
          return error;
9757
0
        }
9758
0
      }
9759
0
    }
9760
0
    if (!is_last_label) {
9761
0
      out.push_back('.');
9762
0
    }
9763
0
  }
9764
0
  return out;
9765
0
}
9766
}  // namespace ada::idna
9767
/* end file src/to_ascii.cpp */
9768
/* begin file src/to_unicode.cpp */
9769
9770
#include <algorithm>
9771
#include <string>
9772
9773
9774
#ifdef ADA_USE_SIMDUTF
9775
#include "simdutf.h"
9776
#endif
9777
9778
namespace ada::idna {
9779
0
std::string to_unicode(std::string_view input) {
9780
0
  std::string output;
9781
0
  output.reserve(input.size());
9782
9783
0
  size_t label_start = 0;
9784
0
  while (label_start < input.size()) {
9785
0
    size_t loc_dot = input.find('.', label_start);
9786
0
    bool is_last_label = (loc_dot == std::string_view::npos);
9787
0
    size_t label_size =
9788
0
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9789
0
    auto label_view = std::string_view(input.data() + label_start, label_size);
9790
9791
0
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9792
0
      label_view.remove_prefix(4);
9793
0
      if (ada::idna::verify_punycode(label_view)) {
9794
0
        std::u32string tmp_buffer;
9795
0
        if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9796
#ifdef ADA_USE_SIMDUTF
9797
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9798
                                                           tmp_buffer.size());
9799
          std::string final_utf8(utf8_size, '\0');
9800
          simdutf::convert_utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9801
                                         final_utf8.data());
9802
#else
9803
0
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9804
0
                                                             tmp_buffer.size());
9805
0
          std::string final_utf8(utf8_size, '\0');
9806
0
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9807
0
                                   final_utf8.data());
9808
0
#endif
9809
0
          output.append(final_utf8);
9810
0
        } else {
9811
          // ToUnicode never fails.  If any step fails, then the original input
9812
          // sequence is returned immediately in that step.
9813
0
          output.append(
9814
0
              std::string_view(input.data() + label_start, label_size));
9815
0
        }
9816
0
      } else {
9817
0
        output.append(std::string_view(input.data() + label_start, label_size));
9818
0
      }
9819
0
    } else {
9820
0
      output.append(label_view);
9821
0
    }
9822
9823
0
    if (!is_last_label) {
9824
0
      output.push_back('.');
9825
0
    }
9826
9827
0
    label_start += label_size + 1;
9828
0
  }
9829
9830
0
  return output;
9831
0
}
9832
}  // namespace ada::idna
9833
/* end file src/to_unicode.cpp */
9834
/* begin file src/identifier.cpp */
9835
9836
#include <algorithm>
9837
#include <array>
9838
#include <string>
9839
9840
/* begin file src/id_tables.cpp */
9841
// IDNA  16.0.0
9842
9843
// clang-format off
9844
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9845
#define ADA_IDNA_IDENTIFIER_TABLES_H
9846
#include <cstdint>
9847
9848
namespace ada::idna {
9849
9850
const uint32_t id_continue[1393][2] =
9851
{
9852
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9853
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9854
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9855
  {444, 447}, {448, 451}, {452, 659}, {660, 660},
9856
  {661, 687}, {688, 705}, {710, 721}, {736, 740},
9857
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9858
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9859
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9860
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9861
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9862
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9863
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9864
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9865
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9866
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9867
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9868
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9869
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9870
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9871
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9872
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9873
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9874
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9875
  {2185, 2190}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9876
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9877
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9878
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9879
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9880
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9881
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
9882
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
9883
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
9884
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
9885
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
9886
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
9887
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
9888
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
9889
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
9890
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
9891
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
9892
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
9893
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
9894
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
9895
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
9896
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
9897
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
9898
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
9899
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
9900
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
9901
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
9902
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
9903
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
9904
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
9905
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
9906
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
9907
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
9908
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
9909
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
9910
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
9911
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
9912
  {3157, 3158}, {3160, 3162}, {3165, 3165}, {3168, 3169},
9913
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
9914
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
9915
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
9916
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
9917
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
9918
  {3293, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
9919
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
9920
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
9921
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
9922
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
9923
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
9924
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
9925
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
9926
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
9927
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
9928
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
9929
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
9930
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
9931
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
9932
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
9933
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
9934
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
9935
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
9936
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
9937
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
9938
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
9939
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
9940
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
9941
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
9942
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
9943
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
9944
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
9945
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
9946
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
9947
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
9948
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
9949
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
9950
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
9951
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
9952
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
9953
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
9954
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
9955
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
9956
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
9957
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
9958
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
9959
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
9960
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
9961
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
9962
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
9963
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
9964
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
9965
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
9966
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
9967
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
9968
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
9969
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
9970
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
9971
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
9972
  {6832, 6845}, {6847, 6862}, {6912, 6915}, {6916, 6916},
9973
  {6917, 6963}, {6964, 6964}, {6965, 6965}, {6966, 6970},
9974
  {6971, 6971}, {6972, 6972}, {6973, 6977}, {6978, 6978},
9975
  {6979, 6980}, {6981, 6988}, {6992, 7001}, {7019, 7027},
9976
  {7040, 7041}, {7042, 7042}, {7043, 7072}, {7073, 7073},
9977
  {7074, 7077}, {7078, 7079}, {7080, 7081}, {7082, 7082},
9978
  {7083, 7085}, {7086, 7087}, {7088, 7097}, {7098, 7141},
9979
  {7142, 7142}, {7143, 7143}, {7144, 7145}, {7146, 7148},
9980
  {7149, 7149}, {7150, 7150}, {7151, 7153}, {7154, 7155},
9981
  {7168, 7203}, {7204, 7211}, {7212, 7219}, {7220, 7221},
9982
  {7222, 7223}, {7232, 7241}, {7245, 7247}, {7248, 7257},
9983
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
9984
  {7357, 7359}, {7376, 7378}, {7380, 7392}, {7393, 7393},
9985
  {7394, 7400}, {7401, 7404}, {7405, 7405}, {7406, 7411},
9986
  {7412, 7412}, {7413, 7414}, {7415, 7415}, {7416, 7417},
9987
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
9988
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7616, 7679},
9989
  {7680, 7957}, {7960, 7965}, {7968, 8005}, {8008, 8013},
9990
  {8016, 8023}, {8025, 8025}, {8027, 8027}, {8029, 8029},
9991
  {8031, 8061}, {8064, 8116}, {8118, 8124}, {8126, 8126},
9992
  {8130, 8132}, {8134, 8140}, {8144, 8147}, {8150, 8155},
9993
  {8160, 8172}, {8178, 8180}, {8182, 8188}, {8204, 8205},
9994
  {8255, 8256}, {8276, 8276}, {8305, 8305}, {8319, 8319},
9995
  {8336, 8348}, {8400, 8412}, {8417, 8417}, {8421, 8432},
9996
  {8450, 8450}, {8455, 8455}, {8458, 8467}, {8469, 8469},
9997
  {8472, 8472}, {8473, 8477}, {8484, 8484}, {8486, 8486},
9998
  {8488, 8488}, {8490, 8493}, {8494, 8494}, {8495, 8500},
9999
  {8501, 8504}, {8505, 8505}, {8508, 8511}, {8517, 8521},
10000
  {8526, 8526}, {8544, 8578}, {8579, 8580}, {8581, 8584},
10001
  {11264, 11387}, {11388, 11389}, {11390, 11492}, {11499, 11502},
10002
  {11503, 11505}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10003
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11647, 11647},
10004
  {11648, 11670}, {11680, 11686}, {11688, 11694}, {11696, 11702},
10005
  {11704, 11710}, {11712, 11718}, {11720, 11726}, {11728, 11734},
10006
  {11736, 11742}, {11744, 11775}, {12293, 12293}, {12294, 12294},
10007
  {12295, 12295}, {12321, 12329}, {12330, 12333}, {12334, 12335},
10008
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10009
  {12353, 12438}, {12441, 12442}, {12443, 12444}, {12445, 12446},
10010
  {12447, 12447}, {12449, 12538}, {12539, 12539}, {12540, 12542},
10011
  {12543, 12543}, {12549, 12591}, {12593, 12686}, {12704, 12735},
10012
  {12784, 12799}, {13312, 19903}, {19968, 40980}, {40981, 40981},
10013
  {40982, 42124}, {42192, 42231}, {42232, 42237}, {42240, 42507},
10014
  {42508, 42508}, {42512, 42527}, {42528, 42537}, {42538, 42539},
10015
  {42560, 42605}, {42606, 42606}, {42607, 42607}, {42612, 42621},
10016
  {42623, 42623}, {42624, 42651}, {42652, 42653}, {42654, 42655},
10017
  {42656, 42725}, {42726, 42735}, {42736, 42737}, {42775, 42783},
10018
  {42786, 42863}, {42864, 42864}, {42865, 42887}, {42888, 42888},
10019
  {42891, 42894}, {42895, 42895}, {42896, 42957}, {42960, 42961},
10020
  {42963, 42963}, {42965, 42972}, {42994, 42996}, {42997, 42998},
10021
  {42999, 42999}, {43000, 43001}, {43002, 43002}, {43003, 43009},
10022
  {43010, 43010}, {43011, 43013}, {43014, 43014}, {43015, 43018},
10023
  {43019, 43019}, {43020, 43042}, {43043, 43044}, {43045, 43046},
10024
  {43047, 43047}, {43052, 43052}, {43072, 43123}, {43136, 43137},
10025
  {43138, 43187}, {43188, 43203}, {43204, 43205}, {43216, 43225},
10026
  {43232, 43249}, {43250, 43255}, {43259, 43259}, {43261, 43262},
10027
  {43263, 43263}, {43264, 43273}, {43274, 43301}, {43302, 43309},
10028
  {43312, 43334}, {43335, 43345}, {43346, 43347}, {43360, 43388},
10029
  {43392, 43394}, {43395, 43395}, {43396, 43442}, {43443, 43443},
10030
  {43444, 43445}, {43446, 43449}, {43450, 43451}, {43452, 43453},
10031
  {43454, 43456}, {43471, 43471}, {43472, 43481}, {43488, 43492},
10032
  {43493, 43493}, {43494, 43494}, {43495, 43503}, {43504, 43513},
10033
  {43514, 43518}, {43520, 43560}, {43561, 43566}, {43567, 43568},
10034
  {43569, 43570}, {43571, 43572}, {43573, 43574}, {43584, 43586},
10035
  {43587, 43587}, {43588, 43595}, {43596, 43596}, {43597, 43597},
10036
  {43600, 43609}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10037
  {43642, 43642}, {43643, 43643}, {43644, 43644}, {43645, 43645},
10038
  {43646, 43695}, {43696, 43696}, {43697, 43697}, {43698, 43700},
10039
  {43701, 43702}, {43703, 43704}, {43705, 43709}, {43710, 43711},
10040
  {43712, 43712}, {43713, 43713}, {43714, 43714}, {43739, 43740},
10041
  {43741, 43741}, {43744, 43754}, {43755, 43755}, {43756, 43757},
10042
  {43758, 43759}, {43762, 43762}, {43763, 43764}, {43765, 43765},
10043
  {43766, 43766}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10044
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10045
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10046
  {44003, 44004}, {44005, 44005}, {44006, 44007}, {44008, 44008},
10047
  {44009, 44010}, {44012, 44012}, {44013, 44013}, {44016, 44025},
10048
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10049
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10050
  {64286, 64286}, {64287, 64296}, {64298, 64310}, {64312, 64316},
10051
  {64318, 64318}, {64320, 64321}, {64323, 64324}, {64326, 64433},
10052
  {64467, 64829}, {64848, 64911}, {64914, 64967}, {65008, 65019},
10053
  {65024, 65039}, {65056, 65071}, {65075, 65076}, {65101, 65103},
10054
  {65136, 65140}, {65142, 65276}, {65296, 65305}, {65313, 65338},
10055
  {65343, 65343}, {65345, 65370}, {65381, 65381}, {65382, 65391},
10056
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10057
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10058
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10059
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10060
  {66045, 66045}, {66176, 66204}, {66208, 66256}, {66272, 66272},
10061
  {66304, 66335}, {66349, 66368}, {66369, 66369}, {66370, 66377},
10062
  {66378, 66378}, {66384, 66421}, {66422, 66426}, {66432, 66461},
10063
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10064
  {66640, 66717}, {66720, 66729}, {66736, 66771}, {66776, 66811},
10065
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10066
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10067
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10068
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10069
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10070
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10071
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10072
  {67872, 67897}, {67968, 68023}, {68030, 68031}, {68096, 68096},
10073
  {68097, 68099}, {68101, 68102}, {68108, 68111}, {68112, 68115},
10074
  {68117, 68119}, {68121, 68149}, {68152, 68154}, {68159, 68159},
10075
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10076
  {68325, 68326}, {68352, 68405}, {68416, 68437}, {68448, 68466},
10077
  {68480, 68497}, {68608, 68680}, {68736, 68786}, {68800, 68850},
10078
  {68864, 68899}, {68900, 68903}, {68912, 68921}, {68928, 68937},
10079
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10080
  {68969, 68973}, {68975, 68975}, {68976, 68997}, {69248, 69289},
10081
  {69291, 69292}, {69296, 69297}, {69314, 69316}, {69372, 69375},
10082
  {69376, 69404}, {69415, 69415}, {69424, 69445}, {69446, 69456},
10083
  {69488, 69505}, {69506, 69509}, {69552, 69572}, {69600, 69622},
10084
  {69632, 69632}, {69633, 69633}, {69634, 69634}, {69635, 69687},
10085
  {69688, 69702}, {69734, 69743}, {69744, 69744}, {69745, 69746},
10086
  {69747, 69748}, {69749, 69749}, {69759, 69761}, {69762, 69762},
10087
  {69763, 69807}, {69808, 69810}, {69811, 69814}, {69815, 69816},
10088
  {69817, 69818}, {69826, 69826}, {69840, 69864}, {69872, 69881},
10089
  {69888, 69890}, {69891, 69926}, {69927, 69931}, {69932, 69932},
10090
  {69933, 69940}, {69942, 69951}, {69956, 69956}, {69957, 69958},
10091
  {69959, 69959}, {69968, 70002}, {70003, 70003}, {70006, 70006},
10092
  {70016, 70017}, {70018, 70018}, {70019, 70066}, {70067, 70069},
10093
  {70070, 70078}, {70079, 70080}, {70081, 70084}, {70089, 70092},
10094
  {70094, 70094}, {70095, 70095}, {70096, 70105}, {70106, 70106},
10095
  {70108, 70108}, {70144, 70161}, {70163, 70187}, {70188, 70190},
10096
  {70191, 70193}, {70194, 70195}, {70196, 70196}, {70197, 70197},
10097
  {70198, 70199}, {70206, 70206}, {70207, 70208}, {70209, 70209},
10098
  {70272, 70278}, {70280, 70280}, {70282, 70285}, {70287, 70301},
10099
  {70303, 70312}, {70320, 70366}, {70367, 70367}, {70368, 70370},
10100
  {70371, 70378}, {70384, 70393}, {70400, 70401}, {70402, 70403},
10101
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10102
  {70450, 70451}, {70453, 70457}, {70459, 70460}, {70461, 70461},
10103
  {70462, 70463}, {70464, 70464}, {70465, 70468}, {70471, 70472},
10104
  {70475, 70477}, {70480, 70480}, {70487, 70487}, {70493, 70497},
10105
  {70498, 70499}, {70502, 70508}, {70512, 70516}, {70528, 70537},
10106
  {70539, 70539}, {70542, 70542}, {70544, 70581}, {70583, 70583},
10107
  {70584, 70586}, {70587, 70592}, {70594, 70594}, {70597, 70597},
10108
  {70599, 70602}, {70604, 70605}, {70606, 70606}, {70607, 70607},
10109
  {70608, 70608}, {70609, 70609}, {70610, 70610}, {70611, 70611},
10110
  {70625, 70626}, {70656, 70708}, {70709, 70711}, {70712, 70719},
10111
  {70720, 70721}, {70722, 70724}, {70725, 70725}, {70726, 70726},
10112
  {70727, 70730}, {70736, 70745}, {70750, 70750}, {70751, 70753},
10113
  {70784, 70831}, {70832, 70834}, {70835, 70840}, {70841, 70841},
10114
  {70842, 70842}, {70843, 70846}, {70847, 70848}, {70849, 70849},
10115
  {70850, 70851}, {70852, 70853}, {70855, 70855}, {70864, 70873},
10116
  {71040, 71086}, {71087, 71089}, {71090, 71093}, {71096, 71099},
10117
  {71100, 71101}, {71102, 71102}, {71103, 71104}, {71128, 71131},
10118
  {71132, 71133}, {71168, 71215}, {71216, 71218}, {71219, 71226},
10119
  {71227, 71228}, {71229, 71229}, {71230, 71230}, {71231, 71232},
10120
  {71236, 71236}, {71248, 71257}, {71296, 71338}, {71339, 71339},
10121
  {71340, 71340}, {71341, 71341}, {71342, 71343}, {71344, 71349},
10122
  {71350, 71350}, {71351, 71351}, {71352, 71352}, {71360, 71369},
10123
  {71376, 71395}, {71424, 71450}, {71453, 71453}, {71454, 71454},
10124
  {71455, 71455}, {71456, 71457}, {71458, 71461}, {71462, 71462},
10125
  {71463, 71467}, {71472, 71481}, {71488, 71494}, {71680, 71723},
10126
  {71724, 71726}, {71727, 71735}, {71736, 71736}, {71737, 71738},
10127
  {71840, 71903}, {71904, 71913}, {71935, 71942}, {71945, 71945},
10128
  {71948, 71955}, {71957, 71958}, {71960, 71983}, {71984, 71989},
10129
  {71991, 71992}, {71995, 71996}, {71997, 71997}, {71998, 71998},
10130
  {71999, 71999}, {72000, 72000}, {72001, 72001}, {72002, 72002},
10131
  {72003, 72003}, {72016, 72025}, {72096, 72103}, {72106, 72144},
10132
  {72145, 72147}, {72148, 72151}, {72154, 72155}, {72156, 72159},
10133
  {72160, 72160}, {72161, 72161}, {72163, 72163}, {72164, 72164},
10134
  {72192, 72192}, {72193, 72202}, {72203, 72242}, {72243, 72248},
10135
  {72249, 72249}, {72250, 72250}, {72251, 72254}, {72263, 72263},
10136
  {72272, 72272}, {72273, 72278}, {72279, 72280}, {72281, 72283},
10137
  {72284, 72329}, {72330, 72342}, {72343, 72343}, {72344, 72345},
10138
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72688, 72697},
10139
  {72704, 72712}, {72714, 72750}, {72751, 72751}, {72752, 72758},
10140
  {72760, 72765}, {72766, 72766}, {72767, 72767}, {72768, 72768},
10141
  {72784, 72793}, {72818, 72847}, {72850, 72871}, {72873, 72873},
10142
  {72874, 72880}, {72881, 72881}, {72882, 72883}, {72884, 72884},
10143
  {72885, 72886}, {72960, 72966}, {72968, 72969}, {72971, 73008},
10144
  {73009, 73014}, {73018, 73018}, {73020, 73021}, {73023, 73029},
10145
  {73030, 73030}, {73031, 73031}, {73040, 73049}, {73056, 73061},
10146
  {73063, 73064}, {73066, 73097}, {73098, 73102}, {73104, 73105},
10147
  {73107, 73108}, {73109, 73109}, {73110, 73110}, {73111, 73111},
10148
  {73112, 73112}, {73120, 73129}, {73440, 73458}, {73459, 73460},
10149
  {73461, 73462}, {73472, 73473}, {73474, 73474}, {73475, 73475},
10150
  {73476, 73488}, {73490, 73523}, {73524, 73525}, {73526, 73530},
10151
  {73534, 73535}, {73536, 73536}, {73537, 73537}, {73538, 73538},
10152
  {73552, 73561}, {73562, 73562}, {73648, 73648}, {73728, 74649},
10153
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10154
  {78912, 78912}, {78913, 78918}, {78919, 78933}, {78944, 82938},
10155
  {82944, 83526}, {90368, 90397}, {90398, 90409}, {90410, 90412},
10156
  {90413, 90415}, {90416, 90425}, {92160, 92728}, {92736, 92766},
10157
  {92768, 92777}, {92784, 92862}, {92864, 92873}, {92880, 92909},
10158
  {92912, 92916}, {92928, 92975}, {92976, 92982}, {92992, 92995},
10159
  {93008, 93017}, {93027, 93047}, {93053, 93071}, {93504, 93506},
10160
  {93507, 93546}, {93547, 93548}, {93552, 93561}, {93760, 93823},
10161
  {93952, 94026}, {94031, 94031}, {94032, 94032}, {94033, 94087},
10162
  {94095, 94098}, {94099, 94111}, {94176, 94177}, {94179, 94179},
10163
  {94180, 94180}, {94192, 94193}, {94208, 100343}, {100352, 101589},
10164
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10165
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10166
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10167
  {113792, 113800}, {113808, 113817}, {113821, 113822}, {118000, 118009},
10168
  {118528, 118573}, {118576, 118598}, {119141, 119142}, {119143, 119145},
10169
  {119149, 119154}, {119163, 119170}, {119173, 119179}, {119210, 119213},
10170
  {119362, 119364}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10171
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10172
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10173
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10174
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10175
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10176
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10177
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {120782, 120831},
10178
  {121344, 121398}, {121403, 121452}, {121461, 121461}, {121476, 121476},
10179
  {121499, 121503}, {121505, 121519}, {122624, 122633}, {122634, 122634},
10180
  {122635, 122654}, {122661, 122666}, {122880, 122886}, {122888, 122904},
10181
  {122907, 122913}, {122915, 122916}, {122918, 122922}, {122928, 122989},
10182
  {123023, 123023}, {123136, 123180}, {123184, 123190}, {123191, 123197},
10183
  {123200, 123209}, {123214, 123214}, {123536, 123565}, {123566, 123566},
10184
  {123584, 123627}, {123628, 123631}, {123632, 123641}, {124112, 124138},
10185
  {124139, 124139}, {124140, 124143}, {124144, 124153}, {124368, 124397},
10186
  {124398, 124399}, {124400, 124400}, {124401, 124410}, {124896, 124902},
10187
  {124904, 124907}, {124909, 124910}, {124912, 124926}, {124928, 125124},
10188
  {125136, 125142}, {125184, 125251}, {125252, 125258}, {125259, 125259},
10189
  {125264, 125273}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10190
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10191
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10192
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10193
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10194
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10195
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10196
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10197
  {126629, 126633}, {126635, 126651}, {130032, 130041}, {131072, 173791},
10198
  {173824, 177977}, {177984, 178205}, {178208, 183969}, {183984, 191456},
10199
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 205743},
10200
  {917760, 917999}
10201
};
10202
const uint32_t id_start[763][2] =
10203
{
10204
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10205
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10206
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10207
  {660, 660}, {661, 687}, {688, 705}, {710, 721},
10208
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10209
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10210
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10211
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10212
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10213
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10214
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10215
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10216
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10217
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10218
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10219
  {2160, 2183}, {2185, 2190}, {2208, 2248}, {2249, 2249},
10220
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10221
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10222
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10223
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10224
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10225
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10226
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10227
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10228
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10229
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10230
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10231
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10232
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10233
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10234
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10235
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10236
  {3160, 3162}, {3165, 3165}, {3168, 3169}, {3200, 3200},
10237
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10238
  {3253, 3257}, {3261, 3261}, {3293, 3294}, {3296, 3297},
10239
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10240
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10241
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10242
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10243
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10244
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10245
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10246
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10247
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10248
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10249
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10250
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10251
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10252
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10253
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10254
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10255
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10256
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10257
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10258
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10259
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10260
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10261
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10262
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10263
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10264
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10265
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10266
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10267
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10268
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10269
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10270
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10271
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10272
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10273
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10274
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10275
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10276
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10277
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10278
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10279
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10280
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10281
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10282
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10283
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10284
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10285
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10286
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10287
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10288
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10289
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10290
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10291
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10292
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10293
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10294
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42957},
10295
  {42960, 42961}, {42963, 42963}, {42965, 42972}, {42994, 42996},
10296
  {42997, 42998}, {42999, 42999}, {43000, 43001}, {43002, 43002},
10297
  {43003, 43009}, {43011, 43013}, {43015, 43018}, {43020, 43042},
10298
  {43072, 43123}, {43138, 43187}, {43250, 43255}, {43259, 43259},
10299
  {43261, 43262}, {43274, 43301}, {43312, 43334}, {43360, 43388},
10300
  {43396, 43442}, {43471, 43471}, {43488, 43492}, {43494, 43494},
10301
  {43495, 43503}, {43514, 43518}, {43520, 43560}, {43584, 43586},
10302
  {43588, 43595}, {43616, 43631}, {43632, 43632}, {43633, 43638},
10303
  {43642, 43642}, {43646, 43695}, {43697, 43697}, {43701, 43702},
10304
  {43705, 43709}, {43712, 43712}, {43714, 43714}, {43739, 43740},
10305
  {43741, 43741}, {43744, 43754}, {43762, 43762}, {43763, 43764},
10306
  {43777, 43782}, {43785, 43790}, {43793, 43798}, {43808, 43814},
10307
  {43816, 43822}, {43824, 43866}, {43868, 43871}, {43872, 43880},
10308
  {43881, 43881}, {43888, 43967}, {43968, 44002}, {44032, 55203},
10309
  {55216, 55238}, {55243, 55291}, {63744, 64109}, {64112, 64217},
10310
  {64256, 64262}, {64275, 64279}, {64285, 64285}, {64287, 64296},
10311
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10312
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10313
  {64914, 64967}, {65008, 65019}, {65136, 65140}, {65142, 65276},
10314
  {65313, 65338}, {65345, 65370}, {65382, 65391}, {65392, 65392},
10315
  {65393, 65437}, {65438, 65439}, {65440, 65470}, {65474, 65479},
10316
  {65482, 65487}, {65490, 65495}, {65498, 65500}, {65536, 65547},
10317
  {65549, 65574}, {65576, 65594}, {65596, 65597}, {65599, 65613},
10318
  {65616, 65629}, {65664, 65786}, {65856, 65908}, {66176, 66204},
10319
  {66208, 66256}, {66304, 66335}, {66349, 66368}, {66369, 66369},
10320
  {66370, 66377}, {66378, 66378}, {66384, 66421}, {66432, 66461},
10321
  {66464, 66499}, {66504, 66511}, {66513, 66517}, {66560, 66639},
10322
  {66640, 66717}, {66736, 66771}, {66776, 66811}, {66816, 66855},
10323
  {66864, 66915}, {66928, 66938}, {66940, 66954}, {66956, 66962},
10324
  {66964, 66965}, {66967, 66977}, {66979, 66993}, {66995, 67001},
10325
  {67003, 67004}, {67008, 67059}, {67072, 67382}, {67392, 67413},
10326
  {67424, 67431}, {67456, 67461}, {67463, 67504}, {67506, 67514},
10327
  {67584, 67589}, {67592, 67592}, {67594, 67637}, {67639, 67640},
10328
  {67644, 67644}, {67647, 67669}, {67680, 67702}, {67712, 67742},
10329
  {67808, 67826}, {67828, 67829}, {67840, 67861}, {67872, 67897},
10330
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68112, 68115},
10331
  {68117, 68119}, {68121, 68149}, {68192, 68220}, {68224, 68252},
10332
  {68288, 68295}, {68297, 68324}, {68352, 68405}, {68416, 68437},
10333
  {68448, 68466}, {68480, 68497}, {68608, 68680}, {68736, 68786},
10334
  {68800, 68850}, {68864, 68899}, {68938, 68941}, {68942, 68942},
10335
  {68943, 68943}, {68944, 68965}, {68975, 68975}, {68976, 68997},
10336
  {69248, 69289}, {69296, 69297}, {69314, 69316}, {69376, 69404},
10337
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10338
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10339
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10340
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10341
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10342
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10343
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10344
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10345
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10346
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10347
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10348
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10349
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10350
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10351
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10352
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10353
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10354
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10355
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10356
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10357
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10358
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10359
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73440, 73458},
10360
  {73474, 73474}, {73476, 73488}, {73490, 73523}, {73648, 73648},
10361
  {73728, 74649}, {74752, 74862}, {74880, 75075}, {77712, 77808},
10362
  {77824, 78895}, {78913, 78918}, {78944, 82938}, {82944, 83526},
10363
  {90368, 90397}, {92160, 92728}, {92736, 92766}, {92784, 92862},
10364
  {92880, 92909}, {92928, 92975}, {92992, 92995}, {93027, 93047},
10365
  {93053, 93071}, {93504, 93506}, {93507, 93546}, {93547, 93548},
10366
  {93760, 93823}, {93952, 94026}, {94032, 94032}, {94099, 94111},
10367
  {94176, 94177}, {94179, 94179}, {94208, 100343}, {100352, 101589},
10368
  {101631, 101640}, {110576, 110579}, {110581, 110587}, {110589, 110590},
10369
  {110592, 110882}, {110898, 110898}, {110928, 110930}, {110933, 110933},
10370
  {110948, 110951}, {110960, 111355}, {113664, 113770}, {113776, 113788},
10371
  {113792, 113800}, {113808, 113817}, {119808, 119892}, {119894, 119964},
10372
  {119966, 119967}, {119970, 119970}, {119973, 119974}, {119977, 119980},
10373
  {119982, 119993}, {119995, 119995}, {119997, 120003}, {120005, 120069},
10374
  {120071, 120074}, {120077, 120084}, {120086, 120092}, {120094, 120121},
10375
  {120123, 120126}, {120128, 120132}, {120134, 120134}, {120138, 120144},
10376
  {120146, 120485}, {120488, 120512}, {120514, 120538}, {120540, 120570},
10377
  {120572, 120596}, {120598, 120628}, {120630, 120654}, {120656, 120686},
10378
  {120688, 120712}, {120714, 120744}, {120746, 120770}, {120772, 120779},
10379
  {122624, 122633}, {122634, 122634}, {122635, 122654}, {122661, 122666},
10380
  {122928, 122989}, {123136, 123180}, {123191, 123197}, {123214, 123214},
10381
  {123536, 123565}, {123584, 123627}, {124112, 124138}, {124139, 124139},
10382
  {124368, 124397}, {124400, 124400}, {124896, 124902}, {124904, 124907},
10383
  {124909, 124910}, {124912, 124926}, {124928, 125124}, {125184, 125251},
10384
  {125259, 125259}, {126464, 126467}, {126469, 126495}, {126497, 126498},
10385
  {126500, 126500}, {126503, 126503}, {126505, 126514}, {126516, 126519},
10386
  {126521, 126521}, {126523, 126523}, {126530, 126530}, {126535, 126535},
10387
  {126537, 126537}, {126539, 126539}, {126541, 126543}, {126545, 126546},
10388
  {126548, 126548}, {126551, 126551}, {126553, 126553}, {126555, 126555},
10389
  {126557, 126557}, {126559, 126559}, {126561, 126562}, {126564, 126564},
10390
  {126567, 126570}, {126572, 126578}, {126580, 126583}, {126585, 126588},
10391
  {126590, 126590}, {126592, 126601}, {126603, 126619}, {126625, 126627},
10392
  {126629, 126633}, {126635, 126651}, {131072, 173791}, {173824, 177977},
10393
  {177984, 178205}, {178208, 183969}, {183984, 191456}, {191472, 192093},
10394
  {194560, 195101}, {196608, 201546}, {201552, 205743}
10395
};
10396
10397
10398
} // namespace ada::idna
10399
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10400
/* end file src/id_tables.cpp */
10401
10402
namespace ada::idna {
10403
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10404
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10405
0
}
10406
10407
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10408
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10409
0
         (c >= '0' && c <= '9');
10410
0
}
10411
10412
0
bool valid_name_code_point(char32_t code_point, bool first) {
10413
  // https://tc39.es/ecma262/#prod-IdentifierStart
10414
  // Fast paths:
10415
0
  if (first &&
10416
0
      (code_point == '$' || code_point == '_' || is_ascii_letter(code_point))) {
10417
0
    return true;
10418
0
  }
10419
0
  if (!first && (code_point == '$' || is_ascii_letter_or_digit(code_point))) {
10420
0
    return true;
10421
0
  }
10422
  // Slow path...
10423
0
  if (code_point == 0xffffffff) {
10424
0
    return false;  // minimal error handling
10425
0
  }
10426
0
  if (first) {
10427
0
    auto iter = std::lower_bound(
10428
0
        std::begin(ada::idna::id_start), std::end(ada::idna::id_start),
10429
0
        code_point,
10430
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10431
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10432
0
  } else {
10433
0
    auto iter = std::lower_bound(
10434
0
        std::begin(id_continue), std::end(id_continue), code_point,
10435
0
        [](const uint32_t* range, uint32_t cp) { return range[1] < cp; });
10436
0
    return iter != std::end(id_start) && code_point >= (*iter)[0];
10437
0
  }
10438
0
}
10439
}  // namespace ada::idna
10440
/* end file src/identifier.cpp */
10441
/* end file src/idna.cpp */
10442
/* end file src/ada_idna.cpp */
10443
ADA_POP_DISABLE_WARNINGS
10444
10445
#include <algorithm>
10446
#if ADA_NEON
10447
#include <arm_neon.h>
10448
#elif ADA_SSE2
10449
#include <emmintrin.h>
10450
#elif ADA_LSX
10451
#include <lsxintrin.h>
10452
#endif
10453
10454
#include <ranges>
10455
10456
namespace ada::unicode {
10457
10458
0
constexpr bool is_tabs_or_newline(char c) noexcept {
10459
0
  return c == '\r' || c == '\n' || c == '\t';
10460
0
}
10461
10462
0
constexpr uint64_t broadcast(uint8_t v) noexcept {
10463
0
  return 0x101010101010101ull * v;
10464
0
}
10465
10466
0
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10467
0
  uint64_t broadcast_80 = broadcast(0x80);
10468
0
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10469
0
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10470
0
  uint64_t non_ascii = 0;
10471
0
  size_t i = 0;
10472
10473
0
  for (; i + 7 < length; i += 8) {
10474
0
    uint64_t word{};
10475
0
    memcpy(&word, input + i, sizeof(word));
10476
0
    non_ascii |= (word & broadcast_80);
10477
0
    word ^=
10478
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10479
0
    memcpy(input + i, &word, sizeof(word));
10480
0
  }
10481
0
  if (i < length) {
10482
0
    uint64_t word{};
10483
0
    memcpy(&word, input + i, length - i);
10484
0
    non_ascii |= (word & broadcast_80);
10485
0
    word ^=
10486
0
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10487
0
    memcpy(input + i, &word, length - i);
10488
0
  }
10489
0
  return non_ascii == 0;
10490
0
}
10491
#if ADA_NEON
10492
ada_really_inline bool has_tabs_or_newline(
10493
    std::string_view user_input) noexcept {
10494
  // first check for short strings in which case we do it naively.
10495
  if (user_input.size() < 16) {  // slow path
10496
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10497
  }
10498
  // fast path for long strings (expected to be common)
10499
  size_t i = 0;
10500
  /**
10501
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10502
   * on table lookup instruction. We notice that these are all unique numbers
10503
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10504
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10505
   * input register. If the input had `\t` in position X then this shuffled
10506
   * register will also have '\t' in that position. Comparing input with this
10507
   * shuffled register will mark us all interesting characters in the input.
10508
   *
10509
   * credit for algorithmic idea: @aqrit, credit for description:
10510
   * @DenisYaroshevskiy
10511
   */
10512
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10513
                                  0, 9, 10, 0, 0, 13, 0, 0};
10514
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10515
  // m['0xd', '0xa', '0x9']
10516
  uint8x16_t running{0};
10517
  for (; i + 15 < user_input.size(); i += 16) {
10518
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10519
10520
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10521
  }
10522
  if (i < user_input.size()) {
10523
    uint8x16_t word =
10524
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10525
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10526
  }
10527
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10528
}
10529
#elif ADA_SSE2
10530
ada_really_inline bool has_tabs_or_newline(
10531
0
    std::string_view user_input) noexcept {
10532
  // first check for short strings in which case we do it naively.
10533
0
  if (user_input.size() < 16) {  // slow path
10534
0
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10535
0
  }
10536
  // fast path for long strings (expected to be common)
10537
0
  size_t i = 0;
10538
0
  const __m128i mask1 = _mm_set1_epi8('\r');
10539
0
  const __m128i mask2 = _mm_set1_epi8('\n');
10540
0
  const __m128i mask3 = _mm_set1_epi8('\t');
10541
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10542
0
  __m128i running{0};
10543
0
  for (; i + 15 < user_input.size(); i += 16) {
10544
0
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10545
0
    running = _mm_or_si128(
10546
0
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10547
0
                                           _mm_cmpeq_epi8(word, mask2))),
10548
0
        _mm_cmpeq_epi8(word, mask3));
10549
0
  }
10550
0
  if (i < user_input.size()) {
10551
0
    __m128i word = _mm_loadu_si128(
10552
0
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10553
0
    running = _mm_or_si128(
10554
0
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10555
0
                                           _mm_cmpeq_epi8(word, mask2))),
10556
0
        _mm_cmpeq_epi8(word, mask3));
10557
0
  }
10558
0
  return _mm_movemask_epi8(running) != 0;
10559
0
}
10560
#elif ADA_LSX
10561
ada_really_inline bool has_tabs_or_newline(
10562
    std::string_view user_input) noexcept {
10563
  // first check for short strings in which case we do it naively.
10564
  if (user_input.size() < 16) {  // slow path
10565
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10566
  }
10567
  // fast path for long strings (expected to be common)
10568
  size_t i = 0;
10569
  const __m128i mask1 = __lsx_vrepli_b('\r');
10570
  const __m128i mask2 = __lsx_vrepli_b('\n');
10571
  const __m128i mask3 = __lsx_vrepli_b('\t');
10572
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10573
  __m128i running{0};
10574
  for (; i + 15 < user_input.size(); i += 16) {
10575
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10576
    running = __lsx_vor_v(
10577
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10578
                                         __lsx_vseq_b(word, mask2))),
10579
        __lsx_vseq_b(word, mask3));
10580
  }
10581
  if (i < user_input.size()) {
10582
    __m128i word = __lsx_vld(
10583
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10584
    running = __lsx_vor_v(
10585
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10586
                                         __lsx_vseq_b(word, mask2))),
10587
        __lsx_vseq_b(word, mask3));
10588
  }
10589
  if (__lsx_bz_v(running)) return false;
10590
  return true;
10591
}
10592
#else
10593
ada_really_inline bool has_tabs_or_newline(
10594
    std::string_view user_input) noexcept {
10595
  auto has_zero_byte = [](uint64_t v) {
10596
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10597
  };
10598
  size_t i = 0;
10599
  uint64_t mask1 = broadcast('\r');
10600
  uint64_t mask2 = broadcast('\n');
10601
  uint64_t mask3 = broadcast('\t');
10602
  uint64_t running{0};
10603
  for (; i + 7 < user_input.size(); i += 8) {
10604
    uint64_t word{};
10605
    memcpy(&word, user_input.data() + i, sizeof(word));
10606
    uint64_t xor1 = word ^ mask1;
10607
    uint64_t xor2 = word ^ mask2;
10608
    uint64_t xor3 = word ^ mask3;
10609
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10610
  }
10611
  if (i < user_input.size()) {
10612
    uint64_t word{};
10613
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10614
    uint64_t xor1 = word ^ mask1;
10615
    uint64_t xor2 = word ^ mask2;
10616
    uint64_t xor3 = word ^ mask3;
10617
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10618
  }
10619
  return running;
10620
}
10621
#endif
10622
10623
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10624
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10625
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10626
// U+007C (|).
10627
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10628
    []() consteval {
10629
      std::array<uint8_t, 256> result{};
10630
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10631
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10632
        result[c] = true;
10633
      }
10634
      return result;
10635
    }();
10636
10637
ada_really_inline constexpr bool is_forbidden_host_code_point(
10638
0
    const char c) noexcept {
10639
0
  return is_forbidden_host_code_point_table[uint8_t(c)];
10640
0
}
10641
10642
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10643
    []() consteval {
10644
      std::array<uint8_t, 256> result{};
10645
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10646
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10647
        result[c] = true;
10648
      }
10649
      for (uint8_t c = 0; c <= 32; c++) {
10650
        result[c] = true;
10651
      }
10652
      for (size_t c = 127; c < 255; c++) {
10653
        result[c] = true;
10654
      }
10655
      return result;
10656
    }();
10657
10658
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10659
10660
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10661
0
    const char c) noexcept {
10662
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10663
0
}
10664
10665
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10666
0
    const char* input, size_t length) noexcept {
10667
0
  size_t i = 0;
10668
0
  uint8_t accumulator{};
10669
0
  for (; i + 4 <= length; i += 4) {
10670
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10671
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10672
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10673
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10674
0
  }
10675
0
  for (; i < length; i++) {
10676
0
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10677
0
  }
10678
0
  return accumulator;
10679
0
}
10680
10681
constexpr static std::array<uint8_t, 256>
10682
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10683
      std::array<uint8_t, 256> result{};
10684
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10685
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10686
        result[c] = 1;
10687
      }
10688
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10689
        result[c] = 2;
10690
      }
10691
      for (uint8_t c = 0; c <= 32; c++) {
10692
        result[c] = 1;
10693
      }
10694
      for (size_t c = 127; c < 255; c++) {
10695
        result[c] = 1;
10696
      }
10697
      return result;
10698
    }();
10699
10700
ada_really_inline constexpr uint8_t
10701
contains_forbidden_domain_code_point_or_upper(const char* input,
10702
0
                                              size_t length) noexcept {
10703
0
  size_t i = 0;
10704
0
  uint8_t accumulator{};
10705
0
  for (; i + 4 <= length; i += 4) {
10706
0
    accumulator |=
10707
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10708
0
    accumulator |=
10709
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10710
0
    accumulator |=
10711
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10712
0
    accumulator |=
10713
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10714
0
  }
10715
0
  for (; i < length; i++) {
10716
0
    accumulator |=
10717
0
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10718
0
  }
10719
0
  return accumulator;
10720
0
}
10721
10722
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10723
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10724
  std::array<bool, 256> result{};
10725
  for (size_t c = 0; c < 256; c++) {
10726
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10727
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10728
  }
10729
  return result;
10730
}();
10731
10732
0
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10733
0
  return is_alnum_plus_table[uint8_t(c)];
10734
  // A table is almost surely much faster than the
10735
  // following under most compilers: return
10736
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10737
0
}
10738
10739
6.07k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10740
6.07k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10741
6.07k
         (c >= 'a' && c <= 'f');
10742
6.07k
}
10743
10744
0
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10745
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10746
  // inclusive.
10747
0
  return (c >= '0' && c <= '9');
10748
0
}
10749
10750
0
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10751
  // If code point is between U+0000 and U+007F inclusive, then return true.
10752
0
  return c <= 0x7F;
10753
0
}
10754
10755
0
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10756
0
  return (unsigned char)c <= ' ';
10757
0
}
10758
10759
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10760
0
    const char c) noexcept {
10761
0
  return c == '\t' || c == '\n' || c == '\r';
10762
0
}
10763
10764
constexpr std::string_view table_is_double_dot_path_segment[] = {
10765
    "..", "%2e.", ".%2e", "%2e%2e"};
10766
10767
ada_really_inline constexpr bool is_double_dot_path_segment(
10768
0
    std::string_view input) noexcept {
10769
  // This will catch most cases:
10770
  // The length must be 2,4 or 6.
10771
  // We divide by two and require
10772
  // that the result be between 1 and 3 inclusively.
10773
0
  uint64_t half_length = uint64_t(input.size()) / 2;
10774
0
  if (half_length - 1 > 2) {
10775
0
    return false;
10776
0
  }
10777
  // We have a string of length 2, 4 or 6.
10778
  // We now check the first character:
10779
0
  if ((input[0] != '.') && (input[0] != '%')) {
10780
0
    return false;
10781
0
  }
10782
  // We are unlikely the get beyond this point.
10783
0
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10784
0
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10785
0
  if (target.size() != input.size()) {
10786
0
    return false;
10787
0
  }
10788
  // We almost never get here.
10789
  // Optimizing the rest is relatively unimportant.
10790
0
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10791
0
    uint16_t A, B;
10792
0
    memcpy(&A, a.data(), sizeof(A));
10793
0
    memcpy(&B, b.data(), sizeof(B));
10794
0
    return A == B;
10795
0
  };
10796
0
  if (!prefix_equal_unsafe(input, target)) {
10797
0
    return false;
10798
0
  }
10799
0
  for (size_t i = 2; i < input.size(); i++) {
10800
0
    char c = input[i];
10801
0
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10802
0
      return false;
10803
0
    }
10804
0
  }
10805
0
  return true;
10806
  // The above code might be a bit better than the code below. Compilers
10807
  // are not stupid and may use the fact that these strings have length 2,4 and
10808
  // 6 and other tricks.
10809
  // return input == ".." ||
10810
  //  input == ".%2e" || input == ".%2E" ||
10811
  //  input == "%2e." || input == "%2E." ||
10812
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10813
  //  "%2e%2E";
10814
0
}
10815
10816
ada_really_inline constexpr bool is_single_dot_path_segment(
10817
0
    std::string_view input) noexcept {
10818
0
  return input == "." || input == "%2e" || input == "%2E";
10819
0
}
10820
10821
0
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
10822
0
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
10823
0
}
10824
10825
constexpr static char hex_to_binary_table[] = {
10826
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
10827
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
10828
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
10829
2.65k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
10830
2.65k
  return hex_to_binary_table[c - '0'];
10831
2.65k
}
10832
10833
8.31k
std::string percent_decode(const std::string_view input, size_t first_percent) {
10834
  // next line is for safety only, we expect users to avoid calling
10835
  // percent_decode when first_percent is outside the range.
10836
8.31k
  if (first_percent == std::string_view::npos) {
10837
6.23k
    return std::string(input);
10838
6.23k
  }
10839
2.08k
  std::string dest;
10840
2.08k
  dest.reserve(input.length());
10841
2.08k
  dest.append(input.substr(0, first_percent));
10842
2.08k
  const char* pointer = input.data() + first_percent;
10843
2.08k
  const char* end = input.data() + input.size();
10844
  // Optimization opportunity: if the following code gets
10845
  // called often, it can be optimized quite a bit.
10846
17.3k
  while (pointer < end) {
10847
15.2k
    const char ch = pointer[0];
10848
15.2k
    size_t remaining = end - pointer - 1;
10849
15.2k
    if (ch != '%' || remaining < 2 ||
10850
15.2k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
10851
3.62k
            (!is_ascii_hex_digit(pointer[1]) ||
10852
13.9k
             !is_ascii_hex_digit(pointer[2])))) {
10853
13.9k
      dest += ch;
10854
13.9k
      pointer++;
10855
13.9k
    } else {
10856
1.32k
      unsigned a = convert_hex_to_binary(pointer[1]);
10857
1.32k
      unsigned b = convert_hex_to_binary(pointer[2]);
10858
1.32k
      char c = static_cast<char>(a * 16 + b);
10859
1.32k
      dest += c;
10860
1.32k
      pointer += 3;
10861
1.32k
    }
10862
15.2k
  }
10863
2.08k
  return dest;
10864
8.31k
}
10865
10866
std::string percent_encode(const std::string_view input,
10867
2.05k
                           const uint8_t character_set[]) {
10868
6.62k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10869
6.62k
    return character_sets::bit_at(character_set, c);
10870
6.62k
  });
10871
  // Optimization: Don't iterate if percent encode is not required
10872
2.05k
  if (pointer == input.end()) {
10873
961
    return std::string(input);
10874
961
  }
10875
10876
1.09k
  std::string result;
10877
1.09k
  result.reserve(input.length());  // in the worst case, percent encoding might
10878
                                   // produce 3 characters.
10879
1.09k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
10880
10881
53.5k
  for (; pointer != input.end(); pointer++) {
10882
52.4k
    if (character_sets::bit_at(character_set, *pointer)) {
10883
42.0k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10884
42.0k
    } else {
10885
10.4k
      result += *pointer;
10886
10.4k
    }
10887
52.4k
  }
10888
10889
1.09k
  return result;
10890
2.05k
}
10891
10892
template <bool append>
10893
bool percent_encode(const std::string_view input, const uint8_t character_set[],
10894
0
                    std::string& out) {
10895
0
  ada_log("percent_encode ", input, " to output string while ",
10896
0
          append ? "appending" : "overwriting");
10897
0
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
10898
0
    return character_sets::bit_at(character_set, c);
10899
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
10900
0
  ada_log("percent_encode done checking, moved to ",
10901
0
          std::distance(input.begin(), pointer));
10902
10903
  // Optimization: Don't iterate if percent encode is not required
10904
0
  if (pointer == input.end()) {
10905
0
    ada_log("percent_encode encoding not needed.");
10906
0
    return false;
10907
0
  }
10908
0
  if constexpr (!append) {
10909
0
    out.clear();
10910
0
  }
10911
0
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
10912
0
          " bytes");
10913
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10914
0
  out.append(input.data(), std::distance(input.begin(), pointer));
10915
0
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
10916
0
          " bytes");
10917
0
  for (; pointer != input.end(); pointer++) {
10918
0
    if (character_sets::bit_at(character_set, *pointer)) {
10919
0
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10920
0
    } else {
10921
0
      out += *pointer;
10922
0
    }
10923
0
  }
10924
0
  return true;
10925
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> >&)
10926
10927
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
10928
0
              size_t first_percent) {
10929
0
  std::string percent_decoded_buffer;
10930
0
  std::string_view input = plain;
10931
0
  if (first_percent != std::string_view::npos) {
10932
0
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
10933
0
    input = percent_decoded_buffer;
10934
0
  }
10935
  // input is a non-empty UTF-8 string, must be percent decoded
10936
0
  std::string idna_ascii = ada::idna::to_ascii(input);
10937
0
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
10938
0
                                idna_ascii.data(), idna_ascii.size())) {
10939
0
    return false;
10940
0
  }
10941
0
  out = std::move(idna_ascii);
10942
0
  return true;
10943
0
}
10944
10945
std::string percent_encode(const std::string_view input,
10946
0
                           const uint8_t character_set[], size_t index) {
10947
0
  std::string out;
10948
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
10949
0
  out.append(input.data(), index);
10950
0
  auto pointer = input.begin() + index;
10951
0
  for (; pointer != input.end(); pointer++) {
10952
0
    if (character_sets::bit_at(character_set, *pointer)) {
10953
0
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
10954
0
    } else {
10955
0
      out += *pointer;
10956
0
    }
10957
0
  }
10958
0
  return out;
10959
0
}
10960
10961
}  // namespace ada::unicode
10962
/* end file src/unicode.cpp */
10963
/* begin file src/serializers.cpp */
10964
#include <array>
10965
#include <charconv>
10966
#include <string>
10967
10968
namespace ada::serializers {
10969
10970
void find_longest_sequence_of_ipv6_pieces(
10971
    const std::array<uint16_t, 8>& address, size_t& compress,
10972
0
    size_t& compress_length) noexcept {
10973
0
  for (size_t i = 0; i < 8; i++) {
10974
0
    if (address[i] == 0) {
10975
0
      size_t next = i + 1;
10976
0
      while (next != 8 && address[next] == 0) ++next;
10977
0
      const size_t count = next - i;
10978
0
      if (compress_length < count) {
10979
0
        compress_length = count;
10980
0
        compress = i;
10981
0
        if (next == 8) break;
10982
0
        i = next;
10983
0
      }
10984
0
    }
10985
0
  }
10986
0
}
10987
10988
0
std::string ipv6(const std::array<uint16_t, 8>& address) noexcept {
10989
0
  size_t compress_length = 0;  // The length of a long sequence of zeros.
10990
0
  size_t compress = 0;         // The start of a long sequence of zeros.
10991
0
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
10992
10993
0
  if (compress_length <= 1) {
10994
    // Optimization opportunity: Find a faster way then snprintf for imploding
10995
    // and return here.
10996
0
    compress = compress_length = 8;
10997
0
  }
10998
10999
0
  std::string output(4 * 8 + 7 + 2, '\0');
11000
0
  size_t piece_index = 0;
11001
0
  char* point = output.data();
11002
0
  char* point_end = output.data() + output.size();
11003
0
  *point++ = '[';
11004
0
  while (true) {
11005
0
    if (piece_index == compress) {
11006
0
      *point++ = ':';
11007
      // If we skip a value initially, we need to write '::', otherwise
11008
      // a single ':' will do since it follows a previous ':'.
11009
0
      if (piece_index == 0) {
11010
0
        *point++ = ':';
11011
0
      }
11012
0
      piece_index += compress_length;
11013
0
      if (piece_index == 8) {
11014
0
        break;
11015
0
      }
11016
0
    }
11017
0
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11018
0
    piece_index++;
11019
0
    if (piece_index == 8) {
11020
0
      break;
11021
0
    }
11022
0
    *point++ = ':';
11023
0
  }
11024
0
  *point++ = ']';
11025
0
  output.resize(point - output.data());
11026
0
  return output;
11027
0
}
11028
11029
0
std::string ipv4(const uint64_t address) noexcept {
11030
0
  std::string output(15, '\0');
11031
0
  char* point = output.data();
11032
0
  char* point_end = output.data() + output.size();
11033
0
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11034
0
  for (int i = 2; i >= 0; i--) {
11035
0
    *point++ = '.';
11036
0
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11037
0
  }
11038
0
  output.resize(point - output.data());
11039
0
  return output;
11040
0
}
11041
11042
}  // namespace ada::serializers
11043
/* end file src/serializers.cpp */
11044
/* begin file src/implementation.cpp */
11045
11046
#include <string_view>
11047
11048
11049
namespace ada {
11050
11051
template <class result_type>
11052
ada_warn_unused tl::expected<result_type, errors> parse(
11053
0
    std::string_view input, const result_type* base_url) {
11054
0
  result_type u =
11055
0
      ada::parser::parse_url_impl<result_type, true>(input, base_url);
11056
0
  if (!u.is_valid) {
11057
0
    return tl::unexpected(errors::type_error);
11058
0
  }
11059
0
  return u;
11060
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*)
11061
11062
template ada::result<url> parse<url>(std::string_view input,
11063
                                     const url* base_url = nullptr);
11064
template ada::result<url_aggregator> parse<url_aggregator>(
11065
    std::string_view input, const url_aggregator* base_url = nullptr);
11066
11067
0
std::string href_from_file(std::string_view input) {
11068
  // This is going to be much faster than constructing a URL.
11069
0
  std::string tmp_buffer;
11070
0
  std::string_view internal_input;
11071
0
  if (unicode::has_tabs_or_newline(input)) {
11072
0
    tmp_buffer = input;
11073
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11074
0
    internal_input = tmp_buffer;
11075
0
  } else {
11076
0
    internal_input = input;
11077
0
  }
11078
0
  std::string path;
11079
0
  if (internal_input.empty()) {
11080
0
    path = "/";
11081
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11082
0
    helpers::parse_prepared_path(internal_input.substr(1),
11083
0
                                 ada::scheme::type::FILE, path);
11084
0
  } else {
11085
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11086
0
  }
11087
0
  return "file://" + path;
11088
0
}
11089
11090
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
11091
0
  ada::url_aggregator base_aggregator;
11092
0
  ada::url_aggregator* base_pointer = nullptr;
11093
11094
0
  if (base_input != nullptr) {
11095
0
    base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11096
0
        *base_input, nullptr);
11097
0
    if (!base_aggregator.is_valid) {
11098
0
      return false;
11099
0
    }
11100
0
    base_pointer = &base_aggregator;
11101
0
  }
11102
11103
0
  ada::url_aggregator result =
11104
0
      ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11105
0
                                                              base_pointer);
11106
0
  return result.is_valid;
11107
0
}
11108
11109
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11110
0
  switch (type) {
11111
0
    case ada::encoding_type::UTF8:
11112
0
      return "UTF-8";
11113
0
    case ada::encoding_type::UTF_16LE:
11114
0
      return "UTF-16LE";
11115
0
    case ada::encoding_type::UTF_16BE:
11116
0
      return "UTF-16BE";
11117
0
    default:
11118
0
      unreachable();
11119
0
  }
11120
0
}
11121
11122
}  // namespace ada
11123
/* end file src/implementation.cpp */
11124
/* begin file src/helpers.cpp */
11125
11126
#include <cstring>
11127
#include <sstream>
11128
11129
namespace ada::helpers {
11130
11131
template <typename out_iter>
11132
0
void encode_json(std::string_view view, out_iter out) {
11133
  // trivial implementation. could be faster.
11134
0
  const char* hexvalues =
11135
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11136
0
  for (uint8_t c : view) {
11137
0
    if (c == '\\') {
11138
0
      *out++ = '\\';
11139
0
      *out++ = '\\';
11140
0
    } else if (c == '"') {
11141
0
      *out++ = '\\';
11142
0
      *out++ = '"';
11143
0
    } else if (c <= 0x1f) {
11144
0
      *out++ = '\\';
11145
0
      *out++ = 'u';
11146
0
      *out++ = '0';
11147
0
      *out++ = '0';
11148
0
      *out++ = hexvalues[2 * c];
11149
0
      *out++ = hexvalues[2 * c + 1];
11150
0
    } else {
11151
0
      *out++ = c;
11152
0
    }
11153
0
  }
11154
0
}
11155
11156
0
ada_unused std::string get_state(ada::state s) {
11157
0
  switch (s) {
11158
0
    case ada::state::AUTHORITY:
11159
0
      return "Authority";
11160
0
    case ada::state::SCHEME_START:
11161
0
      return "Scheme Start";
11162
0
    case ada::state::SCHEME:
11163
0
      return "Scheme";
11164
0
    case ada::state::HOST:
11165
0
      return "Host";
11166
0
    case ada::state::NO_SCHEME:
11167
0
      return "No Scheme";
11168
0
    case ada::state::FRAGMENT:
11169
0
      return "Fragment";
11170
0
    case ada::state::RELATIVE_SCHEME:
11171
0
      return "Relative Scheme";
11172
0
    case ada::state::RELATIVE_SLASH:
11173
0
      return "Relative Slash";
11174
0
    case ada::state::FILE:
11175
0
      return "File";
11176
0
    case ada::state::FILE_HOST:
11177
0
      return "File Host";
11178
0
    case ada::state::FILE_SLASH:
11179
0
      return "File Slash";
11180
0
    case ada::state::PATH_OR_AUTHORITY:
11181
0
      return "Path or Authority";
11182
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11183
0
      return "Special Authority Ignore Slashes";
11184
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11185
0
      return "Special Authority Slashes";
11186
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11187
0
      return "Special Relative or Authority";
11188
0
    case ada::state::QUERY:
11189
0
      return "Query";
11190
0
    case ada::state::PATH:
11191
0
      return "Path";
11192
0
    case ada::state::PATH_START:
11193
0
      return "Path Start";
11194
0
    case ada::state::OPAQUE_PATH:
11195
0
      return "Opaque Path";
11196
0
    case ada::state::PORT:
11197
0
      return "Port";
11198
0
    default:
11199
0
      return "unknown state";
11200
0
  }
11201
0
}
11202
11203
ada_really_inline std::optional<std::string_view> prune_hash(
11204
0
    std::string_view& input) noexcept {
11205
  // compiles down to 20--30 instructions including a class to memchr (C
11206
  // function). this function should be quite fast.
11207
0
  size_t location_of_first = input.find('#');
11208
0
  if (location_of_first == std::string_view::npos) {
11209
0
    return std::nullopt;
11210
0
  }
11211
0
  std::string_view hash = input;
11212
0
  hash.remove_prefix(location_of_first + 1);
11213
0
  input.remove_suffix(input.size() - location_of_first);
11214
0
  return hash;
11215
0
}
11216
11217
ada_really_inline bool shorten_path(std::string& path,
11218
0
                                    ada::scheme::type type) noexcept {
11219
  // Let path be url's path.
11220
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11221
  // Windows drive letter, then return.
11222
0
  if (type == ada::scheme::type::FILE &&
11223
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11224
0
    if (checkers::is_normalized_windows_drive_letter(
11225
0
            helpers::substring(path, 1))) {
11226
0
      return false;
11227
0
    }
11228
0
  }
11229
11230
  // Remove path's last item, if any.
11231
0
  size_t last_delimiter = path.rfind('/');
11232
0
  if (last_delimiter != std::string::npos) {
11233
0
    path.erase(last_delimiter);
11234
0
    return true;
11235
0
  }
11236
11237
0
  return false;
11238
0
}
11239
11240
ada_really_inline bool shorten_path(std::string_view& path,
11241
0
                                    ada::scheme::type type) noexcept {
11242
  // Let path be url's path.
11243
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11244
  // Windows drive letter, then return.
11245
0
  if (type == ada::scheme::type::FILE &&
11246
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11247
0
    if (checkers::is_normalized_windows_drive_letter(
11248
0
            helpers::substring(path, 1))) {
11249
0
      return false;
11250
0
    }
11251
0
  }
11252
11253
  // Remove path's last item, if any.
11254
0
  if (!path.empty()) {
11255
0
    size_t slash_loc = path.rfind('/');
11256
0
    if (slash_loc != std::string_view::npos) {
11257
0
      path.remove_suffix(path.size() - slash_loc);
11258
0
      return true;
11259
0
    }
11260
0
  }
11261
11262
0
  return false;
11263
0
}
11264
11265
ada_really_inline void remove_ascii_tab_or_newline(
11266
0
    std::string& input) noexcept {
11267
  // if this ever becomes a performance issue, we could use an approach similar
11268
  // to has_tabs_or_newline
11269
0
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11270
0
}
11271
11272
ada_really_inline constexpr std::string_view substring(std::string_view input,
11273
0
                                                       size_t pos) noexcept {
11274
0
  ADA_ASSERT_TRUE(pos <= input.size());
11275
  // The following is safer but unneeded if we have the above line:
11276
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11277
0
  return input.substr(pos);
11278
0
}
11279
11280
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11281
0
  ADA_ASSERT_TRUE(pos <= input.size());
11282
0
  input.remove_suffix(input.size() - pos);
11283
0
}
11284
11285
// computes the number of trailing zeroes
11286
// this is a private inline function only defined in this source file.
11287
0
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11288
#ifdef ADA_REGULAR_VISUAL_STUDIO
11289
  unsigned long ret;
11290
  // Search the mask data from least significant bit (LSB)
11291
  // to the most significant bit (MSB) for a set bit (1).
11292
  _BitScanForward(&ret, input_num);
11293
  return (int)ret;
11294
#else   // ADA_REGULAR_VISUAL_STUDIO
11295
0
  return __builtin_ctzl(input_num);
11296
0
#endif  // ADA_REGULAR_VISUAL_STUDIO
11297
0
}
11298
11299
// starting at index location, this finds the next location of a character
11300
// :, /, \\, ? or [. If none is found, view.size() is returned.
11301
// For use within get_host_delimiter_location.
11302
#if ADA_NEON
11303
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11304
// support direct initialization of uint8x16_t. See
11305
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11306
#ifndef ada_make_uint8x16_t
11307
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11308
                            x13, x14, x15, x16)                                \
11309
  ([=]() {                                                                     \
11310
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11311
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11312
    return vld1q_u8(array);                                                    \
11313
  }())
11314
#endif
11315
11316
ada_really_inline size_t find_next_host_delimiter_special(
11317
    std::string_view view, size_t location) noexcept {
11318
  // first check for short strings in which case we do it naively.
11319
  if (view.size() - location < 16) {  // slow path
11320
    for (size_t i = location; i < view.size(); i++) {
11321
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11322
          view[i] == '?' || view[i] == '[') {
11323
        return i;
11324
      }
11325
    }
11326
    return size_t(view.size());
11327
  }
11328
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11329
    uint8x16_t bit_mask =
11330
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11331
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11332
    uint8x16_t minput = vandq_u8(input, bit_mask);
11333
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11334
    tmp = vpaddq_u8(tmp, tmp);
11335
    tmp = vpaddq_u8(tmp, tmp);
11336
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11337
  };
11338
11339
  // fast path for long strings (expected to be common)
11340
  size_t i = location;
11341
  uint8x16_t low_mask =
11342
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11343
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11344
  uint8x16_t high_mask =
11345
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11346
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11347
  uint8x16_t fmask = vmovq_n_u8(0xf);
11348
  uint8x16_t zero{0};
11349
  for (; i + 15 < view.size(); i += 16) {
11350
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11351
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11352
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11353
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11354
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11355
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11356
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11357
      return i + trailing_zeroes(is_non_zero);
11358
    }
11359
  }
11360
11361
  if (i < view.size()) {
11362
    uint8x16_t word =
11363
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11364
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11365
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11366
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11367
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11368
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11369
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11370
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11371
    }
11372
  }
11373
  return size_t(view.size());
11374
}
11375
#elif ADA_SSE2
11376
ada_really_inline size_t find_next_host_delimiter_special(
11377
0
    std::string_view view, size_t location) noexcept {
11378
  // first check for short strings in which case we do it naively.
11379
0
  if (view.size() - location < 16) {  // slow path
11380
0
    for (size_t i = location; i < view.size(); i++) {
11381
0
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11382
0
          view[i] == '?' || view[i] == '[') {
11383
0
        return i;
11384
0
      }
11385
0
    }
11386
0
    return size_t(view.size());
11387
0
  }
11388
  // fast path for long strings (expected to be common)
11389
0
  size_t i = location;
11390
0
  const __m128i mask1 = _mm_set1_epi8(':');
11391
0
  const __m128i mask2 = _mm_set1_epi8('/');
11392
0
  const __m128i mask3 = _mm_set1_epi8('\\');
11393
0
  const __m128i mask4 = _mm_set1_epi8('?');
11394
0
  const __m128i mask5 = _mm_set1_epi8('[');
11395
11396
0
  for (; i + 15 < view.size(); i += 16) {
11397
0
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11398
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11399
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11400
0
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11401
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11402
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11403
0
    __m128i m = _mm_or_si128(
11404
0
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11405
0
    int mask = _mm_movemask_epi8(m);
11406
0
    if (mask != 0) {
11407
0
      return i + trailing_zeroes(mask);
11408
0
    }
11409
0
  }
11410
0
  if (i < view.size()) {
11411
0
    __m128i word =
11412
0
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11413
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11414
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11415
0
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11416
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11417
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11418
0
    __m128i m = _mm_or_si128(
11419
0
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11420
0
    int mask = _mm_movemask_epi8(m);
11421
0
    if (mask != 0) {
11422
0
      return view.length() - 16 + trailing_zeroes(mask);
11423
0
    }
11424
0
  }
11425
0
  return size_t(view.length());
11426
0
}
11427
#elif ADA_LSX
11428
ada_really_inline size_t find_next_host_delimiter_special(
11429
    std::string_view view, size_t location) noexcept {
11430
  // first check for short strings in which case we do it naively.
11431
  if (view.size() - location < 16) {  // slow path
11432
    for (size_t i = location; i < view.size(); i++) {
11433
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11434
          view[i] == '?' || view[i] == '[') {
11435
        return i;
11436
      }
11437
    }
11438
    return size_t(view.size());
11439
  }
11440
  // fast path for long strings (expected to be common)
11441
  size_t i = location;
11442
  const __m128i mask1 = __lsx_vrepli_b(':');
11443
  const __m128i mask2 = __lsx_vrepli_b('/');
11444
  const __m128i mask3 = __lsx_vrepli_b('\\');
11445
  const __m128i mask4 = __lsx_vrepli_b('?');
11446
  const __m128i mask5 = __lsx_vrepli_b('[');
11447
11448
  for (; i + 15 < view.size(); i += 16) {
11449
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11450
    __m128i m1 = __lsx_vseq_b(word, mask1);
11451
    __m128i m2 = __lsx_vseq_b(word, mask2);
11452
    __m128i m3 = __lsx_vseq_b(word, mask3);
11453
    __m128i m4 = __lsx_vseq_b(word, mask4);
11454
    __m128i m5 = __lsx_vseq_b(word, mask5);
11455
    __m128i m =
11456
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11457
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11458
    if (mask != 0) {
11459
      return i + trailing_zeroes(mask);
11460
    }
11461
  }
11462
  if (i < view.size()) {
11463
    __m128i word =
11464
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11465
    __m128i m1 = __lsx_vseq_b(word, mask1);
11466
    __m128i m2 = __lsx_vseq_b(word, mask2);
11467
    __m128i m3 = __lsx_vseq_b(word, mask3);
11468
    __m128i m4 = __lsx_vseq_b(word, mask4);
11469
    __m128i m5 = __lsx_vseq_b(word, mask5);
11470
    __m128i m =
11471
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11472
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11473
    if (mask != 0) {
11474
      return view.length() - 16 + trailing_zeroes(mask);
11475
    }
11476
  }
11477
  return size_t(view.length());
11478
}
11479
#else
11480
// : / [ \\ ?
11481
static constexpr std::array<uint8_t, 256> special_host_delimiters =
11482
    []() consteval {
11483
      std::array<uint8_t, 256> result{};
11484
      for (int i : {':', '/', '[', '\\', '?'}) {
11485
        result[i] = 1;
11486
      }
11487
      return result;
11488
    }();
11489
// credit: @the-moisrex recommended a table-based approach
11490
ada_really_inline size_t find_next_host_delimiter_special(
11491
    std::string_view view, size_t location) noexcept {
11492
  auto const str = view.substr(location);
11493
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11494
    if (special_host_delimiters[(uint8_t)*pos]) {
11495
      return pos - str.begin() + location;
11496
    }
11497
  }
11498
  return size_t(view.size());
11499
}
11500
#endif
11501
11502
// starting at index location, this finds the next location of a character
11503
// :, /, ? or [. If none is found, view.size() is returned.
11504
// For use within get_host_delimiter_location.
11505
#if ADA_NEON
11506
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11507
                                                  size_t location) noexcept {
11508
  // first check for short strings in which case we do it naively.
11509
  if (view.size() - location < 16) {  // slow path
11510
    for (size_t i = location; i < view.size(); i++) {
11511
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11512
          view[i] == '[') {
11513
        return i;
11514
      }
11515
    }
11516
    return size_t(view.size());
11517
  }
11518
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11519
    uint8x16_t bit_mask =
11520
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11521
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11522
    uint8x16_t minput = vandq_u8(input, bit_mask);
11523
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11524
    tmp = vpaddq_u8(tmp, tmp);
11525
    tmp = vpaddq_u8(tmp, tmp);
11526
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11527
  };
11528
11529
  // fast path for long strings (expected to be common)
11530
  size_t i = location;
11531
  uint8x16_t low_mask =
11532
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11533
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
11534
  uint8x16_t high_mask =
11535
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11536
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11537
  uint8x16_t fmask = vmovq_n_u8(0xf);
11538
  uint8x16_t zero{0};
11539
  for (; i + 15 < view.size(); i += 16) {
11540
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11541
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11542
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11543
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11544
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11545
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11546
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11547
      return i + trailing_zeroes(is_non_zero);
11548
    }
11549
  }
11550
11551
  if (i < view.size()) {
11552
    uint8x16_t word =
11553
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11554
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11555
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11556
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11557
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11558
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11559
      uint16_t is_non_zero = ~to_bitmask(is_zero);
11560
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11561
    }
11562
  }
11563
  return size_t(view.size());
11564
}
11565
#elif ADA_SSE2
11566
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11567
0
                                                  size_t location) noexcept {
11568
  // first check for short strings in which case we do it naively.
11569
0
  if (view.size() - location < 16) {  // slow path
11570
0
    for (size_t i = location; i < view.size(); i++) {
11571
0
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11572
0
          view[i] == '[') {
11573
0
        return i;
11574
0
      }
11575
0
    }
11576
0
    return size_t(view.size());
11577
0
  }
11578
  // fast path for long strings (expected to be common)
11579
0
  size_t i = location;
11580
0
  const __m128i mask1 = _mm_set1_epi8(':');
11581
0
  const __m128i mask2 = _mm_set1_epi8('/');
11582
0
  const __m128i mask4 = _mm_set1_epi8('?');
11583
0
  const __m128i mask5 = _mm_set1_epi8('[');
11584
11585
0
  for (; i + 15 < view.size(); i += 16) {
11586
0
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11587
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11588
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11589
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11590
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11591
0
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11592
0
    int mask = _mm_movemask_epi8(m);
11593
0
    if (mask != 0) {
11594
0
      return i + trailing_zeroes(mask);
11595
0
    }
11596
0
  }
11597
0
  if (i < view.size()) {
11598
0
    __m128i word =
11599
0
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11600
0
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11601
0
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11602
0
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11603
0
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11604
0
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
11605
0
    int mask = _mm_movemask_epi8(m);
11606
0
    if (mask != 0) {
11607
0
      return view.length() - 16 + trailing_zeroes(mask);
11608
0
    }
11609
0
  }
11610
0
  return size_t(view.length());
11611
0
}
11612
#elif ADA_LSX
11613
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11614
                                                  size_t location) noexcept {
11615
  // first check for short strings in which case we do it naively.
11616
  if (view.size() - location < 16) {  // slow path
11617
    for (size_t i = location; i < view.size(); i++) {
11618
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
11619
          view[i] == '[') {
11620
        return i;
11621
      }
11622
    }
11623
    return size_t(view.size());
11624
  }
11625
  // fast path for long strings (expected to be common)
11626
  size_t i = location;
11627
  const __m128i mask1 = __lsx_vrepli_b(':');
11628
  const __m128i mask2 = __lsx_vrepli_b('/');
11629
  const __m128i mask4 = __lsx_vrepli_b('?');
11630
  const __m128i mask5 = __lsx_vrepli_b('[');
11631
11632
  for (; i + 15 < view.size(); i += 16) {
11633
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11634
    __m128i m1 = __lsx_vseq_b(word, mask1);
11635
    __m128i m2 = __lsx_vseq_b(word, mask2);
11636
    __m128i m4 = __lsx_vseq_b(word, mask4);
11637
    __m128i m5 = __lsx_vseq_b(word, mask5);
11638
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11639
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11640
    if (mask != 0) {
11641
      return i + trailing_zeroes(mask);
11642
    }
11643
  }
11644
  if (i < view.size()) {
11645
    __m128i word =
11646
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11647
    __m128i m1 = __lsx_vseq_b(word, mask1);
11648
    __m128i m2 = __lsx_vseq_b(word, mask2);
11649
    __m128i m4 = __lsx_vseq_b(word, mask4);
11650
    __m128i m5 = __lsx_vseq_b(word, mask5);
11651
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
11652
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11653
    if (mask != 0) {
11654
      return view.length() - 16 + trailing_zeroes(mask);
11655
    }
11656
  }
11657
  return size_t(view.length());
11658
}
11659
#else
11660
// : / [ ?
11661
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
11662
  std::array<uint8_t, 256> result{};
11663
  for (int i : {':', '/', '?', '['}) {
11664
    result[i] = 1;
11665
  }
11666
  return result;
11667
}();
11668
// credit: @the-moisrex recommended a table-based approach
11669
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
11670
                                                  size_t location) noexcept {
11671
  auto const str = view.substr(location);
11672
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
11673
    if (host_delimiters[(uint8_t)*pos]) {
11674
      return pos - str.begin() + location;
11675
    }
11676
  }
11677
  return size_t(view.size());
11678
}
11679
#endif
11680
11681
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
11682
0
    const bool is_special, std::string_view& view) noexcept {
11683
  /**
11684
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
11685
   * compute a variable called insideBrackets but this variable is only used
11686
   * once, to check whether a ':' character was found outside brackets. Exact
11687
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
11688
   * It is conceptually simpler and arguably more efficient to just return a
11689
   * Boolean indicating whether ':' was found outside brackets.
11690
   */
11691
0
  const size_t view_size = view.size();
11692
0
  size_t location = 0;
11693
0
  bool found_colon = false;
11694
  /**
11695
   * Performance analysis:
11696
   *
11697
   * We are basically seeking the end of the hostname which can be indicated
11698
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
11699
   * (where '\\' is only applicable for special URLs). However, these must
11700
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
11701
   * '?' does not count.
11702
   *
11703
   * So we can skip ahead to the next delimiter, as long as we include '[' in
11704
   * the set of delimiters, and that we handle it first.
11705
   *
11706
   * So the trick is to have a fast function that locates the next delimiter.
11707
   * Unless we find '[', then it only needs to be called once! Ideally, such a
11708
   * function would be provided by the C++ standard library, but it seems that
11709
   * find_first_of is not very fast, so we are forced to roll our own.
11710
   *
11711
   * We do not break into two loops for speed, but for clarity.
11712
   */
11713
0
  if (is_special) {
11714
    // We move to the next delimiter.
11715
0
    location = find_next_host_delimiter_special(view, location);
11716
    // Unless we find '[' then we are going only going to have to call
11717
    // find_next_host_delimiter_special once.
11718
0
    for (; location < view_size;
11719
0
         location = find_next_host_delimiter_special(view, location)) {
11720
0
      if (view[location] == '[') {
11721
0
        location = view.find(']', location);
11722
0
        if (location == std::string_view::npos) {
11723
          // performance: view.find might get translated to a memchr, which
11724
          // has no notion of std::string_view::npos, so the code does not
11725
          // reflect the assembly.
11726
0
          location = view_size;
11727
0
          break;
11728
0
        }
11729
0
      } else {
11730
0
        found_colon = view[location] == ':';
11731
0
        break;
11732
0
      }
11733
0
    }
11734
0
  } else {
11735
    // We move to the next delimiter.
11736
0
    location = find_next_host_delimiter(view, location);
11737
    // Unless we find '[' then we are going only going to have to call
11738
    // find_next_host_delimiter_special once.
11739
0
    for (; location < view_size;
11740
0
         location = find_next_host_delimiter(view, location)) {
11741
0
      if (view[location] == '[') {
11742
0
        location = view.find(']', location);
11743
0
        if (location == std::string_view::npos) {
11744
          // performance: view.find might get translated to a memchr, which
11745
          // has no notion of std::string_view::npos, so the code does not
11746
          // reflect the assembly.
11747
0
          location = view_size;
11748
0
          break;
11749
0
        }
11750
0
      } else {
11751
0
        found_colon = view[location] == ':';
11752
0
        break;
11753
0
      }
11754
0
    }
11755
0
  }
11756
  // performance: remove_suffix may translate into a single instruction.
11757
0
  view.remove_suffix(view_size - location);
11758
0
  return {location, found_colon};
11759
0
}
11760
11761
0
void trim_c0_whitespace(std::string_view& input) noexcept {
11762
0
  while (!input.empty() &&
11763
0
         ada::unicode::is_c0_control_or_space(input.front())) {
11764
0
    input.remove_prefix(1);
11765
0
  }
11766
0
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
11767
0
    input.remove_suffix(1);
11768
0
  }
11769
0
}
11770
11771
ada_really_inline void parse_prepared_path(std::string_view input,
11772
                                           ada::scheme::type type,
11773
0
                                           std::string& path) {
11774
0
  ada_log("parse_prepared_path ", input);
11775
0
  uint8_t accumulator = checkers::path_signature(input);
11776
  // Let us first detect a trivial case.
11777
  // If it is special, we check that we have no dot, no %,  no \ and no
11778
  // character needing percent encoding. Otherwise, we check that we have no %,
11779
  // no dot, and no character needing percent encoding.
11780
0
  constexpr uint8_t need_encoding = 1;
11781
0
  constexpr uint8_t backslash_char = 2;
11782
0
  constexpr uint8_t dot_char = 4;
11783
0
  constexpr uint8_t percent_char = 8;
11784
0
  bool special = type != ada::scheme::NOT_SPECIAL;
11785
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
11786
0
                                      checkers::is_windows_drive_letter(input));
11787
0
  bool trivial_path =
11788
0
      (special ? (accumulator == 0)
11789
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
11790
0
                  0)) &&
11791
0
      (!may_need_slow_file_handling);
11792
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
11793
    // '4' means that we have at least one dot, but nothing that requires
11794
    // percent encoding or decoding. The only part that is not trivial is
11795
    // that we may have single dots and double dots path segments.
11796
    // If we have such segments, then we either have a path that begins
11797
    // with '.' (easy to check), or we have the sequence './'.
11798
    // Note: input cannot be empty, it must at least contain one character ('.')
11799
    // Note: we know that '\' is not present.
11800
0
    if (input[0] != '.') {
11801
0
      size_t slashdot = 0;
11802
0
      bool dot_is_file = true;
11803
0
      for (;;) {
11804
0
        slashdot = input.find("/.", slashdot);
11805
0
        if (slashdot == std::string_view::npos) {  // common case
11806
0
          break;
11807
0
        } else {  // uncommon
11808
          // only three cases matter: /./, /.. or a final /
11809
0
          slashdot += 2;
11810
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
11811
0
                           input[slashdot] == '/');
11812
0
        }
11813
0
      }
11814
0
      trivial_path = dot_is_file;
11815
0
    }
11816
0
  }
11817
0
  if (trivial_path) {
11818
0
    ada_log("parse_path trivial");
11819
0
    path += '/';
11820
0
    path += input;
11821
0
    return;
11822
0
  }
11823
  // We are going to need to look a bit at the path, but let us see if we can
11824
  // ignore percent encoding *and* backslashes *and* percent characters.
11825
  // Except for the trivial case, this is likely to capture 99% of paths out
11826
  // there.
11827
0
  bool fast_path =
11828
0
      (special &&
11829
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
11830
0
      (type != ada::scheme::type::FILE);
11831
0
  if (fast_path) {
11832
0
    ada_log("parse_prepared_path fast");
11833
    // Here we don't need to worry about \ or percent encoding.
11834
    // We also do not have a file protocol. We might have dots, however,
11835
    // but dots must as appear as '.', and they cannot be encoded because
11836
    // the symbol '%' is not present.
11837
0
    size_t previous_location = 0;  // We start at 0.
11838
0
    do {
11839
0
      size_t new_location = input.find('/', previous_location);
11840
      // std::string_view path_view = input;
11841
      //  We process the last segment separately:
11842
0
      if (new_location == std::string_view::npos) {
11843
0
        std::string_view path_view = input.substr(previous_location);
11844
0
        if (path_view == "..") {  // The path ends with ..
11845
          // e.g., if you receive ".." with an empty path, you go to "/".
11846
0
          if (path.empty()) {
11847
0
            path = '/';
11848
0
            return;
11849
0
          }
11850
          // Fast case where we have nothing to do:
11851
0
          if (path.back() == '/') {
11852
0
            return;
11853
0
          }
11854
          // If you have the path "/joe/myfriend",
11855
          // then you delete 'myfriend'.
11856
0
          path.resize(path.rfind('/') + 1);
11857
0
          return;
11858
0
        }
11859
0
        path += '/';
11860
0
        if (path_view != ".") {
11861
0
          path.append(path_view);
11862
0
        }
11863
0
        return;
11864
0
      } else {
11865
        // This is a non-final segment.
11866
0
        std::string_view path_view =
11867
0
            input.substr(previous_location, new_location - previous_location);
11868
0
        previous_location = new_location + 1;
11869
0
        if (path_view == "..") {
11870
0
          size_t last_delimiter = path.rfind('/');
11871
0
          if (last_delimiter != std::string::npos) {
11872
0
            path.erase(last_delimiter);
11873
0
          }
11874
0
        } else if (path_view != ".") {
11875
0
          path += '/';
11876
0
          path.append(path_view);
11877
0
        }
11878
0
      }
11879
0
    } while (true);
11880
0
  } else {
11881
0
    ada_log("parse_path slow");
11882
    // we have reached the general case
11883
0
    bool needs_percent_encoding = (accumulator & 1);
11884
0
    std::string path_buffer_tmp;
11885
0
    do {
11886
0
      size_t location = (special && (accumulator & 2))
11887
0
                            ? input.find_first_of("/\\")
11888
0
                            : input.find('/');
11889
0
      std::string_view path_view = input;
11890
0
      if (location != std::string_view::npos) {
11891
0
        path_view.remove_suffix(path_view.size() - location);
11892
0
        input.remove_prefix(location + 1);
11893
0
      }
11894
      // path_buffer is either path_view or it might point at a percent encoded
11895
      // temporary file.
11896
0
      std::string_view path_buffer =
11897
0
          (needs_percent_encoding &&
11898
0
           ada::unicode::percent_encode<false>(
11899
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
11900
0
              ? path_buffer_tmp
11901
0
              : path_view;
11902
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
11903
0
        helpers::shorten_path(path, type);
11904
0
        if (location == std::string_view::npos) {
11905
0
          path += '/';
11906
0
        }
11907
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
11908
0
                 (location == std::string_view::npos)) {
11909
0
        path += '/';
11910
0
      }
11911
      // Otherwise, if path_buffer is not a single-dot path segment, then:
11912
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
11913
        // If url's scheme is "file", url's path is empty, and path_buffer is a
11914
        // Windows drive letter, then replace the second code point in
11915
        // path_buffer with U+003A (:).
11916
0
        if (type == ada::scheme::type::FILE && path.empty() &&
11917
0
            checkers::is_windows_drive_letter(path_buffer)) {
11918
0
          path += '/';
11919
0
          path += path_buffer[0];
11920
0
          path += ':';
11921
0
          path_buffer.remove_prefix(2);
11922
0
          path.append(path_buffer);
11923
0
        } else {
11924
          // Append path_buffer to url's path.
11925
0
          path += '/';
11926
0
          path.append(path_buffer);
11927
0
        }
11928
0
      }
11929
0
      if (location == std::string_view::npos) {
11930
0
        return;
11931
0
      }
11932
0
    } while (true);
11933
0
  }
11934
0
}
11935
11936
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
11937
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
11938
0
          input1.size(), " bytes] is part of string '", input2, "' [",
11939
0
          input2.size(), " bytes]");
11940
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
11941
0
         input1.data() < input2.data() + input2.size();
11942
0
}
11943
11944
template <class url_type>
11945
ada_really_inline void strip_trailing_spaces_from_opaque_path(
11946
0
    url_type& url) noexcept {
11947
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
11948
0
  if (!url.has_opaque_path) return;
11949
0
  if (url.has_hash()) return;
11950
0
  if (url.has_search()) return;
11951
11952
0
  auto path = std::string(url.get_pathname());
11953
0
  while (!path.empty() && path.back() == ' ') {
11954
0
    path.resize(path.size() - 1);
11955
0
  }
11956
0
  url.update_base_pathname(path);
11957
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&)
11958
11959
// @ / \\ ?
11960
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
11961
    []() consteval {
11962
      std::array<uint8_t, 256> result{};
11963
      for (uint8_t i : {'@', '/', '\\', '?'}) {
11964
        result[i] = 1;
11965
      }
11966
      return result;
11967
    }();
11968
// credit: @the-moisrex recommended a table-based approach
11969
ada_really_inline size_t
11970
0
find_authority_delimiter_special(std::string_view view) noexcept {
11971
  // performance note: we might be able to gain further performance
11972
  // with SIMD instrinsics.
11973
0
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
11974
0
    if (authority_delimiter_special[(uint8_t)*pos]) {
11975
0
      return pos - view.begin();
11976
0
    }
11977
0
  }
11978
0
  return size_t(view.size());
11979
0
}
11980
11981
// @ / ?
11982
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
11983
  std::array<uint8_t, 256> result{};
11984
  for (uint8_t i : {'@', '/', '?'}) {
11985
    result[i] = 1;
11986
  }
11987
  return result;
11988
}();
11989
// credit: @the-moisrex recommended a table-based approach
11990
ada_really_inline size_t
11991
0
find_authority_delimiter(std::string_view view) noexcept {
11992
  // performance note: we might be able to gain further performance
11993
  // with SIMD instrinsics.
11994
0
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
11995
0
    if (authority_delimiter[(uint8_t)*pos]) {
11996
0
      return pos - view.begin();
11997
0
    }
11998
0
  }
11999
0
  return size_t(view.size());
12000
0
}
12001
12002
}  // namespace ada::helpers
12003
12004
namespace ada {
12005
0
ada_warn_unused std::string to_string(ada::state state) {
12006
0
  return ada::helpers::get_state(state);
12007
0
}
12008
#undef ada_make_uint8x16_t
12009
}  // namespace ada
12010
/* end file src/helpers.cpp */
12011
/* begin file src/url.cpp */
12012
12013
#include <numeric>
12014
#include <algorithm>
12015
#include <iterator>
12016
#include <ranges>
12017
#include <string>
12018
#include <string_view>
12019
12020
namespace ada {
12021
12022
0
bool url::parse_opaque_host(std::string_view input) {
12023
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12024
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12025
0
    return is_valid = false;
12026
0
  }
12027
12028
  // Return the result of running UTF-8 percent-encode on input using the C0
12029
  // control percent-encode set.
12030
0
  host = ada::unicode::percent_encode(
12031
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12032
0
  return true;
12033
0
}
12034
12035
0
bool url::parse_ipv4(std::string_view input) {
12036
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12037
0
  if (input.back() == '.') {
12038
0
    input.remove_suffix(1);
12039
0
  }
12040
0
  size_t digit_count{0};
12041
0
  int pure_decimal_count = 0;  // entries that are decimal
12042
0
  std::string_view original_input =
12043
0
      input;  // we might use this if pure_decimal_count == 4.
12044
0
  uint64_t ipv4{0};
12045
  // we could unroll for better performance?
12046
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12047
0
    uint32_t
12048
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12049
0
    bool is_hex = checkers::has_hex_prefix(input);
12050
0
    if (is_hex && ((input.length() == 2) ||
12051
0
                   ((input.length() > 2) && (input[2] == '.')))) {
12052
      // special case
12053
0
      segment_result = 0;
12054
0
      input.remove_prefix(2);
12055
0
    } else {
12056
0
      std::from_chars_result r{};
12057
0
      if (is_hex) {
12058
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12059
0
                            segment_result, 16);
12060
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
12061
0
                 checkers::is_digit(input[1])) {
12062
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12063
0
                            segment_result, 8);
12064
0
      } else {
12065
0
        pure_decimal_count++;
12066
0
        r = std::from_chars(input.data(), input.data() + input.size(),
12067
0
                            segment_result, 10);
12068
0
      }
12069
0
      if (r.ec != std::errc()) {
12070
0
        return is_valid = false;
12071
0
      }
12072
0
      input.remove_prefix(r.ptr - input.data());
12073
0
    }
12074
0
    if (input.empty()) {
12075
      // We have the last value.
12076
      // At this stage, ipv4 contains digit_count*8 bits.
12077
      // So we have 32-digit_count*8 bits left.
12078
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12079
0
        return is_valid = false;
12080
0
      }
12081
0
      ipv4 <<= (32 - digit_count * 8);
12082
0
      ipv4 |= segment_result;
12083
0
      goto final;
12084
0
    } else {
12085
      // There is more, so that the value must no be larger than 255
12086
      // and we must have a '.'.
12087
0
      if ((segment_result > 255) || (input[0] != '.')) {
12088
0
        return is_valid = false;
12089
0
      }
12090
0
      ipv4 <<= 8;
12091
0
      ipv4 |= segment_result;
12092
0
      input.remove_prefix(1);  // remove '.'
12093
0
    }
12094
0
  }
12095
0
  if ((digit_count != 4) || (!input.empty())) {
12096
0
    return is_valid = false;
12097
0
  }
12098
0
final:
12099
  // We could also check r.ptr to see where the parsing ended.
12100
0
  if (pure_decimal_count == 4) {
12101
0
    host = original_input;  // The original input was already all decimal and we
12102
                            // validated it.
12103
0
  } else {
12104
0
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12105
0
  }
12106
0
  host_type = IPV4;
12107
0
  return true;
12108
0
}
12109
12110
0
bool url::parse_ipv6(std::string_view input) {
12111
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12112
12113
0
  if (input.empty()) {
12114
0
    return is_valid = false;
12115
0
  }
12116
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12117
0
  std::array<uint16_t, 8> address{};
12118
12119
  // Let pieceIndex be 0.
12120
0
  int piece_index = 0;
12121
12122
  // Let compress be null.
12123
0
  std::optional<int> compress{};
12124
12125
  // Let pointer be a pointer for input.
12126
0
  std::string_view::iterator pointer = input.begin();
12127
12128
  // If c is U+003A (:), then:
12129
0
  if (input[0] == ':') {
12130
    // If remaining does not start with U+003A (:), validation error, return
12131
    // failure.
12132
0
    if (input.size() == 1 || input[1] != ':') {
12133
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12134
0
      return is_valid = false;
12135
0
    }
12136
12137
    // Increase pointer by 2.
12138
0
    pointer += 2;
12139
12140
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12141
0
    compress = ++piece_index;
12142
0
  }
12143
12144
  // While c is not the EOF code point:
12145
0
  while (pointer != input.end()) {
12146
    // If pieceIndex is 8, validation error, return failure.
12147
0
    if (piece_index == 8) {
12148
0
      ada_log("parse_ipv6 piece_index == 8");
12149
0
      return is_valid = false;
12150
0
    }
12151
12152
    // If c is U+003A (:), then:
12153
0
    if (*pointer == ':') {
12154
      // If compress is non-null, validation error, return failure.
12155
0
      if (compress.has_value()) {
12156
0
        ada_log("parse_ipv6 compress is non-null");
12157
0
        return is_valid = false;
12158
0
      }
12159
12160
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12161
      // then continue.
12162
0
      pointer++;
12163
0
      compress = ++piece_index;
12164
0
      continue;
12165
0
    }
12166
12167
    // Let value and length be 0.
12168
0
    uint16_t value = 0, length = 0;
12169
12170
    // While length is less than 4 and c is an ASCII hex digit,
12171
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12172
    // increase pointer and length by 1.
12173
0
    while (length < 4 && pointer != input.end() &&
12174
0
           unicode::is_ascii_hex_digit(*pointer)) {
12175
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12176
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12177
0
      pointer++;
12178
0
      length++;
12179
0
    }
12180
12181
    // If c is U+002E (.), then:
12182
0
    if (pointer != input.end() && *pointer == '.') {
12183
      // If length is 0, validation error, return failure.
12184
0
      if (length == 0) {
12185
0
        ada_log("parse_ipv6 length is 0");
12186
0
        return is_valid = false;
12187
0
      }
12188
12189
      // Decrease pointer by length.
12190
0
      pointer -= length;
12191
12192
      // If pieceIndex is greater than 6, validation error, return failure.
12193
0
      if (piece_index > 6) {
12194
0
        ada_log("parse_ipv6 piece_index > 6");
12195
0
        return is_valid = false;
12196
0
      }
12197
12198
      // Let numbersSeen be 0.
12199
0
      int numbers_seen = 0;
12200
12201
      // While c is not the EOF code point:
12202
0
      while (pointer != input.end()) {
12203
        // Let ipv4Piece be null.
12204
0
        std::optional<uint16_t> ipv4_piece{};
12205
12206
        // If numbersSeen is greater than 0, then:
12207
0
        if (numbers_seen > 0) {
12208
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12209
          // pointer by 1.
12210
0
          if (*pointer == '.' && numbers_seen < 4) {
12211
0
            pointer++;
12212
0
          }
12213
          // Otherwise, validation error, return failure.
12214
0
          else {
12215
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12216
0
            return is_valid = false;
12217
0
          }
12218
0
        }
12219
12220
        // If c is not an ASCII digit, validation error, return failure.
12221
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12222
0
          ada_log(
12223
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12224
0
              "failure");
12225
0
          return is_valid = false;
12226
0
        }
12227
12228
        // While c is an ASCII digit:
12229
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12230
          // Let number be c interpreted as decimal number.
12231
0
          int number = *pointer - '0';
12232
12233
          // If ipv4Piece is null, then set ipv4Piece to number.
12234
0
          if (!ipv4_piece.has_value()) {
12235
0
            ipv4_piece = number;
12236
0
          }
12237
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12238
0
          else if (ipv4_piece == 0) {
12239
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12240
0
            return is_valid = false;
12241
0
          }
12242
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12243
0
          else {
12244
0
            ipv4_piece = *ipv4_piece * 10 + number;
12245
0
          }
12246
12247
          // If ipv4Piece is greater than 255, validation error, return failure.
12248
0
          if (ipv4_piece > 255) {
12249
0
            ada_log("parse_ipv6 ipv4_piece > 255");
12250
0
            return is_valid = false;
12251
0
          }
12252
12253
          // Increase pointer by 1.
12254
0
          pointer++;
12255
0
        }
12256
12257
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12258
        // ipv4Piece.
12259
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12260
0
        address[piece_index] =
12261
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12262
12263
        // Increase numbersSeen by 1.
12264
0
        numbers_seen++;
12265
12266
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12267
0
        if (numbers_seen == 2 || numbers_seen == 4) {
12268
0
          piece_index++;
12269
0
        }
12270
0
      }
12271
12272
      // If numbersSeen is not 4, validation error, return failure.
12273
0
      if (numbers_seen != 4) {
12274
0
        return is_valid = false;
12275
0
      }
12276
12277
      // Break.
12278
0
      break;
12279
0
    }
12280
    // Otherwise, if c is U+003A (:):
12281
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
12282
      // Increase pointer by 1.
12283
0
      pointer++;
12284
12285
      // If c is the EOF code point, validation error, return failure.
12286
0
      if (pointer == input.end()) {
12287
0
        ada_log(
12288
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
12289
0
            "failure");
12290
0
        return is_valid = false;
12291
0
      }
12292
0
    }
12293
    // Otherwise, if c is not the EOF code point, validation error, return
12294
    // failure.
12295
0
    else if (pointer != input.end()) {
12296
0
      ada_log(
12297
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12298
0
          "error, return failure");
12299
0
      return is_valid = false;
12300
0
    }
12301
12302
    // Set address[pieceIndex] to value.
12303
0
    address[piece_index] = value;
12304
12305
    // Increase pieceIndex by 1.
12306
0
    piece_index++;
12307
0
  }
12308
12309
  // If compress is non-null, then:
12310
0
  if (compress.has_value()) {
12311
    // Let swaps be pieceIndex - compress.
12312
0
    int swaps = piece_index - *compress;
12313
12314
    // Set pieceIndex to 7.
12315
0
    piece_index = 7;
12316
12317
    // While pieceIndex is not 0 and swaps is greater than 0,
12318
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12319
    // decrease both pieceIndex and swaps by 1.
12320
0
    while (piece_index != 0 && swaps > 0) {
12321
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12322
0
      piece_index--;
12323
0
      swaps--;
12324
0
    }
12325
0
  }
12326
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12327
  // return failure.
12328
0
  else if (piece_index != 8) {
12329
0
    ada_log(
12330
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12331
0
        "error, return failure");
12332
0
    return is_valid = false;
12333
0
  }
12334
0
  host = ada::serializers::ipv6(address);
12335
0
  ada_log("parse_ipv6 ", *host);
12336
0
  host_type = IPV6;
12337
0
  return true;
12338
0
}
12339
12340
template <bool has_state_override>
12341
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12342
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
12343
0
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12344
  /**
12345
   * In the common case, we will immediately recognize a special scheme (e.g.,
12346
   *http, https), in which case, we can go really fast.
12347
   **/
12348
0
  if (is_input_special) {  // fast path!!!
12349
0
    if constexpr (has_state_override) {
12350
      // If url's scheme is not a special scheme and buffer is a special scheme,
12351
      // then return.
12352
0
      if (is_special() != is_input_special) {
12353
0
        return false;
12354
0
      }
12355
12356
      // If url includes credentials or has a non-null port, and buffer is
12357
      // "file", then return.
12358
0
      if ((has_credentials() || port.has_value()) &&
12359
0
          parsed_type == ada::scheme::type::FILE) {
12360
0
        return false;
12361
0
      }
12362
12363
      // If url's scheme is "file" and its host is an empty host, then return.
12364
      // An empty host is the empty string.
12365
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12366
0
          host.value().empty()) {
12367
0
        return false;
12368
0
      }
12369
0
    }
12370
12371
0
    type = parsed_type;
12372
12373
0
    if constexpr (has_state_override) {
12374
      // This is uncommon.
12375
0
      uint16_t urls_scheme_port = get_special_port();
12376
12377
0
      if (urls_scheme_port) {
12378
        // If url's port is url's scheme's default port, then set url's port to
12379
        // null.
12380
0
        if (port.has_value() && *port == urls_scheme_port) {
12381
0
          port = std::nullopt;
12382
0
        }
12383
0
      }
12384
0
    }
12385
0
  } else {  // slow path
12386
0
    std::string _buffer(input);
12387
    // Next function is only valid if the input is ASCII and returns false
12388
    // otherwise, but it seems that we always have ascii content so we do not
12389
    // need to check the return value.
12390
    // bool is_ascii =
12391
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
12392
12393
0
    if constexpr (has_state_override) {
12394
      // If url's scheme is a special scheme and buffer is not a special scheme,
12395
      // then return. If url's scheme is not a special scheme and buffer is a
12396
      // special scheme, then return.
12397
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
12398
0
        return true;
12399
0
      }
12400
12401
      // If url includes credentials or has a non-null port, and buffer is
12402
      // "file", then return.
12403
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
12404
0
        return true;
12405
0
      }
12406
12407
      // If url's scheme is "file" and its host is an empty host, then return.
12408
      // An empty host is the empty string.
12409
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
12410
0
          host.value().empty()) {
12411
0
        return true;
12412
0
      }
12413
0
    }
12414
12415
0
    set_scheme(std::move(_buffer));
12416
12417
0
    if constexpr (has_state_override) {
12418
      // This is uncommon.
12419
0
      uint16_t urls_scheme_port = get_special_port();
12420
12421
0
      if (urls_scheme_port) {
12422
        // If url's port is url's scheme's default port, then set url's port to
12423
        // null.
12424
0
        if (port.has_value() && *port == urls_scheme_port) {
12425
0
          port = std::nullopt;
12426
0
        }
12427
0
      }
12428
0
    }
12429
0
  }
12430
12431
0
  return true;
12432
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> >)
12433
12434
0
ada_really_inline bool url::parse_host(std::string_view input) {
12435
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
12436
0
  if (input.empty()) {
12437
0
    return is_valid = false;
12438
0
  }  // technically unnecessary.
12439
  // If input starts with U+005B ([), then:
12440
0
  if (input[0] == '[') {
12441
    // If input does not end with U+005D (]), validation error, return failure.
12442
0
    if (input.back() != ']') {
12443
0
      return is_valid = false;
12444
0
    }
12445
0
    ada_log("parse_host ipv6");
12446
12447
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
12448
    // trailing U+005D (]) removed.
12449
0
    input.remove_prefix(1);
12450
0
    input.remove_suffix(1);
12451
0
    return parse_ipv6(input);
12452
0
  }
12453
12454
  // If isNotSpecial is true, then return the result of opaque-host parsing
12455
  // input.
12456
0
  if (!is_special()) {
12457
0
    return parse_opaque_host(input);
12458
0
  }
12459
  // Let domain be the result of running UTF-8 decode without BOM on the
12460
  // percent-decoding of input. Let asciiDomain be the result of running domain
12461
  // to ASCII with domain and false. The most common case is an ASCII input, in
12462
  // which case we do not need to call the expensive 'to_ascii' if a few
12463
  // conditions are met: no '%' and no 'xn-' subsequence.
12464
0
  std::string buffer = std::string(input);
12465
  // This next function checks that the result is ascii, but we are going to
12466
  // to check anyhow with is_forbidden.
12467
  // bool is_ascii =
12468
0
  unicode::to_lower_ascii(buffer.data(), buffer.size());
12469
0
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
12470
0
      buffer.data(), buffer.size());
12471
0
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
12472
    // fast path
12473
0
    host = std::move(buffer);
12474
0
    if (checkers::is_ipv4(host.value())) {
12475
0
      ada_log("parse_host fast path ipv4");
12476
0
      return parse_ipv4(host.value());
12477
0
    }
12478
0
    ada_log("parse_host fast path ", *host);
12479
0
    return true;
12480
0
  }
12481
0
  ada_log("parse_host calling to_ascii");
12482
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
12483
0
  if (!is_valid) {
12484
0
    ada_log("parse_host to_ascii returns false");
12485
0
    return is_valid = false;
12486
0
  }
12487
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
12488
0
          " bytes]");
12489
12490
0
  if (std::any_of(host.value().begin(), host.value().end(),
12491
0
                  ada::unicode::is_forbidden_domain_code_point)) {
12492
0
    host = std::nullopt;
12493
0
    return is_valid = false;
12494
0
  }
12495
12496
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
12497
  // asciiDomain.
12498
0
  if (checkers::is_ipv4(host.value())) {
12499
0
    ada_log("parse_host got ipv4 ", *host);
12500
0
    return parse_ipv4(host.value());
12501
0
  }
12502
12503
0
  return true;
12504
0
}
12505
12506
0
ada_really_inline void url::parse_path(std::string_view input) {
12507
0
  ada_log("parse_path ", input);
12508
0
  std::string tmp_buffer;
12509
0
  std::string_view internal_input;
12510
0
  if (unicode::has_tabs_or_newline(input)) {
12511
0
    tmp_buffer = input;
12512
    // Optimization opportunity: Instead of copying and then pruning, we could
12513
    // just directly build the string from user_input.
12514
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12515
0
    internal_input = tmp_buffer;
12516
0
  } else {
12517
0
    internal_input = input;
12518
0
  }
12519
12520
  // If url is special, then:
12521
0
  if (is_special()) {
12522
0
    if (internal_input.empty()) {
12523
0
      path = "/";
12524
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
12525
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12526
0
    } else {
12527
0
      helpers::parse_prepared_path(internal_input, type, path);
12528
0
    }
12529
0
  } else if (!internal_input.empty()) {
12530
0
    if (internal_input[0] == '/') {
12531
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
12532
0
    } else {
12533
0
      helpers::parse_prepared_path(internal_input, type, path);
12534
0
    }
12535
0
  } else {
12536
0
    if (!host.has_value()) {
12537
0
      path = "/";
12538
0
    }
12539
0
  }
12540
0
}
12541
12542
0
[[nodiscard]] std::string url::to_string() const {
12543
0
  if (!is_valid) {
12544
0
    return "null";
12545
0
  }
12546
0
  std::string answer;
12547
0
  auto back = std::back_insert_iterator(answer);
12548
0
  answer.append("{\n");
12549
0
  answer.append("\t\"protocol\":\"");
12550
0
  helpers::encode_json(get_protocol(), back);
12551
0
  answer.append("\",\n");
12552
0
  if (has_credentials()) {
12553
0
    answer.append("\t\"username\":\"");
12554
0
    helpers::encode_json(username, back);
12555
0
    answer.append("\",\n");
12556
0
    answer.append("\t\"password\":\"");
12557
0
    helpers::encode_json(password, back);
12558
0
    answer.append("\",\n");
12559
0
  }
12560
0
  if (host.has_value()) {
12561
0
    answer.append("\t\"host\":\"");
12562
0
    helpers::encode_json(host.value(), back);
12563
0
    answer.append("\",\n");
12564
0
  }
12565
0
  if (port.has_value()) {
12566
0
    answer.append("\t\"port\":\"");
12567
0
    answer.append(std::to_string(port.value()));
12568
0
    answer.append("\",\n");
12569
0
  }
12570
0
  answer.append("\t\"path\":\"");
12571
0
  helpers::encode_json(path, back);
12572
0
  answer.append("\",\n");
12573
0
  answer.append("\t\"opaque path\":");
12574
0
  answer.append((has_opaque_path ? "true" : "false"));
12575
0
  if (has_search()) {
12576
0
    answer.append(",\n");
12577
0
    answer.append("\t\"query\":\"");
12578
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
12579
0
    helpers::encode_json(query.value(), back);
12580
0
    answer.append("\"");
12581
0
  }
12582
0
  if (hash.has_value()) {
12583
0
    answer.append(",\n");
12584
0
    answer.append("\t\"hash\":\"");
12585
0
    helpers::encode_json(hash.value(), back);
12586
0
    answer.append("\"");
12587
0
  }
12588
0
  answer.append("\n}");
12589
0
  return answer;
12590
0
}
12591
12592
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
12593
0
  if (!host.has_value()) {
12594
0
    return false;
12595
0
  }
12596
0
  return checkers::verify_dns_length(host.value());
12597
0
}
12598
12599
0
[[nodiscard]] std::string url::get_origin() const noexcept {
12600
0
  if (is_special()) {
12601
    // Return a new opaque origin.
12602
0
    if (type == scheme::FILE) {
12603
0
      return "null";
12604
0
    }
12605
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
12606
0
  }
12607
12608
0
  if (non_special_scheme == "blob") {
12609
0
    if (!path.empty()) {
12610
0
      auto result = ada::parse<ada::url>(path);
12611
0
      if (result &&
12612
0
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
12613
        // If pathURL's scheme is not "http" and not "https", then return a
12614
        // new opaque origin.
12615
0
        return ada::helpers::concat(result->get_protocol(), "//",
12616
0
                                    result->get_host());
12617
0
      }
12618
0
    }
12619
0
  }
12620
12621
  // Return a new opaque origin.
12622
0
  return "null";
12623
0
}
12624
12625
0
[[nodiscard]] std::string url::get_protocol() const noexcept {
12626
0
  if (is_special()) {
12627
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
12628
0
  }
12629
  // We only move the 'scheme' if it is non-special.
12630
0
  return helpers::concat(non_special_scheme, ":");
12631
0
}
12632
12633
0
[[nodiscard]] std::string url::get_host() const noexcept {
12634
  // If url's host is null, then return the empty string.
12635
  // If url's port is null, return url's host, serialized.
12636
  // Return url's host, serialized, followed by U+003A (:) and url's port,
12637
  // serialized.
12638
0
  if (!host.has_value()) {
12639
0
    return "";
12640
0
  }
12641
0
  if (port.has_value()) {
12642
0
    return host.value() + ":" + get_port();
12643
0
  }
12644
0
  return host.value();
12645
0
}
12646
12647
0
[[nodiscard]] std::string url::get_hostname() const noexcept {
12648
0
  return host.value_or("");
12649
0
}
12650
12651
0
[[nodiscard]] std::string url::get_search() const noexcept {
12652
  // If this's URL's query is either null or the empty string, then return the
12653
  // empty string. Return U+003F (?), followed by this's URL's query.
12654
0
  return (!query.has_value() || (query.value().empty())) ? ""
12655
0
                                                         : "?" + query.value();
12656
0
}
12657
12658
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
12659
0
  return username;
12660
0
}
12661
12662
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
12663
0
  return password;
12664
0
}
12665
12666
0
[[nodiscard]] std::string url::get_port() const noexcept {
12667
0
  return port.has_value() ? std::to_string(port.value()) : "";
12668
0
}
12669
12670
0
[[nodiscard]] std::string url::get_hash() const noexcept {
12671
  // If this's URL's fragment is either null or the empty string, then return
12672
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
12673
0
  return (!hash.has_value() || (hash.value().empty())) ? ""
12674
0
                                                       : "#" + hash.value();
12675
0
}
12676
12677
template <bool override_hostname>
12678
0
bool url::set_host_or_hostname(const std::string_view input) {
12679
0
  if (has_opaque_path) {
12680
0
    return false;
12681
0
  }
12682
12683
0
  std::optional<std::string> previous_host = host;
12684
0
  std::optional<uint16_t> previous_port = port;
12685
12686
0
  size_t host_end_pos = input.find('#');
12687
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
12688
0
                                      ? host_end_pos
12689
0
                                      : input.size());
12690
0
  helpers::remove_ascii_tab_or_newline(_host);
12691
0
  std::string_view new_host(_host);
12692
12693
  // If url's scheme is "file", then set state to file host state, instead of
12694
  // host state.
12695
0
  if (type != ada::scheme::type::FILE) {
12696
0
    std::string_view host_view(_host.data(), _host.length());
12697
0
    auto [location, found_colon] =
12698
0
        helpers::get_host_delimiter_location(is_special(), host_view);
12699
12700
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
12701
    // Note: the 'found_colon' value is true if and only if a colon was
12702
    // encountered while not inside brackets.
12703
0
    if (found_colon) {
12704
      // If buffer is the empty string, host-missing validation error, return
12705
      // failure.
12706
0
      std::string_view buffer = host_view.substr(0, location);
12707
0
      if (buffer.empty()) {
12708
0
        return false;
12709
0
      }
12710
12711
      // If state override is given and state override is hostname state, then
12712
      // return failure.
12713
0
      if constexpr (override_hostname) {
12714
0
        return false;
12715
0
      }
12716
12717
      // Let host be the result of host parsing buffer with url is not special.
12718
0
      bool succeeded = parse_host(buffer);
12719
0
      if (!succeeded) {
12720
0
        host = std::move(previous_host);
12721
0
        update_base_port(previous_port);
12722
0
        return false;
12723
0
      }
12724
12725
      // Set url's host to host, buffer to the empty string, and state to port
12726
      // state.
12727
0
      std::string_view port_buffer = new_host.substr(location + 1);
12728
0
      if (!port_buffer.empty()) {
12729
0
        set_port(port_buffer);
12730
0
      }
12731
0
      return true;
12732
0
    }
12733
    // Otherwise, if one of the following is true:
12734
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
12735
    // - url is special and c is U+005C (\)
12736
0
    else {
12737
      // If url is special and host_view is the empty string, host-missing
12738
      // validation error, return failure.
12739
0
      if (host_view.empty() && is_special()) {
12740
0
        return false;
12741
0
      }
12742
12743
      // Otherwise, if state override is given, host_view is the empty string,
12744
      // and either url includes credentials or url's port is non-null, then
12745
      // return failure.
12746
0
      if (host_view.empty() && (has_credentials() || port.has_value())) {
12747
0
        return false;
12748
0
      }
12749
12750
      // Let host be the result of host parsing host_view with url is not
12751
      // special.
12752
0
      if (host_view.empty() && !is_special()) {
12753
0
        host = "";
12754
0
        return true;
12755
0
      }
12756
12757
0
      bool succeeded = parse_host(host_view);
12758
0
      if (!succeeded) {
12759
0
        host = std::move(previous_host);
12760
0
        update_base_port(previous_port);
12761
0
        return false;
12762
0
      }
12763
0
      return true;
12764
0
    }
12765
0
  }
12766
12767
0
  size_t location = new_host.find_first_of("/\\?");
12768
0
  if (location != std::string_view::npos) {
12769
0
    new_host.remove_suffix(new_host.length() - location);
12770
0
  }
12771
12772
0
  if (new_host.empty()) {
12773
    // Set url's host to the empty string.
12774
0
    host = "";
12775
0
  } else {
12776
    // Let host be the result of host parsing buffer with url is not special.
12777
0
    if (!parse_host(new_host)) {
12778
0
      host = std::move(previous_host);
12779
0
      update_base_port(previous_port);
12780
0
      return false;
12781
0
    }
12782
12783
    // If host is "localhost", then set host to the empty string.
12784
0
    if (host == "localhost") {
12785
0
      host = "";
12786
0
    }
12787
0
  }
12788
0
  return true;
12789
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> >)
12790
12791
0
bool url::set_host(const std::string_view input) {
12792
0
  return set_host_or_hostname<false>(input);
12793
0
}
12794
12795
0
bool url::set_hostname(const std::string_view input) {
12796
0
  return set_host_or_hostname<true>(input);
12797
0
}
12798
12799
0
bool url::set_username(const std::string_view input) {
12800
0
  if (cannot_have_credentials_or_port()) {
12801
0
    return false;
12802
0
  }
12803
0
  username = ada::unicode::percent_encode(
12804
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
12805
0
  return true;
12806
0
}
12807
12808
0
bool url::set_password(const std::string_view input) {
12809
0
  if (cannot_have_credentials_or_port()) {
12810
0
    return false;
12811
0
  }
12812
0
  password = ada::unicode::percent_encode(
12813
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
12814
0
  return true;
12815
0
}
12816
12817
0
bool url::set_port(const std::string_view input) {
12818
0
  if (cannot_have_credentials_or_port()) {
12819
0
    return false;
12820
0
  }
12821
12822
0
  if (input.empty()) {
12823
0
    port = std::nullopt;
12824
0
    return true;
12825
0
  }
12826
12827
0
  std::string trimmed(input);
12828
0
  helpers::remove_ascii_tab_or_newline(trimmed);
12829
12830
0
  if (trimmed.empty()) {
12831
0
    return true;
12832
0
  }
12833
12834
  // Input should not start with a non-digit character.
12835
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
12836
0
    return false;
12837
0
  }
12838
12839
  // Find the first non-digit character to determine the length of digits
12840
0
  auto first_non_digit =
12841
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
12842
0
  std::string_view digits_to_parse =
12843
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
12844
12845
  // Revert changes if parse_port fails.
12846
0
  std::optional<uint16_t> previous_port = port;
12847
0
  parse_port(digits_to_parse);
12848
0
  if (is_valid) {
12849
0
    return true;
12850
0
  }
12851
0
  port = std::move(previous_port);
12852
0
  is_valid = true;
12853
0
  return false;
12854
0
}
12855
12856
0
void url::set_hash(const std::string_view input) {
12857
0
  if (input.empty()) {
12858
0
    hash = std::nullopt;
12859
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12860
0
    return;
12861
0
  }
12862
12863
0
  std::string new_value;
12864
0
  new_value = input[0] == '#' ? input.substr(1) : input;
12865
0
  helpers::remove_ascii_tab_or_newline(new_value);
12866
0
  hash = unicode::percent_encode(new_value,
12867
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
12868
0
}
12869
12870
0
void url::set_search(const std::string_view input) {
12871
0
  if (input.empty()) {
12872
0
    query = std::nullopt;
12873
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
12874
0
    return;
12875
0
  }
12876
12877
0
  std::string new_value;
12878
0
  new_value = input[0] == '?' ? input.substr(1) : input;
12879
0
  helpers::remove_ascii_tab_or_newline(new_value);
12880
12881
0
  auto query_percent_encode_set =
12882
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
12883
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
12884
12885
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
12886
0
}
12887
12888
0
bool url::set_pathname(const std::string_view input) {
12889
0
  if (has_opaque_path) {
12890
0
    return false;
12891
0
  }
12892
0
  path.clear();
12893
0
  parse_path(input);
12894
0
  return true;
12895
0
}
12896
12897
0
bool url::set_protocol(const std::string_view input) {
12898
0
  std::string view(input);
12899
0
  helpers::remove_ascii_tab_or_newline(view);
12900
0
  if (view.empty()) {
12901
0
    return true;
12902
0
  }
12903
12904
  // Schemes should start with alpha values.
12905
0
  if (!checkers::is_alpha(view[0])) {
12906
0
    return false;
12907
0
  }
12908
12909
0
  view.append(":");
12910
12911
0
  std::string::iterator pointer =
12912
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
12913
12914
0
  if (pointer != view.end() && *pointer == ':') {
12915
0
    return parse_scheme<true>(
12916
0
        std::string_view(view.data(), pointer - view.begin()));
12917
0
  }
12918
0
  return false;
12919
0
}
12920
12921
0
bool url::set_href(const std::string_view input) {
12922
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
12923
12924
0
  if (out) {
12925
0
    *this = *out;
12926
0
  }
12927
12928
0
  return out.has_value();
12929
0
}
12930
12931
}  // namespace ada
12932
/* end file src/url.cpp */
12933
/* begin file src/parser.cpp */
12934
12935
#include <limits>
12936
#include <ranges>
12937
12938
12939
namespace ada::parser {
12940
12941
template <class result_type, bool store_values>
12942
result_type parse_url_impl(std::string_view user_input,
12943
0
                           const result_type* base_url) {
12944
  // We can specialize the implementation per type.
12945
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12946
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12947
  // something else } is free (at runtime). This means that ada::url_aggregator
12948
  // and ada::url **do not have to support the exact same API**.
12949
0
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
12950
0
  constexpr bool result_type_is_ada_url_aggregator =
12951
0
      std::is_same_v<url_aggregator, result_type>;
12952
0
  static_assert(result_type_is_ada_url ||
12953
0
                result_type_is_ada_url_aggregator);  // We don't support
12954
                                                     // anything else for now.
12955
12956
0
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12957
0
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12958
0
          ")");
12959
12960
0
  state state = state::SCHEME_START;
12961
0
  result_type url{};
12962
12963
  // We refuse to parse URL strings that exceed 4GB. Such strings are almost
12964
  // surely the result of a bug or are otherwise a security concern.
12965
0
  if (user_input.size() > std::numeric_limits<uint32_t>::max()) [[unlikely]] {
12966
0
    url.is_valid = false;
12967
0
  }
12968
  // Going forward, user_input.size() is in [0,
12969
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12970
  // base, or the optional_url was invalid, we must return.
12971
0
  if (base_url != nullptr) {
12972
0
    url.is_valid &= base_url->is_valid;
12973
0
  }
12974
0
  if (!url.is_valid) {
12975
0
    return url;
12976
0
  }
12977
0
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
12978
    // Most of the time, we just need user_input.size().
12979
    // In some instances, we may need a bit more.
12980
    ///////////////////////////
12981
    // This is *very* important. This line should *not* be removed
12982
    // hastily. There are principled reasons why reserve is important
12983
    // for performance. If you have a benchmark with small inputs,
12984
    // it may not matter, but in other instances, it could.
12985
    ////
12986
    // This rounds up to the next power of two.
12987
    // We know that user_input.size() is in [0,
12988
    // std::numeric_limits<uint32_t>::max).
12989
0
    uint32_t reserve_capacity =
12990
0
        (0xFFFFFFFF >>
12991
0
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12992
0
        1;
12993
0
    url.reserve(reserve_capacity);
12994
0
  }
12995
0
  std::string tmp_buffer;
12996
0
  std::string_view url_data;
12997
0
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
12998
0
    tmp_buffer = user_input;
12999
    // Optimization opportunity: Instead of copying and then pruning, we could
13000
    // just directly build the string from user_input.
13001
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13002
0
    url_data = tmp_buffer;
13003
0
  } else [[likely]] {
13004
0
    url_data = user_input;
13005
0
  }
13006
13007
  // Leading and trailing control characters are uncommon and easy to deal with
13008
  // (no performance concern).
13009
0
  helpers::trim_c0_whitespace(url_data);
13010
13011
  // Optimization opportunity. Most websites do not have fragment.
13012
0
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13013
  // We add it last so that an implementation like ada::url_aggregator
13014
  // can append it last to its internal buffer, thus improving performance.
13015
13016
  // Here url_data no longer has its fragment.
13017
  // We are going to access the data from url_data (it is immutable).
13018
  // At any given time, we are pointing at byte 'input_position' in url_data.
13019
  // The input_position variable should range from 0 to input_size.
13020
  // It is illegal to access url_data at input_size.
13021
0
  size_t input_position = 0;
13022
0
  const size_t input_size = url_data.size();
13023
  // Keep running the following state machine by switching on state.
13024
  // If after a run pointer points to the EOF code point, go to the next step.
13025
  // Otherwise, increase pointer by 1 and continue with the state machine.
13026
  // We never decrement input_position.
13027
0
  while (input_position <= input_size) {
13028
0
    ada_log("In parsing at ", input_position, " out of ", input_size,
13029
0
            " in state ", ada::to_string(state));
13030
0
    switch (state) {
13031
0
      case state::SCHEME_START: {
13032
0
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13033
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13034
        // state to scheme state.
13035
0
        if ((input_position != input_size) &&
13036
0
            checkers::is_alpha(url_data[input_position])) {
13037
0
          state = state::SCHEME;
13038
0
          input_position++;
13039
0
        } else {
13040
          // Otherwise, if state override is not given, set state to no scheme
13041
          // state and decrease pointer by 1.
13042
0
          state = state::NO_SCHEME;
13043
0
        }
13044
0
        break;
13045
0
      }
13046
0
      case state::SCHEME: {
13047
0
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13048
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13049
        // append c, lowercased, to buffer.
13050
0
        while ((input_position != input_size) &&
13051
0
               (unicode::is_alnum_plus(url_data[input_position]))) {
13052
0
          input_position++;
13053
0
        }
13054
        // Otherwise, if c is U+003A (:), then:
13055
0
        if ((input_position != input_size) &&
13056
0
            (url_data[input_position] == ':')) {
13057
0
          ada_log("SCHEME the scheme should be ",
13058
0
                  url_data.substr(0, input_position));
13059
0
          if constexpr (result_type_is_ada_url) {
13060
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13061
0
              return url;
13062
0
            }
13063
0
          } else {
13064
            // we pass the colon along instead of painfully adding it back.
13065
0
            if (!url.parse_scheme_with_colon(
13066
0
                    url_data.substr(0, input_position + 1))) {
13067
0
              return url;
13068
0
            }
13069
0
          }
13070
0
          ada_log("SCHEME the scheme is ", url.get_protocol());
13071
13072
          // If url's scheme is "file", then:
13073
0
          if (url.type == scheme::type::FILE) {
13074
            // Set state to file state.
13075
0
            state = state::FILE;
13076
0
          }
13077
          // Otherwise, if url is special, base is non-null, and base's scheme
13078
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13079
          // != nullptr is false.
13080
0
          else if (url.is_special() && base_url != nullptr &&
13081
0
                   base_url->type == url.type) {
13082
            // Set state to special relative or authority state.
13083
0
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13084
0
          }
13085
          // Otherwise, if url is special, set state to special authority
13086
          // slashes state.
13087
0
          else if (url.is_special()) {
13088
0
            state = state::SPECIAL_AUTHORITY_SLASHES;
13089
0
          }
13090
          // Otherwise, if remaining starts with an U+002F (/), set state to
13091
          // path or authority state and increase pointer by 1.
13092
0
          else if (input_position + 1 < input_size &&
13093
0
                   url_data[input_position + 1] == '/') {
13094
0
            state = state::PATH_OR_AUTHORITY;
13095
0
            input_position++;
13096
0
          }
13097
          // Otherwise, set url's path to the empty string and set state to
13098
          // opaque path state.
13099
0
          else {
13100
0
            state = state::OPAQUE_PATH;
13101
0
          }
13102
0
        }
13103
        // Otherwise, if state override is not given, set buffer to the empty
13104
        // string, state to no scheme state, and start over (from the first code
13105
        // point in input).
13106
0
        else {
13107
0
          state = state::NO_SCHEME;
13108
0
          input_position = 0;
13109
0
          break;
13110
0
        }
13111
0
        input_position++;
13112
0
        break;
13113
0
      }
13114
0
      case state::NO_SCHEME: {
13115
0
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13116
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13117
        // validation error, return failure.
13118
0
        if (base_url == nullptr ||
13119
0
            (base_url->has_opaque_path && !fragment.has_value())) {
13120
0
          ada_log("NO_SCHEME validation error");
13121
0
          url.is_valid = false;
13122
0
          return url;
13123
0
        }
13124
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13125
        // set url's scheme to base's scheme, url's path to base's path, url's
13126
        // query to base's query, and set state to fragment state.
13127
0
        else if (base_url->has_opaque_path && fragment.has_value() &&
13128
0
                 input_position == input_size) {
13129
0
          ada_log("NO_SCHEME opaque base with fragment");
13130
0
          url.copy_scheme(*base_url);
13131
0
          url.has_opaque_path = base_url->has_opaque_path;
13132
13133
0
          if constexpr (result_type_is_ada_url) {
13134
0
            url.path = base_url->path;
13135
0
            url.query = base_url->query;
13136
0
          } else {
13137
0
            url.update_base_pathname(base_url->get_pathname());
13138
0
            url.update_base_search(base_url->get_search());
13139
0
          }
13140
0
          url.update_unencoded_base_hash(*fragment);
13141
0
          return url;
13142
0
        }
13143
        // Otherwise, if base's scheme is not "file", set state to relative
13144
        // state and decrease pointer by 1.
13145
0
        else if (base_url->type != scheme::type::FILE) {
13146
0
          ada_log("NO_SCHEME non-file relative path");
13147
0
          state = state::RELATIVE_SCHEME;
13148
0
        }
13149
        // Otherwise, set state to file state and decrease pointer by 1.
13150
0
        else {
13151
0
          ada_log("NO_SCHEME file base type");
13152
0
          state = state::FILE;
13153
0
        }
13154
0
        break;
13155
0
      }
13156
0
      case state::AUTHORITY: {
13157
0
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13158
        // most URLs have no @. Having no @ tells us that we don't have to worry
13159
        // about AUTHORITY. Of course, we could have @ and still not have to
13160
        // worry about AUTHORITY.
13161
        // TODO: Instead of just collecting a bool, collect the location of the
13162
        // '@' and do something useful with it.
13163
        // TODO: We could do various processing early on, using a single pass
13164
        // over the string to collect information about it, e.g., telling us
13165
        // whether there is a @ and if so, where (or how many).
13166
13167
        // Check if url data contains an @.
13168
0
        if (url_data.find('@', input_position) == std::string_view::npos) {
13169
0
          state = state::HOST;
13170
0
          break;
13171
0
        }
13172
0
        bool at_sign_seen{false};
13173
0
        bool password_token_seen{false};
13174
        /**
13175
         * We expect something of the sort...
13176
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13177
         * --------^
13178
         */
13179
0
        do {
13180
0
          std::string_view view = url_data.substr(input_position);
13181
          // The delimiters are @, /, ? \\.
13182
0
          size_t location =
13183
0
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13184
0
                               : helpers::find_authority_delimiter(view);
13185
0
          std::string_view authority_view = view.substr(0, location);
13186
0
          size_t end_of_authority = input_position + authority_view.size();
13187
          // If c is U+0040 (@), then:
13188
0
          if ((end_of_authority != input_size) &&
13189
0
              (url_data[end_of_authority] == '@')) {
13190
            // If atSignSeen is true, then prepend "%40" to buffer.
13191
0
            if (at_sign_seen) {
13192
0
              if (password_token_seen) {
13193
0
                if constexpr (result_type_is_ada_url) {
13194
0
                  url.password += "%40";
13195
0
                } else {
13196
0
                  url.append_base_password("%40");
13197
0
                }
13198
0
              } else {
13199
0
                if constexpr (result_type_is_ada_url) {
13200
0
                  url.username += "%40";
13201
0
                } else {
13202
0
                  url.append_base_username("%40");
13203
0
                }
13204
0
              }
13205
0
            }
13206
13207
0
            at_sign_seen = true;
13208
13209
0
            if (!password_token_seen) {
13210
0
              size_t password_token_location = authority_view.find(':');
13211
0
              password_token_seen =
13212
0
                  password_token_location != std::string_view::npos;
13213
13214
0
              if constexpr (store_values) {
13215
0
                if (!password_token_seen) {
13216
0
                  if constexpr (result_type_is_ada_url) {
13217
0
                    url.username += unicode::percent_encode(
13218
0
                        authority_view,
13219
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13220
0
                  } else {
13221
0
                    url.append_base_username(unicode::percent_encode(
13222
0
                        authority_view,
13223
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13224
0
                  }
13225
0
                } else {
13226
0
                  if constexpr (result_type_is_ada_url) {
13227
0
                    url.username += unicode::percent_encode(
13228
0
                        authority_view.substr(0, password_token_location),
13229
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13230
0
                    url.password += unicode::percent_encode(
13231
0
                        authority_view.substr(password_token_location + 1),
13232
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13233
0
                  } else {
13234
0
                    url.append_base_username(unicode::percent_encode(
13235
0
                        authority_view.substr(0, password_token_location),
13236
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13237
0
                    url.append_base_password(unicode::percent_encode(
13238
0
                        authority_view.substr(password_token_location + 1),
13239
0
                        character_sets::USERINFO_PERCENT_ENCODE));
13240
0
                  }
13241
0
                }
13242
0
              }
13243
0
            } else if constexpr (store_values) {
13244
0
              if constexpr (result_type_is_ada_url) {
13245
0
                url.password += unicode::percent_encode(
13246
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13247
0
              } else {
13248
0
                url.append_base_password(unicode::percent_encode(
13249
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13250
0
              }
13251
0
            }
13252
0
          }
13253
          // Otherwise, if one of the following is true:
13254
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13255
          // - url is special and c is U+005C (\)
13256
0
          else if (end_of_authority == input_size ||
13257
0
                   url_data[end_of_authority] == '/' ||
13258
0
                   url_data[end_of_authority] == '?' ||
13259
0
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13260
            // If atSignSeen is true and authority_view is the empty string,
13261
            // validation error, return failure.
13262
0
            if (at_sign_seen && authority_view.empty()) {
13263
0
              url.is_valid = false;
13264
0
              return url;
13265
0
            }
13266
0
            state = state::HOST;
13267
0
            break;
13268
0
          }
13269
0
          if (end_of_authority == input_size) {
13270
0
            if constexpr (store_values) {
13271
0
              if (fragment.has_value()) {
13272
0
                url.update_unencoded_base_hash(*fragment);
13273
0
              }
13274
0
            }
13275
0
            return url;
13276
0
          }
13277
0
          input_position = end_of_authority + 1;
13278
0
        } while (true);
13279
13280
0
        break;
13281
0
      }
13282
0
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13283
0
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13284
0
                helpers::substring(url_data, input_position));
13285
13286
        // If c is U+002F (/) and remaining starts with U+002F (/),
13287
        // then set state to special authority ignore slashes state and increase
13288
        // pointer by 1.
13289
0
        if (url_data.substr(input_position, 2) == "//") {
13290
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13291
0
          input_position += 2;
13292
0
        } else {
13293
          // Otherwise, validation error, set state to relative state and
13294
          // decrease pointer by 1.
13295
0
          state = state::RELATIVE_SCHEME;
13296
0
        }
13297
13298
0
        break;
13299
0
      }
13300
0
      case state::PATH_OR_AUTHORITY: {
13301
0
        ada_log("PATH_OR_AUTHORITY ",
13302
0
                helpers::substring(url_data, input_position));
13303
13304
        // If c is U+002F (/), then set state to authority state.
13305
0
        if ((input_position != input_size) &&
13306
0
            (url_data[input_position] == '/')) {
13307
0
          state = state::AUTHORITY;
13308
0
          input_position++;
13309
0
        } else {
13310
          // Otherwise, set state to path state, and decrease pointer by 1.
13311
0
          state = state::PATH;
13312
0
        }
13313
13314
0
        break;
13315
0
      }
13316
0
      case state::RELATIVE_SCHEME: {
13317
0
        ada_log("RELATIVE_SCHEME ",
13318
0
                helpers::substring(url_data, input_position));
13319
13320
        // Set url's scheme to base's scheme.
13321
0
        url.copy_scheme(*base_url);
13322
13323
        // If c is U+002F (/), then set state to relative slash state.
13324
0
        if ((input_position != input_size) &&
13325
            // NOLINTNEXTLINE(bugprone-branch-clone)
13326
0
            (url_data[input_position] == '/')) {
13327
0
          ada_log(
13328
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13329
0
              "slash state");
13330
0
          state = state::RELATIVE_SLASH;
13331
0
        } else if (url.is_special() && (input_position != input_size) &&
13332
0
                   (url_data[input_position] == '\\')) {
13333
          // Otherwise, if url is special and c is U+005C (\), validation error,
13334
          // set state to relative slash state.
13335
0
          ada_log(
13336
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13337
0
              "error, set state to relative slash state");
13338
0
          state = state::RELATIVE_SLASH;
13339
0
        } else {
13340
0
          ada_log("RELATIVE_SCHEME otherwise");
13341
          // Set url's username to base's username, url's password to base's
13342
          // password, url's host to base's host, url's port to base's port,
13343
          // url's path to a clone of base's path, and url's query to base's
13344
          // query.
13345
0
          if constexpr (result_type_is_ada_url) {
13346
0
            url.username = base_url->username;
13347
0
            url.password = base_url->password;
13348
0
            url.host = base_url->host;
13349
0
            url.port = base_url->port;
13350
            // cloning the base path includes cloning the has_opaque_path flag
13351
0
            url.has_opaque_path = base_url->has_opaque_path;
13352
0
            url.path = base_url->path;
13353
0
            url.query = base_url->query;
13354
0
          } else {
13355
0
            url.update_base_authority(base_url->get_href(),
13356
0
                                      base_url->get_components());
13357
0
            url.update_host_to_base_host(base_url->get_hostname());
13358
0
            url.update_base_port(base_url->retrieve_base_port());
13359
            // cloning the base path includes cloning the has_opaque_path flag
13360
0
            url.has_opaque_path = base_url->has_opaque_path;
13361
0
            url.update_base_pathname(base_url->get_pathname());
13362
0
            url.update_base_search(base_url->get_search());
13363
0
          }
13364
13365
0
          url.has_opaque_path = base_url->has_opaque_path;
13366
13367
          // If c is U+003F (?), then set url's query to the empty string, and
13368
          // state to query state.
13369
0
          if ((input_position != input_size) &&
13370
0
              (url_data[input_position] == '?')) {
13371
0
            state = state::QUERY;
13372
0
          }
13373
          // Otherwise, if c is not the EOF code point:
13374
0
          else if (input_position != input_size) {
13375
            // Set url's query to null.
13376
0
            url.clear_search();
13377
0
            if constexpr (result_type_is_ada_url) {
13378
              // Shorten url's path.
13379
0
              helpers::shorten_path(url.path, url.type);
13380
0
            } else {
13381
0
              std::string_view path = url.get_pathname();
13382
0
              if (helpers::shorten_path(path, url.type)) {
13383
0
                url.update_base_pathname(std::move(std::string(path)));
13384
0
              }
13385
0
            }
13386
            // Set state to path state and decrease pointer by 1.
13387
0
            state = state::PATH;
13388
0
            break;
13389
0
          }
13390
0
        }
13391
0
        input_position++;
13392
0
        break;
13393
0
      }
13394
0
      case state::RELATIVE_SLASH: {
13395
0
        ada_log("RELATIVE_SLASH ",
13396
0
                helpers::substring(url_data, input_position));
13397
13398
        // If url is special and c is U+002F (/) or U+005C (\), then:
13399
0
        if (url.is_special() && (input_position != input_size) &&
13400
0
            (url_data[input_position] == '/' ||
13401
0
             url_data[input_position] == '\\')) {
13402
          // Set state to special authority ignore slashes state.
13403
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13404
0
        }
13405
        // Otherwise, if c is U+002F (/), then set state to authority state.
13406
0
        else if ((input_position != input_size) &&
13407
0
                 (url_data[input_position] == '/')) {
13408
0
          state = state::AUTHORITY;
13409
0
        }
13410
        // Otherwise, set
13411
        // - url's username to base's username,
13412
        // - url's password to base's password,
13413
        // - url's host to base's host,
13414
        // - url's port to base's port,
13415
        // - state to path state, and then, decrease pointer by 1.
13416
0
        else {
13417
0
          if constexpr (result_type_is_ada_url) {
13418
0
            url.username = base_url->username;
13419
0
            url.password = base_url->password;
13420
0
            url.host = base_url->host;
13421
0
            url.port = base_url->port;
13422
0
          } else {
13423
0
            url.update_base_authority(base_url->get_href(),
13424
0
                                      base_url->get_components());
13425
0
            url.update_host_to_base_host(base_url->get_hostname());
13426
0
            url.update_base_port(base_url->retrieve_base_port());
13427
0
          }
13428
0
          state = state::PATH;
13429
0
          break;
13430
0
        }
13431
13432
0
        input_position++;
13433
0
        break;
13434
0
      }
13435
0
      case state::SPECIAL_AUTHORITY_SLASHES: {
13436
0
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13437
0
                helpers::substring(url_data, input_position));
13438
13439
        // If c is U+002F (/) and remaining starts with U+002F (/),
13440
        // then set state to special authority ignore slashes state and increase
13441
        // pointer by 1.
13442
0
        if (url_data.substr(input_position, 2) == "//") {
13443
0
          input_position += 2;
13444
0
        }
13445
13446
0
        [[fallthrough]];
13447
0
      }
13448
0
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13449
0
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13450
0
                helpers::substring(url_data, input_position));
13451
13452
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13453
        // authority state and decrease pointer by 1.
13454
0
        while ((input_position != input_size) &&
13455
0
               ((url_data[input_position] == '/') ||
13456
0
                (url_data[input_position] == '\\'))) {
13457
0
          input_position++;
13458
0
        }
13459
0
        state = state::AUTHORITY;
13460
13461
0
        break;
13462
0
      }
13463
0
      case state::QUERY: {
13464
0
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13465
0
        if constexpr (store_values) {
13466
          // Let queryPercentEncodeSet be the special-query percent-encode set
13467
          // if url is special; otherwise the query percent-encode set.
13468
0
          const uint8_t* query_percent_encode_set =
13469
0
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13470
0
                               : character_sets::QUERY_PERCENT_ENCODE;
13471
13472
          // Percent-encode after encoding, with encoding, buffer, and
13473
          // queryPercentEncodeSet, and append the result to url's query.
13474
0
          url.update_base_search(url_data.substr(input_position),
13475
0
                                 query_percent_encode_set);
13476
0
          ada_log("QUERY update_base_search completed ");
13477
0
          if (fragment.has_value()) {
13478
0
            url.update_unencoded_base_hash(*fragment);
13479
0
          }
13480
0
        }
13481
0
        return url;
13482
0
      }
13483
0
      case state::HOST: {
13484
0
        ada_log("HOST ", helpers::substring(url_data, input_position));
13485
13486
0
        std::string_view host_view = url_data.substr(input_position);
13487
0
        auto [location, found_colon] =
13488
0
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13489
0
        input_position = (location != std::string_view::npos)
13490
0
                             ? input_position + location
13491
0
                             : input_size;
13492
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13493
        // Note: the 'found_colon' value is true if and only if a colon was
13494
        // encountered while not inside brackets.
13495
0
        if (found_colon) {
13496
          // If buffer is the empty string, validation error, return failure.
13497
          // Let host be the result of host parsing buffer with url is not
13498
          // special.
13499
0
          ada_log("HOST parsing ", host_view);
13500
0
          if (!url.parse_host(host_view)) {
13501
0
            return url;
13502
0
          }
13503
0
          ada_log("HOST parsing results in ", url.get_hostname());
13504
          // Set url's host to host, buffer to the empty string, and state to
13505
          // port state.
13506
0
          state = state::PORT;
13507
0
          input_position++;
13508
0
        }
13509
        // Otherwise, if one of the following is true:
13510
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13511
        // - url is special and c is U+005C (\)
13512
        // The get_host_delimiter_location function either brings us to
13513
        // the colon outside of the bracket, or to one of those characters.
13514
0
        else {
13515
          // If url is special and host_view is the empty string, validation
13516
          // error, return failure.
13517
0
          if (host_view.empty() && url.is_special()) {
13518
0
            url.is_valid = false;
13519
0
            return url;
13520
0
          }
13521
0
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13522
          // Let host be the result of host parsing host_view with url is not
13523
          // special.
13524
0
          if (host_view.empty()) {
13525
0
            url.update_base_hostname("");
13526
0
          } else if (!url.parse_host(host_view)) {
13527
0
            return url;
13528
0
          }
13529
0
          ada_log("HOST parsing results in ", url.get_hostname(),
13530
0
                  " href=", url.get_href());
13531
13532
          // Set url's host to host, and state to path start state.
13533
0
          state = state::PATH_START;
13534
0
        }
13535
13536
0
        break;
13537
0
      }
13538
0
      case state::OPAQUE_PATH: {
13539
0
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13540
0
        std::string_view view = url_data.substr(input_position);
13541
        // If c is U+003F (?), then set url's query to the empty string and
13542
        // state to query state.
13543
0
        size_t location = view.find('?');
13544
0
        if (location != std::string_view::npos) {
13545
0
          view.remove_suffix(view.size() - location);
13546
0
          state = state::QUERY;
13547
0
          input_position += location + 1;
13548
0
        } else {
13549
0
          input_position = input_size + 1;
13550
0
        }
13551
0
        url.has_opaque_path = true;
13552
13553
        // This is a really unlikely scenario in real world. We should not seek
13554
        // to optimize it.
13555
0
        if (view.ends_with(' ')) {
13556
0
          std::string modified_view =
13557
0
              std::string(view.substr(0, view.size() - 1)) + "%20";
13558
0
          url.update_base_pathname(unicode::percent_encode(
13559
0
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13560
0
        } else {
13561
0
          url.update_base_pathname(unicode::percent_encode(
13562
0
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13563
0
        }
13564
0
        break;
13565
0
      }
13566
0
      case state::PORT: {
13567
0
        ada_log("PORT ", helpers::substring(url_data, input_position));
13568
0
        std::string_view port_view = url_data.substr(input_position);
13569
0
        input_position += url.parse_port(port_view, true);
13570
0
        if (!url.is_valid) {
13571
0
          return url;
13572
0
        }
13573
0
        state = state::PATH_START;
13574
0
        [[fallthrough]];
13575
0
      }
13576
0
      case state::PATH_START: {
13577
0
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13578
13579
        // If url is special, then:
13580
0
        if (url.is_special()) {
13581
          // Set state to path state.
13582
0
          state = state::PATH;
13583
13584
          // Optimization: Avoiding going into PATH state improves the
13585
          // performance of urls ending with /.
13586
0
          if (input_position == input_size) {
13587
0
            if constexpr (store_values) {
13588
0
              url.update_base_pathname("/");
13589
0
              if (fragment.has_value()) {
13590
0
                url.update_unencoded_base_hash(*fragment);
13591
0
              }
13592
0
            }
13593
0
            return url;
13594
0
          }
13595
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13596
          // by 1. We know that (input_position == input_size) is impossible
13597
          // here, because of the previous if-check.
13598
0
          if ((url_data[input_position] != '/') &&
13599
0
              (url_data[input_position] != '\\')) {
13600
0
            break;
13601
0
          }
13602
0
        }
13603
        // Otherwise, if state override is not given and c is U+003F (?),
13604
        // set url's query to the empty string and state to query state.
13605
0
        else if ((input_position != input_size) &&
13606
0
                 (url_data[input_position] == '?')) {
13607
0
          state = state::QUERY;
13608
0
        }
13609
        // Otherwise, if c is not the EOF code point:
13610
0
        else if (input_position != input_size) {
13611
          // Set state to path state.
13612
0
          state = state::PATH;
13613
13614
          // If c is not U+002F (/), then decrease pointer by 1.
13615
0
          if (url_data[input_position] != '/') {
13616
0
            break;
13617
0
          }
13618
0
        }
13619
13620
0
        input_position++;
13621
0
        break;
13622
0
      }
13623
0
      case state::PATH: {
13624
0
        ada_log("PATH ", helpers::substring(url_data, input_position));
13625
0
        std::string_view view = url_data.substr(input_position);
13626
13627
        // Most time, we do not need percent encoding.
13628
        // Furthermore, we can immediately locate the '?'.
13629
0
        size_t locofquestionmark = view.find('?');
13630
0
        if (locofquestionmark != std::string_view::npos) {
13631
0
          state = state::QUERY;
13632
0
          view.remove_suffix(view.size() - locofquestionmark);
13633
0
          input_position += locofquestionmark + 1;
13634
0
        } else {
13635
0
          input_position = input_size + 1;
13636
0
        }
13637
0
        if constexpr (store_values) {
13638
0
          if constexpr (result_type_is_ada_url) {
13639
0
            helpers::parse_prepared_path(view, url.type, url.path);
13640
0
          } else {
13641
0
            url.consume_prepared_path(view);
13642
0
            ADA_ASSERT_TRUE(url.validate());
13643
0
          }
13644
0
        }
13645
0
        break;
13646
0
      }
13647
0
      case state::FILE_SLASH: {
13648
0
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13649
13650
        // If c is U+002F (/) or U+005C (\), then:
13651
0
        if ((input_position != input_size) &&
13652
0
            (url_data[input_position] == '/' ||
13653
0
             url_data[input_position] == '\\')) {
13654
0
          ada_log("FILE_SLASH c is U+002F or U+005C");
13655
          // Set state to file host state.
13656
0
          state = state::FILE_HOST;
13657
0
          input_position++;
13658
0
        } else {
13659
0
          ada_log("FILE_SLASH otherwise");
13660
          // If base is non-null and base's scheme is "file", then:
13661
          // Note: it is unsafe to do base_url->scheme unless you know that
13662
          // base_url_has_value() is true.
13663
0
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13664
            // Set url's host to base's host.
13665
0
            if constexpr (result_type_is_ada_url) {
13666
0
              url.host = base_url->host;
13667
0
            } else {
13668
0
              url.update_host_to_base_host(base_url->get_host());
13669
0
            }
13670
            // If the code point substring from pointer to the end of input does
13671
            // not start with a Windows drive letter and base's path[0] is a
13672
            // normalized Windows drive letter, then append base's path[0] to
13673
            // url's path.
13674
0
            if (!base_url->get_pathname().empty()) {
13675
0
              if (!checkers::is_windows_drive_letter(
13676
0
                      url_data.substr(input_position))) {
13677
0
                std::string_view first_base_url_path =
13678
0
                    base_url->get_pathname().substr(1);
13679
0
                size_t loc = first_base_url_path.find('/');
13680
0
                if (loc != std::string_view::npos) {
13681
0
                  helpers::resize(first_base_url_path, loc);
13682
0
                }
13683
0
                if (checkers::is_normalized_windows_drive_letter(
13684
0
                        first_base_url_path)) {
13685
0
                  if constexpr (result_type_is_ada_url) {
13686
0
                    url.path += '/';
13687
0
                    url.path += first_base_url_path;
13688
0
                  } else {
13689
0
                    url.append_base_pathname(
13690
0
                        helpers::concat("/", first_base_url_path));
13691
0
                  }
13692
0
                }
13693
0
              }
13694
0
            }
13695
0
          }
13696
13697
          // Set state to path state, and decrease pointer by 1.
13698
0
          state = state::PATH;
13699
0
        }
13700
13701
0
        break;
13702
0
      }
13703
0
      case state::FILE_HOST: {
13704
0
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13705
0
        std::string_view view = url_data.substr(input_position);
13706
13707
0
        size_t location = view.find_first_of("/\\?");
13708
0
        std::string_view file_host_buffer(
13709
0
            view.data(),
13710
0
            (location != std::string_view::npos) ? location : view.size());
13711
13712
0
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13713
0
          state = state::PATH;
13714
0
        } else if (file_host_buffer.empty()) {
13715
          // Set url's host to the empty string.
13716
0
          if constexpr (result_type_is_ada_url) {
13717
0
            url.host = "";
13718
0
          } else {
13719
0
            url.update_base_hostname("");
13720
0
          }
13721
          // Set state to path start state.
13722
0
          state = state::PATH_START;
13723
0
        } else {
13724
0
          size_t consumed_bytes = file_host_buffer.size();
13725
0
          input_position += consumed_bytes;
13726
          // Let host be the result of host parsing buffer with url is not
13727
          // special.
13728
0
          if (!url.parse_host(file_host_buffer)) {
13729
0
            return url;
13730
0
          }
13731
13732
0
          if constexpr (result_type_is_ada_url) {
13733
            // If host is "localhost", then set host to the empty string.
13734
0
            if (url.host.has_value() && url.host.value() == "localhost") {
13735
0
              url.host = "";
13736
0
            }
13737
0
          } else {
13738
0
            if (url.get_hostname() == "localhost") {
13739
0
              url.update_base_hostname("");
13740
0
            }
13741
0
          }
13742
13743
          // Set buffer to the empty string and state to path start state.
13744
0
          state = state::PATH_START;
13745
0
        }
13746
13747
0
        break;
13748
0
      }
13749
0
      case state::FILE: {
13750
0
        ada_log("FILE ", helpers::substring(url_data, input_position));
13751
0
        std::string_view file_view = url_data.substr(input_position);
13752
13753
0
        url.set_protocol_as_file();
13754
0
        if constexpr (result_type_is_ada_url) {
13755
          // Set url's host to the empty string.
13756
0
          url.host = "";
13757
0
        } else {
13758
0
          url.update_base_hostname("");
13759
0
        }
13760
        // If c is U+002F (/) or U+005C (\), then:
13761
0
        if (input_position != input_size &&
13762
0
            (url_data[input_position] == '/' ||
13763
0
             url_data[input_position] == '\\')) {
13764
0
          ada_log("FILE c is U+002F or U+005C");
13765
          // Set state to file slash state.
13766
0
          state = state::FILE_SLASH;
13767
0
        }
13768
        // Otherwise, if base is non-null and base's scheme is "file":
13769
0
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13770
          // Set url's host to base's host, url's path to a clone of base's
13771
          // path, and url's query to base's query.
13772
0
          ada_log("FILE base non-null");
13773
0
          if constexpr (result_type_is_ada_url) {
13774
0
            url.host = base_url->host;
13775
0
            url.path = base_url->path;
13776
0
            url.query = base_url->query;
13777
0
          } else {
13778
0
            url.update_host_to_base_host(base_url->get_hostname());
13779
0
            url.update_base_pathname(base_url->get_pathname());
13780
0
            url.update_base_search(base_url->get_search());
13781
0
          }
13782
0
          url.has_opaque_path = base_url->has_opaque_path;
13783
13784
          // If c is U+003F (?), then set url's query to the empty string and
13785
          // state to query state.
13786
0
          if (input_position != input_size && url_data[input_position] == '?') {
13787
0
            state = state::QUERY;
13788
0
          }
13789
          // Otherwise, if c is not the EOF code point:
13790
0
          else if (input_position != input_size) {
13791
            // Set url's query to null.
13792
0
            url.clear_search();
13793
            // If the code point substring from pointer to the end of input does
13794
            // not start with a Windows drive letter, then shorten url's path.
13795
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13796
0
              if constexpr (result_type_is_ada_url) {
13797
0
                helpers::shorten_path(url.path, url.type);
13798
0
              } else {
13799
0
                std::string_view path = url.get_pathname();
13800
0
                if (helpers::shorten_path(path, url.type)) {
13801
0
                  url.update_base_pathname(std::move(std::string(path)));
13802
0
                }
13803
0
              }
13804
0
            }
13805
            // Otherwise:
13806
0
            else {
13807
              // Set url's path to an empty list.
13808
0
              url.clear_pathname();
13809
0
              url.has_opaque_path = true;
13810
0
            }
13811
13812
            // Set state to path state and decrease pointer by 1.
13813
0
            state = state::PATH;
13814
0
            break;
13815
0
          }
13816
0
        }
13817
        // Otherwise, set state to path state, and decrease pointer by 1.
13818
0
        else {
13819
0
          ada_log("FILE go to path");
13820
0
          state = state::PATH;
13821
0
          break;
13822
0
        }
13823
13824
0
        input_position++;
13825
0
        break;
13826
0
      }
13827
0
      default:
13828
0
        unreachable();
13829
0
    }
13830
0
  }
13831
0
  if constexpr (store_values) {
13832
0
    if (fragment.has_value()) {
13833
0
      url.update_unencoded_base_hash(*fragment);
13834
0
    }
13835
0
  }
13836
0
  return url;
13837
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*)
13838
13839
template url parse_url_impl(std::string_view user_input,
13840
                            const url* base_url = nullptr);
13841
template url_aggregator parse_url_impl(
13842
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13843
13844
template <class result_type>
13845
result_type parse_url(std::string_view user_input,
13846
0
                      const result_type* base_url) {
13847
0
  return parse_url_impl<result_type, true>(user_input, base_url);
13848
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*)
13849
13850
template url parse_url<url>(std::string_view user_input,
13851
                            const url* base_url = nullptr);
13852
template url_aggregator parse_url<url_aggregator>(
13853
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13854
}  // namespace ada::parser
13855
/* end file src/parser.cpp */
13856
/* begin file src/url_components.cpp */
13857
13858
#include <iterator>
13859
#include <string>
13860
13861
namespace ada {
13862
13863
0
[[nodiscard]] std::string url_components::to_string() const {
13864
0
  std::string answer;
13865
0
  auto back = std::back_insert_iterator(answer);
13866
0
  answer.append("{\n");
13867
13868
0
  answer.append("\t\"protocol_end\":\"");
13869
0
  helpers::encode_json(std::to_string(protocol_end), back);
13870
0
  answer.append("\",\n");
13871
13872
0
  answer.append("\t\"username_end\":\"");
13873
0
  helpers::encode_json(std::to_string(username_end), back);
13874
0
  answer.append("\",\n");
13875
13876
0
  answer.append("\t\"host_start\":\"");
13877
0
  helpers::encode_json(std::to_string(host_start), back);
13878
0
  answer.append("\",\n");
13879
13880
0
  answer.append("\t\"host_end\":\"");
13881
0
  helpers::encode_json(std::to_string(host_end), back);
13882
0
  answer.append("\",\n");
13883
13884
0
  answer.append("\t\"port\":\"");
13885
0
  helpers::encode_json(std::to_string(port), back);
13886
0
  answer.append("\",\n");
13887
13888
0
  answer.append("\t\"pathname_start\":\"");
13889
0
  helpers::encode_json(std::to_string(pathname_start), back);
13890
0
  answer.append("\",\n");
13891
13892
0
  answer.append("\t\"search_start\":\"");
13893
0
  helpers::encode_json(std::to_string(search_start), back);
13894
0
  answer.append("\",\n");
13895
13896
0
  answer.append("\t\"hash_start\":\"");
13897
0
  helpers::encode_json(std::to_string(hash_start), back);
13898
0
  answer.append("\",\n");
13899
13900
0
  answer.append("\n}");
13901
0
  return answer;
13902
0
}
13903
13904
}  // namespace ada
13905
/* end file src/url_components.cpp */
13906
/* begin file src/url_aggregator.cpp */
13907
13908
#include <iterator>
13909
#include <ranges>
13910
#include <string>
13911
#include <string_view>
13912
13913
namespace ada {
13914
template <bool has_state_override>
13915
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13916
0
    const std::string_view input_with_colon) {
13917
0
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13918
0
  ADA_ASSERT_TRUE(validate());
13919
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13920
0
  std::string_view input{input_with_colon};
13921
0
  input.remove_suffix(1);
13922
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
13923
0
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13924
  /**
13925
   * In the common case, we will immediately recognize a special scheme (e.g.,
13926
   *http, https), in which case, we can go really fast.
13927
   **/
13928
0
  if (is_input_special) {  // fast path!!!
13929
0
    if constexpr (has_state_override) {
13930
      // If url's scheme is not a special scheme and buffer is a special scheme,
13931
      // then return.
13932
0
      if (is_special() != is_input_special) {
13933
0
        return false;
13934
0
      }
13935
13936
      // If url includes credentials or has a non-null port, and buffer is
13937
      // "file", then return.
13938
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13939
0
          parsed_type == ada::scheme::type::FILE) {
13940
0
        return false;
13941
0
      }
13942
13943
      // If url's scheme is "file" and its host is an empty host, then return.
13944
      // An empty host is the empty string.
13945
0
      if (type == ada::scheme::type::FILE &&
13946
0
          components.host_start == components.host_end) {
13947
0
        return false;
13948
0
      }
13949
0
    }
13950
13951
0
    type = parsed_type;
13952
0
    set_scheme_from_view_with_colon(input_with_colon);
13953
13954
0
    if constexpr (has_state_override) {
13955
      // This is uncommon.
13956
0
      uint16_t urls_scheme_port = get_special_port();
13957
13958
      // If url's port is url's scheme's default port, then set url's port to
13959
      // null.
13960
0
      if (components.port == urls_scheme_port) {
13961
0
        clear_port();
13962
0
      }
13963
0
    }
13964
0
  } else {  // slow path
13965
0
    std::string _buffer(input);
13966
    // Next function is only valid if the input is ASCII and returns false
13967
    // otherwise, but it seems that we always have ascii content so we do not
13968
    // need to check the return value.
13969
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13970
13971
0
    if constexpr (has_state_override) {
13972
      // If url's scheme is a special scheme and buffer is not a special scheme,
13973
      // then return. If url's scheme is not a special scheme and buffer is a
13974
      // special scheme, then return.
13975
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
13976
0
        return true;
13977
0
      }
13978
13979
      // If url includes credentials or has a non-null port, and buffer is
13980
      // "file", then return.
13981
0
      if ((has_credentials() || components.port != url_components::omitted) &&
13982
0
          _buffer == "file") {
13983
0
        return true;
13984
0
      }
13985
13986
      // If url's scheme is "file" and its host is an empty host, then return.
13987
      // An empty host is the empty string.
13988
0
      if (type == ada::scheme::type::FILE &&
13989
0
          components.host_start == components.host_end) {
13990
0
        return true;
13991
0
      }
13992
0
    }
13993
13994
0
    set_scheme(_buffer);
13995
13996
0
    if constexpr (has_state_override) {
13997
      // This is uncommon.
13998
0
      uint16_t urls_scheme_port = get_special_port();
13999
14000
      // If url's port is url's scheme's default port, then set url's port to
14001
      // null.
14002
0
      if (components.port == urls_scheme_port) {
14003
0
        clear_port();
14004
0
      }
14005
0
    }
14006
0
  }
14007
0
  ADA_ASSERT_TRUE(validate());
14008
0
  return true;
14009
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> >)
14010
14011
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
14012
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14013
0
  ADA_ASSERT_TRUE(validate());
14014
  // next line could overflow but unsigned arithmetic has well-defined
14015
  // overflows.
14016
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14017
0
  type = u.type;
14018
0
  buffer.erase(0, components.protocol_end);
14019
0
  buffer.insert(0, u.get_protocol());
14020
0
  components.protocol_end = u.components.protocol_end;
14021
14022
  // No need to update the components
14023
0
  if (new_difference == 0) {
14024
0
    return;
14025
0
  }
14026
14027
  // Update the rest of the components.
14028
0
  components.username_end += new_difference;
14029
0
  components.host_start += new_difference;
14030
0
  components.host_end += new_difference;
14031
0
  components.pathname_start += new_difference;
14032
0
  if (components.search_start != url_components::omitted) {
14033
0
    components.search_start += new_difference;
14034
0
  }
14035
0
  if (components.hash_start != url_components::omitted) {
14036
0
    components.hash_start += new_difference;
14037
0
  }
14038
0
  ADA_ASSERT_TRUE(validate());
14039
0
}
14040
14041
inline void url_aggregator::set_scheme_from_view_with_colon(
14042
0
    std::string_view new_scheme_with_colon) noexcept {
14043
0
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14044
0
          new_scheme_with_colon);
14045
0
  ADA_ASSERT_TRUE(validate());
14046
0
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14047
0
                  new_scheme_with_colon.back() == ':');
14048
  // next line could overflow but unsigned arithmetic has well-defined
14049
  // overflows.
14050
0
  uint32_t new_difference =
14051
0
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14052
14053
0
  if (buffer.empty()) {
14054
0
    buffer.append(new_scheme_with_colon);
14055
0
  } else {
14056
0
    buffer.erase(0, components.protocol_end);
14057
0
    buffer.insert(0, new_scheme_with_colon);
14058
0
  }
14059
0
  components.protocol_end += new_difference;
14060
14061
  // Update the rest of the components.
14062
0
  components.username_end += new_difference;
14063
0
  components.host_start += new_difference;
14064
0
  components.host_end += new_difference;
14065
0
  components.pathname_start += new_difference;
14066
0
  if (components.search_start != url_components::omitted) {
14067
0
    components.search_start += new_difference;
14068
0
  }
14069
0
  if (components.hash_start != url_components::omitted) {
14070
0
    components.hash_start += new_difference;
14071
0
  }
14072
0
  ADA_ASSERT_TRUE(validate());
14073
0
}
14074
14075
0
inline void url_aggregator::set_scheme(std::string_view new_scheme) noexcept {
14076
0
  ada_log("url_aggregator::set_scheme ", new_scheme);
14077
0
  ADA_ASSERT_TRUE(validate());
14078
0
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14079
  // next line could overflow but unsigned arithmetic has well-defined
14080
  // overflows.
14081
0
  uint32_t new_difference =
14082
0
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14083
14084
0
  type = ada::scheme::get_scheme_type(new_scheme);
14085
0
  if (buffer.empty()) {
14086
0
    buffer.append(helpers::concat(new_scheme, ":"));
14087
0
  } else {
14088
0
    buffer.erase(0, components.protocol_end);
14089
0
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14090
0
  }
14091
0
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14092
14093
  // Update the rest of the components.
14094
0
  components.username_end += new_difference;
14095
0
  components.host_start += new_difference;
14096
0
  components.host_end += new_difference;
14097
0
  components.pathname_start += new_difference;
14098
0
  if (components.search_start != url_components::omitted) {
14099
0
    components.search_start += new_difference;
14100
0
  }
14101
0
  if (components.hash_start != url_components::omitted) {
14102
0
    components.hash_start += new_difference;
14103
0
  }
14104
0
  ADA_ASSERT_TRUE(validate());
14105
0
}
14106
14107
0
bool url_aggregator::set_protocol(const std::string_view input) {
14108
0
  ada_log("url_aggregator::set_protocol ", input);
14109
0
  ADA_ASSERT_TRUE(validate());
14110
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14111
0
  std::string view(input);
14112
0
  helpers::remove_ascii_tab_or_newline(view);
14113
0
  if (view.empty()) {
14114
0
    return true;
14115
0
  }
14116
14117
  // Schemes should start with alpha values.
14118
0
  if (!checkers::is_alpha(view[0])) {
14119
0
    return false;
14120
0
  }
14121
14122
0
  view.append(":");
14123
14124
0
  std::string::iterator pointer =
14125
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14126
14127
0
  if (pointer != view.end() && *pointer == ':') {
14128
0
    return parse_scheme_with_colon<true>(
14129
0
        view.substr(0, pointer - view.begin() + 1));
14130
0
  }
14131
0
  return false;
14132
0
}
14133
14134
0
bool url_aggregator::set_username(const std::string_view input) {
14135
0
  ada_log("url_aggregator::set_username '", input, "' ");
14136
0
  ADA_ASSERT_TRUE(validate());
14137
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14138
0
  if (cannot_have_credentials_or_port()) {
14139
0
    return false;
14140
0
  }
14141
0
  size_t idx = ada::unicode::percent_encode_index(
14142
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14143
0
  if (idx == input.size()) {
14144
0
    update_base_username(input);
14145
0
  } else {
14146
    // We only create a temporary string if we have to!
14147
0
    update_base_username(ada::unicode::percent_encode(
14148
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14149
0
  }
14150
0
  ADA_ASSERT_TRUE(validate());
14151
0
  return true;
14152
0
}
14153
14154
0
bool url_aggregator::set_password(const std::string_view input) {
14155
0
  ada_log("url_aggregator::set_password '", input, "'");
14156
0
  ADA_ASSERT_TRUE(validate());
14157
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14158
0
  if (cannot_have_credentials_or_port()) {
14159
0
    return false;
14160
0
  }
14161
0
  size_t idx = ada::unicode::percent_encode_index(
14162
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14163
0
  if (idx == input.size()) {
14164
0
    update_base_password(input);
14165
0
  } else {
14166
    // We only create a temporary string if we have to!
14167
0
    update_base_password(ada::unicode::percent_encode(
14168
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14169
0
  }
14170
0
  ADA_ASSERT_TRUE(validate());
14171
0
  return true;
14172
0
}
14173
14174
0
bool url_aggregator::set_port(const std::string_view input) {
14175
0
  ada_log("url_aggregator::set_port ", input);
14176
0
  ADA_ASSERT_TRUE(validate());
14177
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14178
0
  if (cannot_have_credentials_or_port()) {
14179
0
    return false;
14180
0
  }
14181
14182
0
  if (input.empty()) {
14183
0
    clear_port();
14184
0
    return true;
14185
0
  }
14186
14187
0
  std::string trimmed(input);
14188
0
  helpers::remove_ascii_tab_or_newline(trimmed);
14189
14190
0
  if (trimmed.empty()) {
14191
0
    return true;
14192
0
  }
14193
14194
  // Input should not start with a non-digit character.
14195
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14196
0
    return false;
14197
0
  }
14198
14199
  // Find the first non-digit character to determine the length of digits
14200
0
  auto first_non_digit =
14201
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14202
0
  std::string_view digits_to_parse =
14203
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14204
14205
  // Revert changes if parse_port fails.
14206
0
  uint32_t previous_port = components.port;
14207
0
  parse_port(digits_to_parse);
14208
0
  if (is_valid) {
14209
0
    return true;
14210
0
  }
14211
0
  update_base_port(previous_port);
14212
0
  is_valid = true;
14213
0
  ADA_ASSERT_TRUE(validate());
14214
0
  return false;
14215
0
}
14216
14217
0
bool url_aggregator::set_pathname(const std::string_view input) {
14218
0
  ada_log("url_aggregator::set_pathname ", input);
14219
0
  ADA_ASSERT_TRUE(validate());
14220
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14221
0
  if (has_opaque_path) {
14222
0
    return false;
14223
0
  }
14224
0
  clear_pathname();
14225
0
  parse_path(input);
14226
0
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14227
0
    buffer.insert(components.pathname_start, "/.");
14228
0
    components.pathname_start += 2;
14229
0
  }
14230
0
  ADA_ASSERT_TRUE(validate());
14231
0
  return true;
14232
0
}
14233
14234
0
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14235
0
  ada_log("url_aggregator::parse_path ", input);
14236
0
  ADA_ASSERT_TRUE(validate());
14237
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14238
0
  std::string tmp_buffer;
14239
0
  std::string_view internal_input;
14240
0
  if (unicode::has_tabs_or_newline(input)) {
14241
0
    tmp_buffer = input;
14242
    // Optimization opportunity: Instead of copying and then pruning, we could
14243
    // just directly build the string from user_input.
14244
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14245
0
    internal_input = tmp_buffer;
14246
0
  } else {
14247
0
    internal_input = input;
14248
0
  }
14249
14250
  // If url is special, then:
14251
0
  if (is_special()) {
14252
0
    if (internal_input.empty()) {
14253
0
      update_base_pathname("/");
14254
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14255
0
      consume_prepared_path(internal_input.substr(1));
14256
0
    } else {
14257
0
      consume_prepared_path(internal_input);
14258
0
    }
14259
0
  } else if (!internal_input.empty()) {
14260
0
    if (internal_input[0] == '/') {
14261
0
      consume_prepared_path(internal_input.substr(1));
14262
0
    } else {
14263
0
      consume_prepared_path(internal_input);
14264
0
    }
14265
0
  } else {
14266
    // Non-special URLs with an empty host can have their paths erased
14267
    // Path-only URLs cannot have their paths erased
14268
0
    if (components.host_start == components.host_end && !has_authority()) {
14269
0
      update_base_pathname("/");
14270
0
    }
14271
0
  }
14272
0
  ADA_ASSERT_TRUE(validate());
14273
0
}
14274
14275
0
void url_aggregator::set_search(const std::string_view input) {
14276
0
  ada_log("url_aggregator::set_search ", input);
14277
0
  ADA_ASSERT_TRUE(validate());
14278
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14279
0
  if (input.empty()) {
14280
0
    clear_search();
14281
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14282
0
    return;
14283
0
  }
14284
14285
0
  std::string new_value;
14286
0
  new_value = input[0] == '?' ? input.substr(1) : input;
14287
0
  helpers::remove_ascii_tab_or_newline(new_value);
14288
14289
0
  auto query_percent_encode_set =
14290
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14291
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14292
14293
0
  update_base_search(new_value, query_percent_encode_set);
14294
0
  ADA_ASSERT_TRUE(validate());
14295
0
}
14296
14297
0
void url_aggregator::set_hash(const std::string_view input) {
14298
0
  ada_log("url_aggregator::set_hash ", input);
14299
0
  ADA_ASSERT_TRUE(validate());
14300
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14301
0
  if (input.empty()) {
14302
0
    if (components.hash_start != url_components::omitted) {
14303
0
      buffer.resize(components.hash_start);
14304
0
      components.hash_start = url_components::omitted;
14305
0
    }
14306
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14307
0
    return;
14308
0
  }
14309
14310
0
  std::string new_value;
14311
0
  new_value = input[0] == '#' ? input.substr(1) : input;
14312
0
  helpers::remove_ascii_tab_or_newline(new_value);
14313
0
  update_unencoded_base_hash(new_value);
14314
0
  ADA_ASSERT_TRUE(validate());
14315
0
}
14316
14317
0
bool url_aggregator::set_href(const std::string_view input) {
14318
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14319
0
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14320
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14321
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
14322
14323
0
  if (out) {
14324
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14325
    // TODO: Figure out why the following line puts test to never finish.
14326
0
    *this = *out;
14327
0
  }
14328
14329
0
  return out.has_value();
14330
0
}
14331
14332
0
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14333
0
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14334
0
          " bytes]");
14335
0
  ADA_ASSERT_TRUE(validate());
14336
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14337
0
  if (input.empty()) {
14338
0
    return is_valid = false;
14339
0
  }  // technically unnecessary.
14340
  // If input starts with U+005B ([), then:
14341
0
  if (input[0] == '[') {
14342
    // If input does not end with U+005D (]), validation error, return failure.
14343
0
    if (input.back() != ']') {
14344
0
      return is_valid = false;
14345
0
    }
14346
0
    ada_log("parse_host ipv6");
14347
14348
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14349
    // trailing U+005D (]) removed.
14350
0
    input.remove_prefix(1);
14351
0
    input.remove_suffix(1);
14352
0
    return parse_ipv6(input);
14353
0
  }
14354
14355
  // If isNotSpecial is true, then return the result of opaque-host parsing
14356
  // input.
14357
0
  if (!is_special()) {
14358
0
    return parse_opaque_host(input);
14359
0
  }
14360
  // Let domain be the result of running UTF-8 decode without BOM on the
14361
  // percent-decoding of input. Let asciiDomain be the result of running domain
14362
  // to ASCII with domain and false. The most common case is an ASCII input, in
14363
  // which case we do not need to call the expensive 'to_ascii' if a few
14364
  // conditions are met: no '%' and no 'xn-' subsequence.
14365
14366
  // Often, the input does not contain any forbidden code points, and no upper
14367
  // case ASCII letter, then we can just copy it to the buffer. We want to
14368
  // optimize for such a common case.
14369
0
  uint8_t is_forbidden_or_upper =
14370
0
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14371
0
                                                             input.size());
14372
  // Minor optimization opportunity:
14373
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
14374
  // the presence of characters that cannot appear in the ipv4 address and we
14375
  // could also check whether x and n and - are present, and so we could skip
14376
  // some of the checks below. However, the gains are likely to be small, and
14377
  // the code would be more complex.
14378
0
  if (is_forbidden_or_upper == 0 &&
14379
0
      input.find("xn-") == std::string_view::npos) {
14380
    // fast path
14381
0
    update_base_hostname(input);
14382
0
    if (checkers::is_ipv4(get_hostname())) {
14383
0
      ada_log("parse_host fast path ipv4");
14384
0
      return parse_ipv4(get_hostname(), true);
14385
0
    }
14386
0
    ada_log("parse_host fast path ", get_hostname());
14387
0
    return true;
14388
0
  }
14389
  // We have encountered at least one forbidden code point or the input contains
14390
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14391
  // conversion.
14392
14393
0
  ada_log("parse_host calling to_ascii");
14394
0
  std::optional<std::string> host = std::string(get_hostname());
14395
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14396
0
  if (!is_valid) {
14397
0
    ada_log("parse_host to_ascii returns false");
14398
0
    return is_valid = false;
14399
0
  }
14400
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14401
0
          " bytes]");
14402
14403
0
  if (std::ranges::any_of(host.value(),
14404
0
                          ada::unicode::is_forbidden_domain_code_point)) {
14405
0
    return is_valid = false;
14406
0
  }
14407
14408
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14409
  // asciiDomain.
14410
0
  if (checkers::is_ipv4(host.value())) {
14411
0
    ada_log("parse_host got ipv4 ", *host);
14412
0
    return parse_ipv4(host.value(), false);
14413
0
  }
14414
14415
0
  update_base_hostname(host.value());
14416
0
  ADA_ASSERT_TRUE(validate());
14417
0
  return true;
14418
0
}
14419
14420
template <bool override_hostname>
14421
0
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14422
0
  ada_log("url_aggregator::set_host_or_hostname ", input);
14423
0
  ADA_ASSERT_TRUE(validate());
14424
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14425
0
  if (has_opaque_path) {
14426
0
    return false;
14427
0
  }
14428
14429
0
  std::string previous_host(get_hostname());
14430
0
  uint32_t previous_port = components.port;
14431
14432
0
  size_t host_end_pos = input.find('#');
14433
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
14434
0
                                      ? host_end_pos
14435
0
                                      : input.size());
14436
0
  helpers::remove_ascii_tab_or_newline(_host);
14437
0
  std::string_view new_host(_host);
14438
14439
  // If url's scheme is "file", then set state to file host state, instead of
14440
  // host state.
14441
0
  if (type != ada::scheme::type::FILE) {
14442
0
    std::string_view host_view(_host.data(), _host.length());
14443
0
    auto [location, found_colon] =
14444
0
        helpers::get_host_delimiter_location(is_special(), host_view);
14445
14446
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14447
    // Note: the 'found_colon' value is true if and only if a colon was
14448
    // encountered while not inside brackets.
14449
0
    if (found_colon) {
14450
      // If buffer is the empty string, host-missing validation error, return
14451
      // failure.
14452
0
      std::string_view host_buffer = host_view.substr(0, location);
14453
0
      if (host_buffer.empty()) {
14454
0
        return false;
14455
0
      }
14456
14457
      // If state override is given and state override is hostname state, then
14458
      // return failure.
14459
0
      if constexpr (override_hostname) {
14460
0
        return false;
14461
0
      }
14462
14463
      // Let host be the result of host parsing buffer with url is not special.
14464
0
      bool succeeded = parse_host(host_buffer);
14465
0
      if (!succeeded) {
14466
0
        update_base_hostname(previous_host);
14467
0
        update_base_port(previous_port);
14468
0
        return false;
14469
0
      }
14470
14471
      // Set url's host to host, buffer to the empty string, and state to port
14472
      // state.
14473
0
      std::string_view port_buffer = new_host.substr(location + 1);
14474
0
      if (!port_buffer.empty()) {
14475
0
        set_port(port_buffer);
14476
0
      }
14477
0
      return true;
14478
0
    }
14479
    // Otherwise, if one of the following is true:
14480
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14481
    // - url is special and c is U+005C (\)
14482
0
    else {
14483
      // If url is special and host_view is the empty string, host-missing
14484
      // validation error, return failure.
14485
0
      if (host_view.empty() && is_special()) {
14486
0
        return false;
14487
0
      }
14488
14489
      // Otherwise, if state override is given, host_view is the empty string,
14490
      // and either url includes credentials or url's port is non-null, then
14491
      // return failure.
14492
0
      if (host_view.empty() && (has_credentials() || has_port())) {
14493
0
        return false;
14494
0
      }
14495
14496
      // Let host be the result of host parsing host_view with url is not
14497
      // special.
14498
0
      if (host_view.empty() && !is_special()) {
14499
0
        if (has_hostname()) {
14500
0
          clear_hostname();  // easy!
14501
0
        } else if (has_dash_dot()) {
14502
0
          add_authority_slashes_if_needed();
14503
0
          delete_dash_dot();
14504
0
        }
14505
0
        return true;
14506
0
      }
14507
14508
0
      bool succeeded = parse_host(host_view);
14509
0
      if (!succeeded) {
14510
0
        update_base_hostname(previous_host);
14511
0
        update_base_port(previous_port);
14512
0
        return false;
14513
0
      } else if (has_dash_dot()) {
14514
        // Should remove dash_dot from pathname
14515
0
        delete_dash_dot();
14516
0
      }
14517
0
      return true;
14518
0
    }
14519
0
  }
14520
14521
0
  size_t location = new_host.find_first_of("/\\?");
14522
0
  if (location != std::string_view::npos) {
14523
0
    new_host.remove_suffix(new_host.length() - location);
14524
0
  }
14525
14526
0
  if (new_host.empty()) {
14527
    // Set url's host to the empty string.
14528
0
    clear_hostname();
14529
0
  } else {
14530
    // Let host be the result of host parsing buffer with url is not special.
14531
0
    if (!parse_host(new_host)) {
14532
0
      update_base_hostname(previous_host);
14533
0
      update_base_port(previous_port);
14534
0
      return false;
14535
0
    }
14536
14537
    // If host is "localhost", then set host to the empty string.
14538
0
    if (helpers::substring(buffer, components.host_start,
14539
0
                           components.host_end) == "localhost") {
14540
0
      clear_hostname();
14541
0
    }
14542
0
  }
14543
0
  ADA_ASSERT_TRUE(validate());
14544
0
  return true;
14545
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> >)
14546
14547
0
bool url_aggregator::set_host(const std::string_view input) {
14548
0
  ada_log("url_aggregator::set_host '", input, "'");
14549
0
  ADA_ASSERT_TRUE(validate());
14550
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14551
0
  return set_host_or_hostname<false>(input);
14552
0
}
14553
14554
0
bool url_aggregator::set_hostname(const std::string_view input) {
14555
0
  ada_log("url_aggregator::set_hostname '", input, "'");
14556
0
  ADA_ASSERT_TRUE(validate());
14557
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14558
0
  return set_host_or_hostname<true>(input);
14559
0
}
14560
14561
0
[[nodiscard]] std::string url_aggregator::get_origin() const noexcept {
14562
0
  ada_log("url_aggregator::get_origin");
14563
0
  if (is_special()) {
14564
    // Return a new opaque origin.
14565
0
    if (type == scheme::FILE) {
14566
0
      return "null";
14567
0
    }
14568
14569
0
    return helpers::concat(get_protocol(), "//", get_host());
14570
0
  }
14571
14572
0
  if (get_protocol() == "blob:") {
14573
0
    std::string_view path = get_pathname();
14574
0
    if (!path.empty()) {
14575
0
      auto out = ada::parse<ada::url_aggregator>(path);
14576
0
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14577
        // If pathURL's scheme is not "http" and not "https", then return a
14578
        // new opaque origin.
14579
0
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14580
0
      }
14581
0
    }
14582
0
  }
14583
14584
  // Return a new opaque origin.
14585
0
  return "null";
14586
0
}
14587
14588
[[nodiscard]] std::string_view url_aggregator::get_username() const noexcept
14589
0
    ada_lifetime_bound {
14590
0
  ada_log("url_aggregator::get_username");
14591
0
  if (has_non_empty_username()) {
14592
0
    return helpers::substring(buffer, components.protocol_end + 2,
14593
0
                              components.username_end);
14594
0
  }
14595
0
  return "";
14596
0
}
14597
14598
[[nodiscard]] std::string_view url_aggregator::get_password() const noexcept
14599
0
    ada_lifetime_bound {
14600
0
  ada_log("url_aggregator::get_password");
14601
0
  if (has_non_empty_password()) {
14602
0
    return helpers::substring(buffer, components.username_end + 1,
14603
0
                              components.host_start);
14604
0
  }
14605
0
  return "";
14606
0
}
14607
14608
[[nodiscard]] std::string_view url_aggregator::get_port() const noexcept
14609
0
    ada_lifetime_bound {
14610
0
  ada_log("url_aggregator::get_port");
14611
0
  if (components.port == url_components::omitted) {
14612
0
    return "";
14613
0
  }
14614
0
  return helpers::substring(buffer, components.host_end + 1,
14615
0
                            components.pathname_start);
14616
0
}
14617
14618
[[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept
14619
0
    ada_lifetime_bound {
14620
0
  ada_log("url_aggregator::get_hash");
14621
  // If this's URL's fragment is either null or the empty string, then return
14622
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14623
0
  if (components.hash_start == url_components::omitted) {
14624
0
    return "";
14625
0
  }
14626
0
  if (buffer.size() - components.hash_start <= 1) {
14627
0
    return "";
14628
0
  }
14629
0
  return helpers::substring(buffer, components.hash_start);
14630
0
}
14631
14632
[[nodiscard]] std::string_view url_aggregator::get_host() const noexcept
14633
0
    ada_lifetime_bound {
14634
0
  ada_log("url_aggregator::get_host");
14635
  // Technically, we should check if there is a hostname, but
14636
  // the code below works even if there isn't.
14637
  // if(!has_hostname()) { return ""; }
14638
0
  size_t start = components.host_start;
14639
0
  if (components.host_end > components.host_start &&
14640
0
      buffer[components.host_start] == '@') {
14641
0
    start++;
14642
0
  }
14643
  // if we have an empty host, then the space between components.host_end and
14644
  // components.pathname_start may be occupied by /.
14645
0
  if (start == components.host_end) {
14646
0
    return {};
14647
0
  }
14648
0
  return helpers::substring(buffer, start, components.pathname_start);
14649
0
}
14650
14651
[[nodiscard]] std::string_view url_aggregator::get_hostname() const noexcept
14652
0
    ada_lifetime_bound {
14653
0
  ada_log("url_aggregator::get_hostname");
14654
  // Technically, we should check if there is a hostname, but
14655
  // the code below works even if there isn't.
14656
  // if(!has_hostname()) { return ""; }
14657
0
  size_t start = components.host_start;
14658
  // So host_start is not where the host begins.
14659
0
  if (components.host_end > components.host_start &&
14660
0
      buffer[components.host_start] == '@') {
14661
0
    start++;
14662
0
  }
14663
0
  return helpers::substring(buffer, start, components.host_end);
14664
0
}
14665
14666
[[nodiscard]] std::string_view url_aggregator::get_search() const noexcept
14667
0
    ada_lifetime_bound {
14668
0
  ada_log("url_aggregator::get_search");
14669
  // If this's URL's query is either null or the empty string, then return the
14670
  // empty string. Return U+003F (?), followed by this's URL's query.
14671
0
  if (components.search_start == url_components::omitted) {
14672
0
    return "";
14673
0
  }
14674
0
  auto ending_index = uint32_t(buffer.size());
14675
0
  if (components.hash_start != url_components::omitted) {
14676
0
    ending_index = components.hash_start;
14677
0
  }
14678
0
  if (ending_index - components.search_start <= 1) {
14679
0
    return "";
14680
0
  }
14681
0
  return helpers::substring(buffer, components.search_start, ending_index);
14682
0
}
14683
14684
[[nodiscard]] std::string_view url_aggregator::get_protocol() const noexcept
14685
0
    ada_lifetime_bound {
14686
0
  ada_log("url_aggregator::get_protocol");
14687
0
  return helpers::substring(buffer, 0, components.protocol_end);
14688
0
}
14689
14690
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14691
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14692
0
          " bytes]");
14693
0
  if (!is_valid) {
14694
0
    return "null";
14695
0
  }
14696
14697
0
  std::string answer;
14698
0
  auto back = std::back_insert_iterator(answer);
14699
0
  answer.append("{\n");
14700
14701
0
  answer.append("\t\"buffer\":\"");
14702
0
  helpers::encode_json(buffer, back);
14703
0
  answer.append("\",\n");
14704
14705
0
  answer.append("\t\"protocol\":\"");
14706
0
  helpers::encode_json(get_protocol(), back);
14707
0
  answer.append("\",\n");
14708
14709
0
  if (has_credentials()) {
14710
0
    answer.append("\t\"username\":\"");
14711
0
    helpers::encode_json(get_username(), back);
14712
0
    answer.append("\",\n");
14713
0
    answer.append("\t\"password\":\"");
14714
0
    helpers::encode_json(get_password(), back);
14715
0
    answer.append("\",\n");
14716
0
  }
14717
14718
0
  answer.append("\t\"host\":\"");
14719
0
  helpers::encode_json(get_host(), back);
14720
0
  answer.append("\",\n");
14721
14722
0
  answer.append("\t\"path\":\"");
14723
0
  helpers::encode_json(get_pathname(), back);
14724
0
  answer.append("\",\n");
14725
0
  answer.append("\t\"opaque path\":");
14726
0
  answer.append((has_opaque_path ? "true" : "false"));
14727
0
  answer.append(",\n");
14728
14729
0
  if (components.search_start != url_components::omitted) {
14730
0
    answer.append("\t\"query\":\"");
14731
0
    helpers::encode_json(get_search(), back);
14732
0
    answer.append("\",\n");
14733
0
  }
14734
0
  if (components.hash_start != url_components::omitted) {
14735
0
    answer.append("\t\"fragment\":\"");
14736
0
    helpers::encode_json(get_hash(), back);
14737
0
    answer.append("\",\n");
14738
0
  }
14739
14740
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
14741
0
    if (offset == url_components::omitted) {
14742
0
      return "null";
14743
0
    } else {
14744
0
      return std::to_string(offset);
14745
0
    }
14746
0
  };
14747
14748
0
  answer.append("\t\"protocol_end\":");
14749
0
  answer.append(convert_offset_to_string(components.protocol_end));
14750
0
  answer.append(",\n");
14751
14752
0
  answer.append("\t\"username_end\":");
14753
0
  answer.append(convert_offset_to_string(components.username_end));
14754
0
  answer.append(",\n");
14755
14756
0
  answer.append("\t\"host_start\":");
14757
0
  answer.append(convert_offset_to_string(components.host_start));
14758
0
  answer.append(",\n");
14759
14760
0
  answer.append("\t\"host_end\":");
14761
0
  answer.append(convert_offset_to_string(components.host_end));
14762
0
  answer.append(",\n");
14763
14764
0
  answer.append("\t\"port\":");
14765
0
  answer.append(convert_offset_to_string(components.port));
14766
0
  answer.append(",\n");
14767
14768
0
  answer.append("\t\"pathname_start\":");
14769
0
  answer.append(convert_offset_to_string(components.pathname_start));
14770
0
  answer.append(",\n");
14771
14772
0
  answer.append("\t\"search_start\":");
14773
0
  answer.append(convert_offset_to_string(components.search_start));
14774
0
  answer.append(",\n");
14775
14776
0
  answer.append("\t\"hash_start\":");
14777
0
  answer.append(convert_offset_to_string(components.hash_start));
14778
0
  answer.append("\n}");
14779
14780
0
  return answer;
14781
0
}
14782
14783
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
14784
0
  if (components.host_start == components.host_end) {
14785
0
    return false;
14786
0
  }
14787
0
  return checkers::verify_dns_length(get_hostname());
14788
0
}
14789
14790
0
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
14791
0
  ada_log("parse_ipv4 ", input, " [", input.size(),
14792
0
          " bytes], overlaps with buffer: ",
14793
0
          helpers::overlaps(input, buffer) ? "yes" : "no");
14794
0
  ADA_ASSERT_TRUE(validate());
14795
0
  const bool trailing_dot = (input.back() == '.');
14796
0
  if (trailing_dot) {
14797
0
    input.remove_suffix(1);
14798
0
  }
14799
0
  size_t digit_count{0};
14800
0
  int pure_decimal_count = 0;  // entries that are decimal
14801
0
  uint64_t ipv4{0};
14802
  // we could unroll for better performance?
14803
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
14804
0
    uint32_t
14805
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
14806
0
    bool is_hex = checkers::has_hex_prefix(input);
14807
0
    if (is_hex && ((input.length() == 2) ||
14808
0
                   ((input.length() > 2) && (input[2] == '.')))) {
14809
      // special case
14810
0
      segment_result = 0;
14811
0
      input.remove_prefix(2);
14812
0
    } else {
14813
0
      std::from_chars_result r{};
14814
0
      if (is_hex) {
14815
0
        ada_log("parse_ipv4 trying to parse hex number");
14816
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
14817
0
                            segment_result, 16);
14818
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
14819
0
                 checkers::is_digit(input[1])) {
14820
0
        ada_log("parse_ipv4 trying to parse octal number");
14821
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
14822
0
                            segment_result, 8);
14823
0
      } else {
14824
0
        ada_log("parse_ipv4 trying to parse decimal number");
14825
0
        pure_decimal_count++;
14826
0
        r = std::from_chars(input.data(), input.data() + input.size(),
14827
0
                            segment_result, 10);
14828
0
      }
14829
0
      if (r.ec != std::errc()) {
14830
0
        ada_log("parse_ipv4 parsing failed");
14831
0
        return is_valid = false;
14832
0
      }
14833
0
      ada_log("parse_ipv4 parsed ", segment_result);
14834
0
      input.remove_prefix(r.ptr - input.data());
14835
0
    }
14836
0
    if (input.empty()) {
14837
      // We have the last value.
14838
      // At this stage, ipv4 contains digit_count*8 bits.
14839
      // So we have 32-digit_count*8 bits left.
14840
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
14841
0
        return is_valid = false;
14842
0
      }
14843
0
      ipv4 <<= (32 - digit_count * 8);
14844
0
      ipv4 |= segment_result;
14845
0
      goto final;
14846
0
    } else {
14847
      // There is more, so that the value must no be larger than 255
14848
      // and we must have a '.'.
14849
0
      if ((segment_result > 255) || (input[0] != '.')) {
14850
0
        return is_valid = false;
14851
0
      }
14852
0
      ipv4 <<= 8;
14853
0
      ipv4 |= segment_result;
14854
0
      input.remove_prefix(1);  // remove '.'
14855
0
    }
14856
0
  }
14857
0
  if ((digit_count != 4) || (!input.empty())) {
14858
0
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
14859
0
    return is_valid = false;
14860
0
  }
14861
0
final:
14862
0
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
14863
0
          " host: ", get_host());
14864
14865
  // We could also check r.ptr to see where the parsing ended.
14866
0
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
14867
0
    ada_log(
14868
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
14869
0
        "buffer");
14870
    // The original input was already all decimal and we validated it. So we
14871
    // don't need to do anything.
14872
0
  } else {
14873
0
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
14874
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
14875
    // serializer.
14876
    // TODO: This is likely a bug because it goes back update_base_hostname, not
14877
    // what we want to do.
14878
0
    update_base_hostname(
14879
0
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
14880
0
  }
14881
0
  host_type = IPV4;
14882
0
  ADA_ASSERT_TRUE(validate());
14883
0
  return true;
14884
0
}
14885
14886
0
bool url_aggregator::parse_ipv6(std::string_view input) {
14887
  // TODO: Implement in_place optimization: we know that input points
14888
  // in the buffer, so we can just check whether the buffer is already
14889
  // well formatted.
14890
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
14891
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
14892
0
  ADA_ASSERT_TRUE(validate());
14893
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14894
0
  if (input.empty()) {
14895
0
    return is_valid = false;
14896
0
  }
14897
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
14898
0
  std::array<uint16_t, 8> address{};
14899
14900
  // Let pieceIndex be 0.
14901
0
  int piece_index = 0;
14902
14903
  // Let compress be null.
14904
0
  std::optional<int> compress{};
14905
14906
  // Let pointer be a pointer for input.
14907
0
  std::string_view::iterator pointer = input.begin();
14908
14909
  // If c is U+003A (:), then:
14910
0
  if (input[0] == ':') {
14911
    // If remaining does not start with U+003A (:), validation error, return
14912
    // failure.
14913
0
    if (input.size() == 1 || input[1] != ':') {
14914
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
14915
0
      return is_valid = false;
14916
0
    }
14917
14918
    // Increase pointer by 2.
14919
0
    pointer += 2;
14920
14921
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
14922
0
    compress = ++piece_index;
14923
0
  }
14924
14925
  // While c is not the EOF code point:
14926
0
  while (pointer != input.end()) {
14927
    // If pieceIndex is 8, validation error, return failure.
14928
0
    if (piece_index == 8) {
14929
0
      ada_log("parse_ipv6 piece_index == 8");
14930
0
      return is_valid = false;
14931
0
    }
14932
14933
    // If c is U+003A (:), then:
14934
0
    if (*pointer == ':') {
14935
      // If compress is non-null, validation error, return failure.
14936
0
      if (compress.has_value()) {
14937
0
        ada_log("parse_ipv6 compress is non-null");
14938
0
        return is_valid = false;
14939
0
      }
14940
14941
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
14942
      // then continue.
14943
0
      pointer++;
14944
0
      compress = ++piece_index;
14945
0
      continue;
14946
0
    }
14947
14948
    // Let value and length be 0.
14949
0
    uint16_t value = 0, length = 0;
14950
14951
    // While length is less than 4 and c is an ASCII hex digit,
14952
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
14953
    // increase pointer and length by 1.
14954
0
    while (length < 4 && pointer != input.end() &&
14955
0
           unicode::is_ascii_hex_digit(*pointer)) {
14956
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
14957
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
14958
0
      pointer++;
14959
0
      length++;
14960
0
    }
14961
14962
    // If c is U+002E (.), then:
14963
0
    if (pointer != input.end() && *pointer == '.') {
14964
      // If length is 0, validation error, return failure.
14965
0
      if (length == 0) {
14966
0
        ada_log("parse_ipv6 length is 0");
14967
0
        return is_valid = false;
14968
0
      }
14969
14970
      // Decrease pointer by length.
14971
0
      pointer -= length;
14972
14973
      // If pieceIndex is greater than 6, validation error, return failure.
14974
0
      if (piece_index > 6) {
14975
0
        ada_log("parse_ipv6 piece_index > 6");
14976
0
        return is_valid = false;
14977
0
      }
14978
14979
      // Let numbersSeen be 0.
14980
0
      int numbers_seen = 0;
14981
14982
      // While c is not the EOF code point:
14983
0
      while (pointer != input.end()) {
14984
        // Let ipv4Piece be null.
14985
0
        std::optional<uint16_t> ipv4_piece{};
14986
14987
        // If numbersSeen is greater than 0, then:
14988
0
        if (numbers_seen > 0) {
14989
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
14990
          // pointer by 1.
14991
0
          if (*pointer == '.' && numbers_seen < 4) {
14992
0
            pointer++;
14993
0
          } else {
14994
            // Otherwise, validation error, return failure.
14995
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
14996
0
            return is_valid = false;
14997
0
          }
14998
0
        }
14999
15000
        // If c is not an ASCII digit, validation error, return failure.
15001
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15002
0
          ada_log(
15003
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15004
0
              "failure");
15005
0
          return is_valid = false;
15006
0
        }
15007
15008
        // While c is an ASCII digit:
15009
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15010
          // Let number be c interpreted as decimal number.
15011
0
          int number = *pointer - '0';
15012
15013
          // If ipv4Piece is null, then set ipv4Piece to number.
15014
0
          if (!ipv4_piece.has_value()) {
15015
0
            ipv4_piece = number;
15016
0
          }
15017
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15018
0
          else if (ipv4_piece == 0) {
15019
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15020
0
            return is_valid = false;
15021
0
          }
15022
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15023
0
          else {
15024
0
            ipv4_piece = *ipv4_piece * 10 + number;
15025
0
          }
15026
15027
          // If ipv4Piece is greater than 255, validation error, return failure.
15028
0
          if (ipv4_piece > 255) {
15029
0
            ada_log("parse_ipv6 ipv4_piece > 255");
15030
0
            return is_valid = false;
15031
0
          }
15032
15033
          // Increase pointer by 1.
15034
0
          pointer++;
15035
0
        }
15036
15037
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15038
        // ipv4Piece.
15039
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15040
0
        address[piece_index] =
15041
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15042
15043
        // Increase numbersSeen by 1.
15044
0
        numbers_seen++;
15045
15046
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15047
0
        if (numbers_seen == 2 || numbers_seen == 4) {
15048
0
          piece_index++;
15049
0
        }
15050
0
      }
15051
15052
      // If numbersSeen is not 4, validation error, return failure.
15053
0
      if (numbers_seen != 4) {
15054
0
        return is_valid = false;
15055
0
      }
15056
15057
      // Break.
15058
0
      break;
15059
0
    }
15060
    // Otherwise, if c is U+003A (:):
15061
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
15062
      // Increase pointer by 1.
15063
0
      pointer++;
15064
15065
      // If c is the EOF code point, validation error, return failure.
15066
0
      if (pointer == input.end()) {
15067
0
        ada_log(
15068
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
15069
0
            "failure");
15070
0
        return is_valid = false;
15071
0
      }
15072
0
    }
15073
    // Otherwise, if c is not the EOF code point, validation error, return
15074
    // failure.
15075
0
    else if (pointer != input.end()) {
15076
0
      ada_log(
15077
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15078
0
          "error, return failure");
15079
0
      return is_valid = false;
15080
0
    }
15081
15082
    // Set address[pieceIndex] to value.
15083
0
    address[piece_index] = value;
15084
15085
    // Increase pieceIndex by 1.
15086
0
    piece_index++;
15087
0
  }
15088
15089
  // If compress is non-null, then:
15090
0
  if (compress.has_value()) {
15091
    // Let swaps be pieceIndex - compress.
15092
0
    int swaps = piece_index - *compress;
15093
15094
    // Set pieceIndex to 7.
15095
0
    piece_index = 7;
15096
15097
    // While pieceIndex is not 0 and swaps is greater than 0,
15098
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15099
    // decrease both pieceIndex and swaps by 1.
15100
0
    while (piece_index != 0 && swaps > 0) {
15101
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15102
0
      piece_index--;
15103
0
      swaps--;
15104
0
    }
15105
0
  }
15106
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15107
  // return failure.
15108
0
  else if (piece_index != 8) {
15109
0
    ada_log(
15110
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15111
0
        "error, return failure");
15112
0
    return is_valid = false;
15113
0
  }
15114
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15115
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15116
  // what we want to do.
15117
0
  update_base_hostname(ada::serializers::ipv6(address));
15118
0
  ada_log("parse_ipv6 ", get_hostname());
15119
0
  ADA_ASSERT_TRUE(validate());
15120
0
  host_type = IPV6;
15121
0
  return true;
15122
0
}
15123
15124
0
bool url_aggregator::parse_opaque_host(std::string_view input) {
15125
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15126
0
  ADA_ASSERT_TRUE(validate());
15127
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15128
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15129
0
    return is_valid = false;
15130
0
  }
15131
15132
  // Return the result of running UTF-8 percent-encode on input using the C0
15133
  // control percent-encode set.
15134
0
  size_t idx = ada::unicode::percent_encode_index(
15135
0
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15136
0
  if (idx == input.size()) {
15137
0
    update_base_hostname(input);
15138
0
  } else {
15139
    // We only create a temporary string if we need to.
15140
0
    update_base_hostname(ada::unicode::percent_encode(
15141
0
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15142
0
  }
15143
0
  ADA_ASSERT_TRUE(validate());
15144
0
  return true;
15145
0
}
15146
15147
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15148
0
  if (!is_valid) {
15149
0
    return "invalid";
15150
0
  }
15151
0
  std::string answer;
15152
0
  answer.append(buffer);
15153
0
  answer.append(" [");
15154
0
  answer.append(std::to_string(buffer.size()));
15155
0
  answer.append(" bytes]");
15156
0
  answer.append("\n");
15157
  // first line
15158
0
  std::string line1;
15159
0
  line1.resize(buffer.size(), ' ');
15160
0
  if (components.hash_start != url_components::omitted) {
15161
0
    line1[components.hash_start] = '|';
15162
0
  }
15163
0
  if (components.search_start != url_components::omitted) {
15164
0
    line1[components.search_start] = '|';
15165
0
  }
15166
0
  if (components.pathname_start != buffer.size()) {
15167
0
    line1[components.pathname_start] = '|';
15168
0
  }
15169
0
  if (components.host_end != buffer.size()) {
15170
0
    line1[components.host_end] = '|';
15171
0
  }
15172
0
  if (components.host_start != buffer.size()) {
15173
0
    line1[components.host_start] = '|';
15174
0
  }
15175
0
  if (components.username_end != buffer.size()) {
15176
0
    line1[components.username_end] = '|';
15177
0
  }
15178
0
  if (components.protocol_end != buffer.size()) {
15179
0
    line1[components.protocol_end] = '|';
15180
0
  }
15181
0
  answer.append(line1);
15182
0
  answer.append("\n");
15183
15184
0
  std::string line2 = line1;
15185
0
  if (components.hash_start != url_components::omitted) {
15186
0
    line2[components.hash_start] = '`';
15187
0
    line1[components.hash_start] = ' ';
15188
15189
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15190
0
      line2[i] = '-';
15191
0
    }
15192
0
    line2.append(" hash_start");
15193
0
    answer.append(line2);
15194
0
    answer.append("\n");
15195
0
  }
15196
15197
0
  std::string line3 = line1;
15198
0
  if (components.search_start != url_components::omitted) {
15199
0
    line3[components.search_start] = '`';
15200
0
    line1[components.search_start] = ' ';
15201
15202
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15203
0
      line3[i] = '-';
15204
0
    }
15205
0
    line3.append(" search_start ");
15206
0
    line3.append(std::to_string(components.search_start));
15207
0
    answer.append(line3);
15208
0
    answer.append("\n");
15209
0
  }
15210
15211
0
  std::string line4 = line1;
15212
0
  if (components.pathname_start != buffer.size()) {
15213
0
    line4[components.pathname_start] = '`';
15214
0
    line1[components.pathname_start] = ' ';
15215
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15216
0
      line4[i] = '-';
15217
0
    }
15218
0
    line4.append(" pathname_start ");
15219
0
    line4.append(std::to_string(components.pathname_start));
15220
0
    answer.append(line4);
15221
0
    answer.append("\n");
15222
0
  }
15223
15224
0
  std::string line5 = line1;
15225
0
  if (components.host_end != buffer.size()) {
15226
0
    line5[components.host_end] = '`';
15227
0
    line1[components.host_end] = ' ';
15228
15229
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15230
0
      line5[i] = '-';
15231
0
    }
15232
0
    line5.append(" host_end ");
15233
0
    line5.append(std::to_string(components.host_end));
15234
0
    answer.append(line5);
15235
0
    answer.append("\n");
15236
0
  }
15237
15238
0
  std::string line6 = line1;
15239
0
  if (components.host_start != buffer.size()) {
15240
0
    line6[components.host_start] = '`';
15241
0
    line1[components.host_start] = ' ';
15242
15243
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15244
0
      line6[i] = '-';
15245
0
    }
15246
0
    line6.append(" host_start ");
15247
0
    line6.append(std::to_string(components.host_start));
15248
0
    answer.append(line6);
15249
0
    answer.append("\n");
15250
0
  }
15251
15252
0
  std::string line7 = line1;
15253
0
  if (components.username_end != buffer.size()) {
15254
0
    line7[components.username_end] = '`';
15255
0
    line1[components.username_end] = ' ';
15256
15257
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15258
0
      line7[i] = '-';
15259
0
    }
15260
0
    line7.append(" username_end ");
15261
0
    line7.append(std::to_string(components.username_end));
15262
0
    answer.append(line7);
15263
0
    answer.append("\n");
15264
0
  }
15265
15266
0
  std::string line8 = line1;
15267
0
  if (components.protocol_end != buffer.size()) {
15268
0
    line8[components.protocol_end] = '`';
15269
0
    line1[components.protocol_end] = ' ';
15270
15271
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15272
0
      line8[i] = '-';
15273
0
    }
15274
0
    line8.append(" protocol_end ");
15275
0
    line8.append(std::to_string(components.protocol_end));
15276
0
    answer.append(line8);
15277
0
    answer.append("\n");
15278
0
  }
15279
15280
0
  if (components.hash_start == url_components::omitted) {
15281
0
    answer.append("note: hash omitted\n");
15282
0
  }
15283
0
  if (components.search_start == url_components::omitted) {
15284
0
    answer.append("note: search omitted\n");
15285
0
  }
15286
0
  if (components.protocol_end > buffer.size()) {
15287
0
    answer.append("warning: protocol_end overflows\n");
15288
0
  }
15289
0
  if (components.username_end > buffer.size()) {
15290
0
    answer.append("warning: username_end overflows\n");
15291
0
  }
15292
0
  if (components.host_start > buffer.size()) {
15293
0
    answer.append("warning: host_start overflows\n");
15294
0
  }
15295
0
  if (components.host_end > buffer.size()) {
15296
0
    answer.append("warning: host_end overflows\n");
15297
0
  }
15298
0
  if (components.pathname_start > buffer.size()) {
15299
0
    answer.append("warning: pathname_start overflows\n");
15300
0
  }
15301
0
  return answer;
15302
0
}
15303
15304
0
void url_aggregator::delete_dash_dot() {
15305
0
  ada_log("url_aggregator::delete_dash_dot");
15306
0
  ADA_ASSERT_TRUE(validate());
15307
0
  ADA_ASSERT_TRUE(has_dash_dot());
15308
0
  buffer.erase(components.host_end, 2);
15309
0
  components.pathname_start -= 2;
15310
0
  if (components.search_start != url_components::omitted) {
15311
0
    components.search_start -= 2;
15312
0
  }
15313
0
  if (components.hash_start != url_components::omitted) {
15314
0
    components.hash_start -= 2;
15315
0
  }
15316
0
  ADA_ASSERT_TRUE(validate());
15317
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15318
0
}
15319
15320
0
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15321
0
  ada_log("url_aggregator::consume_prepared_path ", input);
15322
  /***
15323
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15324
   * unfortunate. This particular function is nearly identical, except that it
15325
   * is a method on url_aggregator. The idea is that the trivial path (which is
15326
   * very common) merely appends to the buffer. This is the same trivial path as
15327
   * with helpers::parse_prepared_path, except that we have the additional check
15328
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15329
   * modify it, and then insert it back into the buffer.
15330
   */
15331
0
  uint8_t accumulator = checkers::path_signature(input);
15332
  // Let us first detect a trivial case.
15333
  // If it is special, we check that we have no dot, no %,  no \ and no
15334
  // character needing percent encoding. Otherwise, we check that we have no %,
15335
  // no dot, and no character needing percent encoding.
15336
0
  constexpr uint8_t need_encoding = 1;
15337
0
  constexpr uint8_t backslash_char = 2;
15338
0
  constexpr uint8_t dot_char = 4;
15339
0
  constexpr uint8_t percent_char = 8;
15340
0
  bool special = type != ada::scheme::NOT_SPECIAL;
15341
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15342
0
                                      checkers::is_windows_drive_letter(input));
15343
0
  bool trivial_path =
15344
0
      (special ? (accumulator == 0)
15345
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15346
0
                  0)) &&
15347
0
      (!may_need_slow_file_handling);
15348
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15349
    // '4' means that we have at least one dot, but nothing that requires
15350
    // percent encoding or decoding. The only part that is not trivial is
15351
    // that we may have single dots and double dots path segments.
15352
    // If we have such segments, then we either have a path that begins
15353
    // with '.' (easy to check), or we have the sequence './'.
15354
    // Note: input cannot be empty, it must at least contain one character ('.')
15355
    // Note: we know that '\' is not present.
15356
0
    if (input[0] != '.') {
15357
0
      size_t slashdot = 0;
15358
0
      bool dot_is_file = true;
15359
0
      for (;;) {
15360
0
        slashdot = input.find("/.", slashdot);
15361
0
        if (slashdot == std::string_view::npos) {  // common case
15362
0
          break;
15363
0
        } else {  // uncommon
15364
          // only three cases matter: /./, /.. or a final /
15365
0
          slashdot += 2;
15366
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15367
0
                           input[slashdot] == '/');
15368
0
        }
15369
0
      }
15370
0
      trivial_path = dot_is_file;
15371
0
    }
15372
0
  }
15373
0
  if (trivial_path && is_at_path()) {
15374
0
    ada_log("parse_path trivial");
15375
0
    buffer += '/';
15376
0
    buffer += input;
15377
0
    return;
15378
0
  }
15379
0
  std::string path = std::string(get_pathname());
15380
  // We are going to need to look a bit at the path, but let us see if we can
15381
  // ignore percent encoding *and* backslashes *and* percent characters.
15382
  // Except for the trivial case, this is likely to capture 99% of paths out
15383
  // there.
15384
0
  bool fast_path =
15385
0
      (special &&
15386
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15387
0
      (type != ada::scheme::type::FILE);
15388
0
  if (fast_path) {
15389
0
    ada_log("parse_prepared_path fast");
15390
    // Here we don't need to worry about \ or percent encoding.
15391
    // We also do not have a file protocol. We might have dots, however,
15392
    // but dots must as appear as '.', and they cannot be encoded because
15393
    // the symbol '%' is not present.
15394
0
    size_t previous_location = 0;  // We start at 0.
15395
0
    do {
15396
0
      size_t new_location = input.find('/', previous_location);
15397
      // std::string_view path_view = input;
15398
      //  We process the last segment separately:
15399
0
      if (new_location == std::string_view::npos) {
15400
0
        std::string_view path_view = input.substr(previous_location);
15401
0
        if (path_view == "..") {  // The path ends with ..
15402
          // e.g., if you receive ".." with an empty path, you go to "/".
15403
0
          if (path.empty()) {
15404
0
            path = '/';
15405
0
            update_base_pathname(path);
15406
0
            return;
15407
0
          }
15408
          // Fast case where we have nothing to do:
15409
0
          if (path.back() == '/') {
15410
0
            update_base_pathname(path);
15411
0
            return;
15412
0
          }
15413
          // If you have the path "/joe/myfriend",
15414
          // then you delete 'myfriend'.
15415
0
          path.resize(path.rfind('/') + 1);
15416
0
          update_base_pathname(path);
15417
0
          return;
15418
0
        }
15419
0
        path += '/';
15420
0
        if (path_view != ".") {
15421
0
          path.append(path_view);
15422
0
        }
15423
0
        update_base_pathname(path);
15424
0
        return;
15425
0
      } else {
15426
        // This is a non-final segment.
15427
0
        std::string_view path_view =
15428
0
            input.substr(previous_location, new_location - previous_location);
15429
0
        previous_location = new_location + 1;
15430
0
        if (path_view == "..") {
15431
0
          size_t last_delimiter = path.rfind('/');
15432
0
          if (last_delimiter != std::string::npos) {
15433
0
            path.erase(last_delimiter);
15434
0
          }
15435
0
        } else if (path_view != ".") {
15436
0
          path += '/';
15437
0
          path.append(path_view);
15438
0
        }
15439
0
      }
15440
0
    } while (true);
15441
0
  } else {
15442
0
    ada_log("parse_path slow");
15443
    // we have reached the general case
15444
0
    bool needs_percent_encoding = (accumulator & 1);
15445
0
    std::string path_buffer_tmp;
15446
0
    do {
15447
0
      size_t location = (special && (accumulator & 2))
15448
0
                            ? input.find_first_of("/\\")
15449
0
                            : input.find('/');
15450
0
      std::string_view path_view = input;
15451
0
      if (location != std::string_view::npos) {
15452
0
        path_view.remove_suffix(path_view.size() - location);
15453
0
        input.remove_prefix(location + 1);
15454
0
      }
15455
      // path_buffer is either path_view or it might point at a percent encoded
15456
      // temporary string.
15457
0
      std::string_view path_buffer =
15458
0
          (needs_percent_encoding &&
15459
0
           ada::unicode::percent_encode<false>(
15460
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15461
0
              ? path_buffer_tmp
15462
0
              : path_view;
15463
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15464
0
        helpers::shorten_path(path, type);
15465
0
        if (location == std::string_view::npos) {
15466
0
          path += '/';
15467
0
        }
15468
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15469
0
                 (location == std::string_view::npos)) {
15470
0
        path += '/';
15471
0
      }
15472
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15473
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15474
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15475
        // Windows drive letter, then replace the second code point in
15476
        // path_buffer with U+003A (:).
15477
0
        if (type == ada::scheme::type::FILE && path.empty() &&
15478
0
            checkers::is_windows_drive_letter(path_buffer)) {
15479
0
          path += '/';
15480
0
          path += path_buffer[0];
15481
0
          path += ':';
15482
0
          path_buffer.remove_prefix(2);
15483
0
          path.append(path_buffer);
15484
0
        } else {
15485
          // Append path_buffer to url's path.
15486
0
          path += '/';
15487
0
          path.append(path_buffer);
15488
0
        }
15489
0
      }
15490
0
      if (location == std::string_view::npos) {
15491
0
        update_base_pathname(path);
15492
0
        return;
15493
0
      }
15494
0
    } while (true);
15495
0
  }
15496
0
}
15497
}  // namespace ada
15498
/* end file src/url_aggregator.cpp */
15499
15500
#if ADA_INCLUDE_URL_PATTERN
15501
/* begin file src/url_pattern.cpp */
15502
#if ADA_INCLUDE_URL_PATTERN
15503
15504
15505
#include <algorithm>
15506
#include <optional>
15507
#include <string>
15508
15509
namespace ada {
15510
15511
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15512
    const url_pattern_init& init, url_pattern_init::process_type type,
15513
    std::optional<std::string_view> protocol,
15514
    std::optional<std::string_view> username,
15515
    std::optional<std::string_view> password,
15516
    std::optional<std::string_view> hostname,
15517
    std::optional<std::string_view> port,
15518
    std::optional<std::string_view> pathname,
15519
    std::optional<std::string_view> search,
15520
0
    std::optional<std::string_view> hash) {
15521
  // Let result be the result of creating a new URLPatternInit.
15522
0
  auto result = url_pattern_init{};
15523
15524
  // If protocol is not null, set result["protocol"] to protocol.
15525
0
  if (protocol.has_value()) result.protocol = *protocol;
15526
15527
  // If username is not null, set result["username"] to username.
15528
0
  if (username.has_value()) result.username = *username;
15529
15530
  // If password is not null, set result["password"] to password.
15531
0
  if (password.has_value()) result.password = *password;
15532
15533
  // If hostname is not null, set result["hostname"] to hostname.
15534
0
  if (hostname.has_value()) result.hostname = *hostname;
15535
15536
  // If port is not null, set result["port"] to port.
15537
0
  if (port.has_value()) result.port = *port;
15538
15539
  // If pathname is not null, set result["pathname"] to pathname.
15540
0
  if (pathname.has_value()) result.pathname = *pathname;
15541
15542
  // If search is not null, set result["search"] to search.
15543
0
  if (search.has_value()) result.search = *search;
15544
15545
  // If hash is not null, set result["hash"] to hash.
15546
0
  if (hash.has_value()) result.hash = *hash;
15547
15548
  // Let baseURL be null.
15549
0
  std::optional<url_aggregator> base_url{};
15550
15551
  // If init["baseURL"] exists:
15552
0
  if (init.base_url.has_value()) {
15553
    // Set baseURL to the result of parsing init["baseURL"].
15554
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15555
    // If baseURL is failure, then throw a TypeError.
15556
0
    if (!parsing_result) {
15557
0
      return tl::unexpected(errors::type_error);
15558
0
    }
15559
0
    base_url = std::move(*parsing_result);
15560
15561
    // If init["protocol"] does not exist, then set result["protocol"] to the
15562
    // result of processing a base URL string given baseURL's scheme and type.
15563
0
    if (!init.protocol.has_value()) {
15564
0
      ADA_ASSERT_TRUE(base_url.has_value());
15565
0
      std::string_view base_url_protocol = base_url->get_protocol();
15566
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15567
0
      result.protocol =
15568
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15569
0
    }
15570
15571
    // If type is not "pattern" and init contains none of "protocol",
15572
    // "hostname", "port" and "username", then set result["username"] to the
15573
    // result of processing a base URL string given baseURL's username and type.
15574
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15575
0
        !init.port && !init.username) {
15576
0
      result.username = url_pattern_helpers::process_base_url_string(
15577
0
          base_url->get_username(), type);
15578
0
    }
15579
15580
    // TODO: Optimization opportunity: Merge this with the previous check.
15581
    // If type is not "pattern" and init contains none of "protocol",
15582
    // "hostname", "port", "username" and "password", then set
15583
    // result["password"] to the result of processing a base URL string given
15584
    // baseURL's password and type.
15585
0
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15586
0
        !init.port && !init.username && !init.password) {
15587
0
      result.password = url_pattern_helpers::process_base_url_string(
15588
0
          base_url->get_password(), type);
15589
0
    }
15590
15591
    // If init contains neither "protocol" nor "hostname", then:
15592
0
    if (!init.protocol && !init.hostname) {
15593
      // Let baseHost be baseURL's host.
15594
      // If baseHost is null, then set baseHost to the empty string.
15595
0
      auto base_host = base_url->get_hostname();
15596
      // Set result["hostname"] to the result of processing a base URL string
15597
      // given baseHost and type.
15598
0
      result.hostname =
15599
0
          url_pattern_helpers::process_base_url_string(base_host, type);
15600
0
    }
15601
15602
    // If init contains none of "protocol", "hostname", and "port", then:
15603
0
    if (!init.protocol && !init.hostname && !init.port) {
15604
      // If baseURL's port is null, then set result["port"] to the empty string.
15605
      // Otherwise, set result["port"] to baseURL's port, serialized.
15606
0
      result.port = base_url->get_port();
15607
0
    }
15608
15609
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15610
    // then set result["pathname"] to the result of processing a base URL string
15611
    // given the result of URL path serializing baseURL and type.
15612
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15613
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15614
0
          base_url->get_pathname(), type);
15615
0
    }
15616
15617
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15618
    // "search", then:
15619
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15620
0
        !init.search) {
15621
      // Let baseQuery be baseURL's query.
15622
      // Set result["search"] to the result of processing a base URL string
15623
      // given baseQuery and type.
15624
0
      result.search = url_pattern_helpers::process_base_url_string(
15625
0
          base_url->get_search(), type);
15626
0
    }
15627
15628
    // If init contains none of "protocol", "hostname", "port", "pathname",
15629
    // "search", and "hash", then:
15630
0
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15631
0
        !init.search && !init.hash) {
15632
      // Let baseFragment be baseURL's fragment.
15633
      // Set result["hash"] to the result of processing a base URL string given
15634
      // baseFragment and type.
15635
0
      result.hash = url_pattern_helpers::process_base_url_string(
15636
0
          base_url->get_hash(), type);
15637
0
    }
15638
0
  }
15639
15640
  // If init["protocol"] exists, then set result["protocol"] to the result of
15641
  // process protocol for init given init["protocol"] and type.
15642
0
  if (init.protocol) {
15643
0
    auto process_result = process_protocol(*init.protocol, type);
15644
0
    if (!process_result) {
15645
0
      return tl::unexpected(process_result.error());
15646
0
    }
15647
0
    result.protocol = std::move(*process_result);
15648
0
  }
15649
15650
  // If init["username"] exists, then set result["username"] to the result of
15651
  // process username for init given init["username"] and type.
15652
0
  if (init.username.has_value()) {
15653
0
    auto process_result = process_username(*init.username, type);
15654
0
    if (!process_result) {
15655
0
      return tl::unexpected(process_result.error());
15656
0
    }
15657
0
    result.username = std::move(*process_result);
15658
0
  }
15659
15660
  // If init["password"] exists, then set result["password"] to the result of
15661
  // process password for init given init["password"] and type.
15662
0
  if (init.password.has_value()) {
15663
0
    auto process_result = process_password(*init.password, type);
15664
0
    if (!process_result) {
15665
0
      return tl::unexpected(process_result.error());
15666
0
    }
15667
0
    result.password = std::move(*process_result);
15668
0
  }
15669
15670
  // If init["hostname"] exists, then set result["hostname"] to the result of
15671
  // process hostname for init given init["hostname"] and type.
15672
0
  if (init.hostname.has_value()) {
15673
0
    auto process_result = process_hostname(*init.hostname, type);
15674
0
    if (!process_result) {
15675
0
      return tl::unexpected(process_result.error());
15676
0
    }
15677
0
    result.hostname = std::move(*process_result);
15678
0
  }
15679
15680
  // If init["port"] exists, then set result["port"] to the result of process
15681
  // port for init given init["port"], result["protocol"], and type.
15682
0
  if (init.port) {
15683
0
    auto process_result =
15684
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
15685
0
    if (!process_result) {
15686
0
      return tl::unexpected(process_result.error());
15687
0
    }
15688
0
    result.port = std::move(*process_result);
15689
0
  }
15690
15691
  // If init["pathname"] exists:
15692
0
  if (init.pathname.has_value()) {
15693
    // Set result["pathname"] to init["pathname"].
15694
0
    result.pathname = init.pathname;
15695
15696
    // If the following are all true:
15697
    // - baseURL is not null;
15698
    // - baseURL has an opaque path; and
15699
    // - the result of running is an absolute pathname given result["pathname"]
15700
    // and type is false,
15701
0
    if (base_url && !base_url->has_opaque_path &&
15702
0
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15703
      // Let baseURLPath be the result of running process a base URL string
15704
      // given the result of URL path serializing baseURL and type.
15705
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15706
      // exist.
15707
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
15708
0
          base_url->get_pathname(), type);
15709
15710
      // Let slash index be the index of the last U+002F (/) code point found in
15711
      // baseURLPath, interpreted as a sequence of code points, or null if there
15712
      // are no instances of the code point.
15713
0
      auto slash_index = base_url_path.find_last_of('/');
15714
15715
      // If slash index is not null:
15716
0
      if (slash_index != std::string::npos) {
15717
        // Let new pathname be the code point substring from 0 to slash index +
15718
        // 1 within baseURLPath.
15719
0
        base_url_path.resize(slash_index + 1);
15720
        // Append result["pathname"] to the end of new pathname.
15721
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
15722
0
        base_url_path.append(std::move(*result.pathname));
15723
        // Set result["pathname"] to new pathname.
15724
0
        result.pathname = std::move(base_url_path);
15725
0
      }
15726
0
    }
15727
15728
    // Set result["pathname"] to the result of process pathname for init given
15729
    // result["pathname"], result["protocol"], and type.
15730
0
    auto pathname_processing_result =
15731
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
15732
0
    if (!pathname_processing_result) {
15733
0
      return tl::unexpected(pathname_processing_result.error());
15734
0
    }
15735
0
    result.pathname = std::move(*pathname_processing_result);
15736
0
  }
15737
15738
  // If init["search"] exists then set result["search"] to the result of process
15739
  // search for init given init["search"] and type.
15740
0
  if (init.search) {
15741
0
    auto process_result = process_search(*init.search, type);
15742
0
    if (!process_result) {
15743
0
      return tl::unexpected(process_result.error());
15744
0
    }
15745
0
    result.search = std::move(*process_result);
15746
0
  }
15747
15748
  // If init["hash"] exists then set result["hash"] to the result of process
15749
  // hash for init given init["hash"] and type.
15750
0
  if (init.hash) {
15751
0
    auto process_result = process_hash(*init.hash, type);
15752
0
    if (!process_result) {
15753
0
      return tl::unexpected(process_result.error());
15754
0
    }
15755
0
    result.hash = std::move(*process_result);
15756
0
  }
15757
  // Return result.
15758
0
  return result;
15759
0
}
15760
15761
tl::expected<std::string, errors> url_pattern_init::process_protocol(
15762
0
    std::string_view value, process_type type) {
15763
0
  ada_log("process_protocol=", value, " [", type, "]");
15764
  // Let strippedValue be the given value with a single trailing U+003A (:)
15765
  // removed, if any.
15766
0
  if (value.ends_with(":")) {
15767
0
    value.remove_suffix(1);
15768
0
  }
15769
  // If type is "pattern" then return strippedValue.
15770
0
  if (type == process_type::pattern) {
15771
0
    return std::string(value);
15772
0
  }
15773
  // Return the result of running canonicalize a protocol given strippedValue.
15774
0
  return url_pattern_helpers::canonicalize_protocol(value);
15775
0
}
15776
15777
tl::expected<std::string, errors> url_pattern_init::process_username(
15778
0
    std::string_view value, process_type type) {
15779
  // If type is "pattern" then return value.
15780
0
  if (type == process_type::pattern) {
15781
0
    return std::string(value);
15782
0
  }
15783
  // Return the result of running canonicalize a username given value.
15784
0
  return url_pattern_helpers::canonicalize_username(value);
15785
0
}
15786
15787
tl::expected<std::string, errors> url_pattern_init::process_password(
15788
0
    std::string_view value, process_type type) {
15789
  // If type is "pattern" then return value.
15790
0
  if (type == process_type::pattern) {
15791
0
    return std::string(value);
15792
0
  }
15793
  // Return the result of running canonicalize a password given value.
15794
0
  return url_pattern_helpers::canonicalize_password(value);
15795
0
}
15796
15797
tl::expected<std::string, errors> url_pattern_init::process_hostname(
15798
0
    std::string_view value, process_type type) {
15799
0
  ada_log("process_hostname value=", value, " type=", type);
15800
  // If type is "pattern" then return value.
15801
0
  if (type == process_type::pattern) {
15802
0
    return std::string(value);
15803
0
  }
15804
  // Return the result of running canonicalize a hostname given value.
15805
0
  return url_pattern_helpers::canonicalize_hostname(value);
15806
0
}
15807
15808
tl::expected<std::string, errors> url_pattern_init::process_port(
15809
0
    std::string_view port, std::string_view protocol, process_type type) {
15810
  // If type is "pattern" then return portValue.
15811
0
  if (type == process_type::pattern) {
15812
0
    return std::string(port);
15813
0
  }
15814
  // Return the result of running canonicalize a port given portValue and
15815
  // protocolValue.
15816
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
15817
0
}
15818
15819
tl::expected<std::string, errors> url_pattern_init::process_pathname(
15820
0
    std::string_view value, std::string_view protocol, process_type type) {
15821
  // If type is "pattern" then return pathnameValue.
15822
0
  if (type == process_type::pattern) {
15823
0
    return std::string(value);
15824
0
  }
15825
15826
  // If protocolValue is a special scheme or the empty string, then return the
15827
  // result of running canonicalize a pathname given pathnameValue.
15828
0
  if (protocol.empty() || scheme::is_special(protocol)) {
15829
0
    return url_pattern_helpers::canonicalize_pathname(value);
15830
0
  }
15831
15832
  // Return the result of running canonicalize an opaque pathname given
15833
  // pathnameValue.
15834
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
15835
0
}
15836
15837
tl::expected<std::string, errors> url_pattern_init::process_search(
15838
0
    std::string_view value, process_type type) {
15839
  // Let strippedValue be the given value with a single leading U+003F (?)
15840
  // removed, if any.
15841
0
  if (value.starts_with("?")) {
15842
0
    value.remove_prefix(1);
15843
0
  }
15844
0
  ADA_ASSERT_TRUE(!value.starts_with("?"));
15845
  // If type is "pattern" then return strippedValue.
15846
0
  if (type == process_type::pattern) {
15847
0
    return std::string(value);
15848
0
  }
15849
  // Return the result of running canonicalize a search given strippedValue.
15850
0
  return url_pattern_helpers::canonicalize_search(value);
15851
0
}
15852
15853
tl::expected<std::string, errors> url_pattern_init::process_hash(
15854
0
    std::string_view value, process_type type) {
15855
  // Let strippedValue be the given value with a single leading U+0023 (#)
15856
  // removed, if any.
15857
0
  if (value.starts_with("#")) {
15858
0
    value.remove_prefix(1);
15859
0
  }
15860
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
15861
  // If type is "pattern" then return strippedValue.
15862
0
  if (type == process_type::pattern) {
15863
0
    return std::string(value);
15864
0
  }
15865
  // Return the result of running canonicalize a hash given strippedValue.
15866
0
  return url_pattern_helpers::canonicalize_hash(value);
15867
0
}
15868
15869
}  // namespace ada
15870
15871
#endif  // ADA_INCLUDE_URL_PATTERN
15872
/* end file src/url_pattern.cpp */
15873
/* begin file src/url_pattern_helpers.cpp */
15874
#if ADA_INCLUDE_URL_PATTERN
15875
15876
#include <algorithm>
15877
#include <optional>
15878
#include <string>
15879
15880
namespace ada::url_pattern_helpers {
15881
15882
std::tuple<std::string, std::vector<std::string>>
15883
generate_regular_expression_and_name_list(
15884
    const std::vector<url_pattern_part>& part_list,
15885
0
    url_pattern_compile_component_options options) {
15886
  // Let result be "^"
15887
0
  std::string result = "^";
15888
15889
  // Let name list be a new list
15890
0
  std::vector<std::string> name_list{};
15891
15892
  // For each part of part list:
15893
0
  for (const url_pattern_part& part : part_list) {
15894
    // If part's type is "fixed-text":
15895
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
15896
      // If part's modifier is "none"
15897
0
      if (part.modifier == url_pattern_part_modifier::none) {
15898
        // Append the result of running escape a regexp string given part's
15899
        // value
15900
0
        result += escape_regexp_string(part.value);
15901
0
      } else {
15902
        // A "fixed-text" part with a modifier uses a non capturing group
15903
        // (?:<fixed text>)<modifier>
15904
        // Append "(?:" to the end of result.
15905
0
        result.append("(?:");
15906
        // Append the result of running escape a regexp string given part's
15907
        // value to the end of result.
15908
0
        result.append(escape_regexp_string(part.value));
15909
        // Append ")" to the end of result.
15910
0
        result.append(")");
15911
        // Append the result of running convert a modifier to a string given
15912
        // part's modifier to the end of result.
15913
0
        result.append(convert_modifier_to_string(part.modifier));
15914
0
      }
15915
0
      continue;
15916
0
    }
15917
15918
    // Assert: part's name is not the empty string
15919
0
    ADA_ASSERT_TRUE(!part.name.empty());
15920
15921
    // Append part's name to name list
15922
0
    name_list.push_back(part.name);
15923
15924
    // Let regexp value be part's value
15925
0
    std::string regexp_value = part.value;
15926
15927
    // If part's type is "segment-wildcard"
15928
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
15929
      // then set regexp value to the result of running generate a segment
15930
      // wildcard regexp given options.
15931
0
      regexp_value = generate_segment_wildcard_regexp(options);
15932
0
    }
15933
    // Otherwise if part's type is "full-wildcard"
15934
0
    else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
15935
      // then set regexp value to full wildcard regexp value.
15936
0
      regexp_value = ".*";
15937
0
    }
15938
15939
    // If part's prefix is the empty string and part's suffix is the empty
15940
    // string
15941
0
    if (part.prefix.empty() && part.suffix.empty()) {
15942
      // If part's modifier is "none" or "optional"
15943
0
      if (part.modifier == url_pattern_part_modifier::none ||
15944
0
          part.modifier == url_pattern_part_modifier::optional) {
15945
        // (<regexp value>)<modifier>
15946
0
        result += "(" + regexp_value + ")" +
15947
0
                  convert_modifier_to_string(part.modifier);
15948
0
      } else {
15949
        // ((?:<regexp value>)<modifier>)
15950
0
        result += "((?:" + regexp_value + ")" +
15951
0
                  convert_modifier_to_string(part.modifier) + ")";
15952
0
      }
15953
0
      continue;
15954
0
    }
15955
15956
    // If part's modifier is "none" or "optional"
15957
0
    if (part.modifier == url_pattern_part_modifier::none ||
15958
0
        part.modifier == url_pattern_part_modifier::optional) {
15959
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
15960
0
      result += "(?:" + escape_regexp_string(part.prefix) + "(" + regexp_value +
15961
0
                ")" + escape_regexp_string(part.suffix) + ")" +
15962
0
                convert_modifier_to_string(part.modifier);
15963
0
      continue;
15964
0
    }
15965
15966
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
15967
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
15968
0
                    part.modifier == url_pattern_part_modifier::one_or_more);
15969
15970
    // Assert: part's prefix is not the empty string or part's suffix is not the
15971
    // empty string
15972
0
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
15973
15974
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
15975
    // value>))*)<suffix>)?
15976
    // Append "(?:" to the end of result.
15977
0
    result.append("(?:");
15978
    // Append the result of running escape a regexp string given part's prefix
15979
    // to the end of result.
15980
0
    result.append(escape_regexp_string(part.prefix));
15981
    // Append "((?:" to the end of result.
15982
0
    result.append("((?:");
15983
    // Append regexp value to the end of result.
15984
0
    result.append(regexp_value);
15985
    // Append ")(?:" to the end of result.
15986
0
    result.append(")(?:");
15987
    // Append the result of running escape a regexp string given part's suffix
15988
    // to the end of result.
15989
0
    result.append(escape_regexp_string(part.suffix));
15990
    // Append the result of running escape a regexp string given part's prefix
15991
    // to the end of result.
15992
0
    result.append(escape_regexp_string(part.prefix));
15993
    // Append "(?:" to the end of result.
15994
0
    result.append("(?:");
15995
    // Append regexp value to the end of result.
15996
0
    result.append(regexp_value);
15997
    // Append "))*)" to the end of result.
15998
0
    result.append("))*)");
15999
    // Append the result of running escape a regexp string given part's suffix
16000
    // to the end of result.
16001
0
    result.append(escape_regexp_string(part.suffix));
16002
    // Append ")" to the end of result.
16003
0
    result.append(")");
16004
16005
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16006
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16007
0
      result += "?";
16008
0
    }
16009
0
  }
16010
16011
  // Append "$" to the end of result
16012
0
  result += "$";
16013
16014
  // Return (result, name list)
16015
0
  return {std::move(result), std::move(name_list)};
16016
0
}
16017
16018
0
bool is_ipv6_address(std::string_view input) noexcept {
16019
  // If input's code point length is less than 2, then return false.
16020
0
  if (input.size() < 2) return false;
16021
16022
  // Let input code points be input interpreted as a list of code points.
16023
  // If input code points[0] is U+005B ([), then return true.
16024
0
  if (input.front() == '[') return true;
16025
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16026
  // ([), then return true.
16027
0
  if (input.starts_with("{[")) return true;
16028
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16029
  // ([), then return true.
16030
0
  return input.starts_with("\\[");
16031
0
}
16032
16033
0
std::string convert_modifier_to_string(url_pattern_part_modifier modifier) {
16034
  // TODO: Optimize this.
16035
0
  switch (modifier) {
16036
      // If modifier is "zero-or-more", then return "*".
16037
0
    case url_pattern_part_modifier::zero_or_more:
16038
0
      return "*";
16039
    // If modifier is "optional", then return "?".
16040
0
    case url_pattern_part_modifier::optional:
16041
0
      return "?";
16042
    // If modifier is "one-or-more", then return "+".
16043
0
    case url_pattern_part_modifier::one_or_more:
16044
0
      return "+";
16045
    // Return the empty string.
16046
0
    default:
16047
0
      return "";
16048
0
  }
16049
0
}
16050
16051
std::string generate_segment_wildcard_regexp(
16052
0
    url_pattern_compile_component_options options) {
16053
  // Let result be "[^".
16054
0
  std::string result = "[^";
16055
  // Append the result of running escape a regexp string given options's
16056
  // delimiter code point to the end of result.
16057
0
  result.append(escape_regexp_string(options.get_delimiter()));
16058
  // Append "]+?" to the end of result.
16059
0
  result.append("]+?");
16060
  // Return result.
16061
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16062
0
  return result;
16063
0
}
16064
16065
tl::expected<std::string, errors> canonicalize_protocol(
16066
0
    std::string_view input) {
16067
0
  ada_log("canonicalize_protocol called with input=", input);
16068
  // If value is the empty string, return value.
16069
0
  if (input.empty()) [[unlikely]] {
16070
0
    return "";
16071
0
  }
16072
16073
  // IMPORTANT: Deviation from the spec. We remove the trailing ':' here.
16074
0
  if (input.ends_with(":")) {
16075
0
    input.remove_suffix(1);
16076
0
  }
16077
16078
  // Let dummyURL be a new URL record.
16079
  // Let parseResult be the result of running the basic URL parser given value
16080
  // followed by "://dummy.test", with dummyURL as url.
16081
0
  if (auto dummy_url = ada::parse<url_aggregator>(
16082
0
          std::string(input) + "://dummy.test", nullptr)) {
16083
    // IMPORTANT: Deviation from the spec. We remove the trailing ':' here.
16084
    // Since URL parser always return protocols ending with `:`
16085
0
    auto protocol = dummy_url->get_protocol();
16086
0
    protocol.remove_suffix(1);
16087
0
    return std::string(protocol);
16088
0
  }
16089
  // If parseResult is failure, then throw a TypeError.
16090
0
  return tl::unexpected(errors::type_error);
16091
0
}
16092
16093
tl::expected<std::string, errors> canonicalize_username(
16094
0
    std::string_view input) {
16095
  // If value is the empty string, return value.
16096
0
  if (input.empty()) [[unlikely]] {
16097
0
    return "";
16098
0
  }
16099
  // Let dummyURL be a new URL record.
16100
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16101
0
  ADA_ASSERT_TRUE(url.has_value());
16102
  // Set the username given dummyURL and value.
16103
0
  if (!url->set_username(input)) {
16104
0
    return tl::unexpected(errors::type_error);
16105
0
  }
16106
  // Return dummyURL's username.
16107
0
  return std::string(url->get_username());
16108
0
}
16109
16110
tl::expected<std::string, errors> canonicalize_password(
16111
0
    std::string_view input) {
16112
  // If value is the empty string, return value.
16113
0
  if (input.empty()) [[unlikely]] {
16114
0
    return "";
16115
0
  }
16116
  // Let dummyURL be a new URL record.
16117
  // Set the password given dummyURL and value.
16118
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16119
16120
0
  ADA_ASSERT_TRUE(url.has_value());
16121
0
  if (!url->set_password(input)) {
16122
0
    return tl::unexpected(errors::type_error);
16123
0
  }
16124
  // Return dummyURL's password.
16125
0
  return std::string(url->get_password());
16126
0
}
16127
16128
tl::expected<std::string, errors> canonicalize_hostname(
16129
0
    std::string_view input) {
16130
0
  ada_log("canonicalize_hostname input=", input);
16131
  // If value is the empty string, return value.
16132
0
  if (input.empty()) [[unlikely]] {
16133
0
    return "";
16134
0
  }
16135
  // Let dummyURL be a new URL record.
16136
  // Let parseResult be the result of running the basic URL parser given value
16137
  // with dummyURL as url and hostname state as state override.
16138
16139
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16140
  // hostname will not be converted using IDNA.
16141
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16142
0
  ADA_ASSERT_TRUE(url);
16143
  // if (!isValidHostnameInput(hostname)) return kj::none;
16144
0
  if (!url->set_hostname(input)) {
16145
    // If parseResult is failure, then throw a TypeError.
16146
0
    return tl::unexpected(errors::type_error);
16147
0
  }
16148
  // Return dummyURL's host, serialized, or empty string if it is null.
16149
0
  return std::string(url->get_hostname());
16150
0
}
16151
16152
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16153
0
    std::string_view input) {
16154
0
  ada_log("canonicalize_ipv6_hostname input=", input);
16155
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16156
0
  if (std::ranges::any_of(input, [](char c) {
16157
0
        return c != '[' && c != ']' && c != ':' &&
16158
0
               !unicode::is_ascii_hex_digit(c);
16159
0
      })) {
16160
0
    return tl::unexpected(errors::type_error);
16161
0
  }
16162
  // Append the result of running ASCII lowercase given code point to the end of
16163
  // result.
16164
0
  auto hostname = std::string(input);
16165
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16166
0
  return hostname;
16167
0
}
16168
16169
tl::expected<std::string, errors> canonicalize_port(
16170
0
    std::string_view port_value) {
16171
  // If portValue is the empty string, return portValue.
16172
0
  if (port_value.empty()) [[unlikely]] {
16173
0
    return "";
16174
0
  }
16175
  // Let dummyURL be a new URL record.
16176
  // If protocolValue was given, then set dummyURL's scheme to protocolValue.
16177
  // Let parseResult be the result of running basic URL parser given portValue
16178
  // with dummyURL as url and port state as state override.
16179
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16180
0
  ADA_ASSERT_TRUE(url);
16181
0
  if (url->set_port(port_value)) {
16182
    // Return dummyURL's port, serialized, or empty string if it is null.
16183
0
    return std::string(url->get_port());
16184
0
  }
16185
  // If parseResult is failure, then throw a TypeError.
16186
0
  return tl::unexpected(errors::type_error);
16187
0
}
16188
16189
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16190
0
    std::string_view port_value, std::string_view protocol) {
16191
  // If portValue is the empty string, return portValue.
16192
0
  if (port_value.empty()) [[unlikely]] {
16193
0
    return "";
16194
0
  }
16195
16196
  // TODO: Remove this
16197
  // We have an empty protocol because get_protocol() returns an empty string
16198
  // We should handle this in the caller rather than here.
16199
0
  if (protocol.empty()) {
16200
0
    protocol = "fake";
16201
0
  } else if (protocol.ends_with(":")) {
16202
0
    protocol.remove_suffix(1);
16203
0
  }
16204
  // Let dummyURL be a new URL record.
16205
  // If protocolValue was given, then set dummyURL's scheme to protocolValue.
16206
  // Let parseResult be the result of running basic URL parser given portValue
16207
  // with dummyURL as url and port state as state override.
16208
0
  auto url = ada::parse<url_aggregator>(std::string(protocol) + "://dummy.test",
16209
0
                                        nullptr);
16210
  // TODO: Remove has_port() check.
16211
  // This is actually a bug with url parser where set_port() returns true for
16212
  // "invalid80" port value.
16213
0
  if (url && url->set_port(port_value) && url->has_port()) {
16214
    // Return dummyURL's port, serialized, or empty string if it is null.
16215
0
    return std::string(url->get_port());
16216
0
  }
16217
  // TODO: Remove this once the previous has_port() check is removed.
16218
0
  if (url) {
16219
0
    if (scheme::is_special(protocol) && url->get_port().empty()) {
16220
0
      return "";
16221
0
    }
16222
0
  }
16223
  // If parseResult is failure, then throw a TypeError.
16224
0
  return tl::unexpected(errors::type_error);
16225
0
}
16226
16227
tl::expected<std::string, errors> canonicalize_pathname(
16228
0
    std::string_view input) {
16229
  // If value is the empty string, then return value.
16230
0
  if (input.empty()) [[unlikely]] {
16231
0
    return "";
16232
0
  }
16233
  // Let leading slash be true if the first code point in value is U+002F (/)
16234
  // and otherwise false.
16235
0
  const bool leading_slash = input.starts_with("/");
16236
  // Let modified value be "/-" if leading slash is false and otherwise the
16237
  // empty string.
16238
0
  const auto modified_value = leading_slash ? "" : "/-";
16239
0
  const auto full_url =
16240
0
      std::string("fake://fake-url") + modified_value + std::string(input);
16241
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
16242
0
    const auto pathname = url->get_pathname();
16243
    // If leading slash is false, then set result to the code point substring
16244
    // from 2 to the end of the string within result.
16245
0
    return leading_slash ? std::string(pathname)
16246
0
                         : std::string(pathname.substr(2));
16247
0
  }
16248
  // If parseResult is failure, then throw a TypeError.
16249
0
  return tl::unexpected(errors::type_error);
16250
0
}
16251
16252
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16253
0
    std::string_view input) {
16254
  // If value is the empty string, return value.
16255
0
  if (input.empty()) [[unlikely]] {
16256
0
    return "";
16257
0
  }
16258
  // Let dummyURL be a new URL record.
16259
  // Set dummyURL's path to the empty string.
16260
  // Let parseResult be the result of running URL parsing given value with
16261
  // dummyURL as url and opaque path state as state override.
16262
0
  if (auto url =
16263
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16264
    // Return the result of URL path serializing dummyURL.
16265
0
    return std::string(url->get_pathname());
16266
0
  }
16267
  // If parseResult is failure, then throw a TypeError.
16268
0
  return tl::unexpected(errors::type_error);
16269
0
}
16270
16271
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16272
  // If value is the empty string, return value.
16273
0
  if (input.empty()) [[unlikely]] {
16274
0
    return "";
16275
0
  }
16276
  // Let dummyURL be a new URL record.
16277
  // Set dummyURL's query to the empty string.
16278
  // Let parseResult be the result of running basic URL parser given value with
16279
  // dummyURL as url and query state as state override.
16280
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16281
0
  ADA_ASSERT_TRUE(url.has_value());
16282
0
  url->set_search(input);
16283
0
  if (url->has_search()) {
16284
0
    const auto search = url->get_search();
16285
0
    return std::string(search.substr(1));
16286
0
  }
16287
0
  return tl::unexpected(errors::type_error);
16288
0
}
16289
16290
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16291
  // If value is the empty string, return value.
16292
0
  if (input.empty()) [[unlikely]] {
16293
0
    return "";
16294
0
  }
16295
  // Let dummyURL be a new URL record.
16296
  // Set dummyURL's fragment to the empty string.
16297
  // Let parseResult be the result of running basic URL parser given value with
16298
  // dummyURL as url and fragment state as state override.
16299
0
  auto url = ada::parse<url_aggregator>("fake://dummy.test", nullptr);
16300
0
  ADA_ASSERT_TRUE(url.has_value());
16301
0
  url->set_hash(input);
16302
  // Return dummyURL's fragment.
16303
0
  if (url->has_hash()) {
16304
0
    const auto hash = url->get_hash();
16305
0
    return std::string(hash.substr(1));
16306
0
  }
16307
0
  return tl::unexpected(errors::type_error);
16308
0
}
16309
16310
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16311
0
                                                  token_policy policy) {
16312
0
  ada_log("tokenize input: ", input);
16313
  // Let tokenizer be a new tokenizer.
16314
  // Set tokenizer's input to input.
16315
  // Set tokenizer's policy to policy.
16316
0
  auto tokenizer = Tokenizer(input, policy);
16317
  // While tokenizer's index is less than tokenizer's input's code point length:
16318
0
  while (tokenizer.index < tokenizer.input.size()) {
16319
    // Run seek and get the next code point given tokenizer and tokenizer's
16320
    // index.
16321
0
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16322
16323
    // If tokenizer's code point is U+002A (*):
16324
0
    if (tokenizer.code_point == '*') {
16325
      // Run add a token with default position and length given tokenizer and
16326
      // "asterisk".
16327
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16328
0
      ada_log("add ASTERISK token");
16329
      // Continue.
16330
0
      continue;
16331
0
    }
16332
16333
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16334
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16335
      // Run add a token with default position and length given tokenizer and
16336
      // "other-modifier".
16337
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16338
      // Continue.
16339
0
      continue;
16340
0
    }
16341
16342
    // If tokenizer's code point is U+005C (\):
16343
0
    if (tokenizer.code_point == '\\') {
16344
      // If tokenizer's index is equal to tokenizer's input's code point length
16345
      // - 1:
16346
0
      if (tokenizer.index == tokenizer.input.size() - 1) {
16347
        // Run process a tokenizing error given tokenizer, tokenizer's next
16348
        // index, and tokenizer's index.
16349
0
        if (auto error = tokenizer.process_tokenizing_error(
16350
0
                tokenizer.next_index, tokenizer.index)) {
16351
0
          ada_log("process_tokenizing_error failed");
16352
0
          return tl::unexpected(*error);
16353
0
        }
16354
0
        continue;
16355
0
      }
16356
16357
      // Let escaped index be tokenizer's next index.
16358
0
      auto escaped_index = tokenizer.next_index;
16359
      // Run get the next code point given tokenizer.
16360
0
      tokenizer.get_next_code_point();
16361
      // Run add a token with default length given tokenizer, "escaped-char",
16362
      // tokenizer's next index, and escaped index.
16363
0
      tokenizer.add_token_with_default_length(
16364
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16365
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16366
0
              " with escaped index ", escaped_index);
16367
      // Continue.
16368
0
      continue;
16369
0
    }
16370
16371
    // If tokenizer's code point is U+007B ({):
16372
0
    if (tokenizer.code_point == '{') {
16373
      // Run add a token with default position and length given tokenizer and
16374
      // "open".
16375
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
16376
0
      ada_log("add OPEN token");
16377
0
      continue;
16378
0
    }
16379
16380
    // If tokenizer's code point is U+007D (}):
16381
0
    if (tokenizer.code_point == '}') {
16382
      // Run add a token with default position and length given tokenizer and
16383
      // "close".
16384
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16385
0
      ada_log("add CLOSE token");
16386
0
      continue;
16387
0
    }
16388
16389
    // If tokenizer's code point is U+003A (:):
16390
0
    if (tokenizer.code_point == ':') {
16391
      // Let name position be tokenizer's next index.
16392
0
      auto name_position = tokenizer.next_index;
16393
      // Let name start be name position.
16394
0
      auto name_start = name_position;
16395
      // While name position is less than tokenizer's input's code point length:
16396
0
      while (name_position < tokenizer.input.size()) {
16397
        // Run seek and get the next code point given tokenizer and name
16398
        // position.
16399
0
        tokenizer.seek_and_get_next_code_point(name_position);
16400
        // Let first code point be true if name position equals name start and
16401
        // false otherwise.
16402
0
        bool first_code_point = name_position == name_start;
16403
        // Let valid code point be the result of running is a valid name code
16404
        // point given tokenizer's code point and first code point.
16405
0
        auto valid_code_point =
16406
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16407
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16408
0
                " first_code_point=", first_code_point,
16409
0
                " valid_code_point=", valid_code_point);
16410
        // If valid code point is false break.
16411
0
        if (!valid_code_point) break;
16412
        // Set name position to tokenizer's next index.
16413
0
        name_position = tokenizer.next_index;
16414
0
      }
16415
16416
      // If name position is less than or equal to name start:
16417
0
      if (name_position <= name_start) {
16418
        // Run process a tokenizing error given tokenizer, name start, and
16419
        // tokenizer's index.
16420
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16421
0
                                                            tokenizer.index)) {
16422
0
          ada_log("process_tokenizing_error failed");
16423
0
          return tl::unexpected(*error);
16424
0
        }
16425
        // Continue
16426
0
        continue;
16427
0
      }
16428
16429
      // Run add a token with default length given tokenizer, "name", name
16430
      // position, and name start.
16431
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16432
0
                                              name_start);
16433
0
      continue;
16434
0
    }
16435
16436
    // If tokenizer's code point is U+0028 (():
16437
0
    if (tokenizer.code_point == '(') {
16438
      // Let depth be 1.
16439
0
      size_t depth = 1;
16440
      // Let regexp position be tokenizer's next index.
16441
0
      auto regexp_position = tokenizer.next_index;
16442
      // Let regexp start be regexp position.
16443
0
      auto regexp_start = regexp_position;
16444
      // Let error be false.
16445
0
      bool error = false;
16446
16447
      // While regexp position is less than tokenizer's input's code point
16448
      // length:
16449
0
      while (regexp_position < tokenizer.input.size()) {
16450
        // Run seek and get the next code point given tokenizer and regexp
16451
        // position.
16452
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
16453
16454
        // TODO: Optimization opportunity: The next 2 if statements can be
16455
        // merged. If the result of running is ASCII given tokenizer's code
16456
        // point is false:
16457
0
        if (!unicode::is_ascii(tokenizer.code_point)) {
16458
          // Run process a tokenizing error given tokenizer, regexp start, and
16459
          // tokenizer's index.
16460
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16461
0
                  regexp_start, tokenizer.index)) {
16462
0
            return tl::unexpected(*process_error);
16463
0
          }
16464
          // Set error to true.
16465
0
          error = true;
16466
0
          break;
16467
0
        }
16468
16469
        // If regexp position equals regexp start and tokenizer's code point is
16470
        // U+003F (?):
16471
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16472
          // Run process a tokenizing error given tokenizer, regexp start, and
16473
          // tokenizer's index.
16474
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16475
0
                  regexp_start, tokenizer.index)) {
16476
0
            return tl::unexpected(*process_error);
16477
0
          }
16478
          // Set error to true;
16479
0
          error = true;
16480
0
          break;
16481
0
        }
16482
16483
        // If tokenizer's code point is U+005C (\):
16484
0
        if (tokenizer.code_point == '\\') {
16485
          // If regexp position equals tokenizer's input's code point length - 1
16486
0
          if (regexp_position == tokenizer.input.size() - 1) {
16487
            // Run process a tokenizing error given tokenizer, regexp start, and
16488
            // tokenizer's index.
16489
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16490
0
                    regexp_start, tokenizer.index)) {
16491
0
              return tl::unexpected(*process_error);
16492
0
            }
16493
            // Set error to true.
16494
0
            error = true;
16495
0
            break;
16496
0
          }
16497
          // Run get the next code point given tokenizer.
16498
0
          tokenizer.get_next_code_point();
16499
          // If the result of running is ASCII given tokenizer's code point is
16500
          // false:
16501
0
          if (!unicode::is_ascii(tokenizer.code_point)) {
16502
            // Run process a tokenizing error given tokenizer, regexp start, and
16503
            // tokenizer's index.
16504
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16505
0
                    regexp_start, tokenizer.index);
16506
0
                process_error.has_value()) {
16507
0
              return tl::unexpected(*process_error);
16508
0
            }
16509
            // Set error to true.
16510
0
            error = true;
16511
0
            break;
16512
0
          }
16513
          // Set regexp position to tokenizer's next index.
16514
0
          regexp_position = tokenizer.next_index;
16515
0
          continue;
16516
0
        }
16517
16518
        // If tokenizer's code point is U+0029 ()):
16519
0
        if (tokenizer.code_point == ')') {
16520
          // Decrement depth by 1.
16521
0
          depth--;
16522
          // If depth is 0:
16523
0
          if (depth == 0) {
16524
            // Set regexp position to tokenizer's next index.
16525
0
            regexp_position = tokenizer.next_index;
16526
            // Break.
16527
0
            break;
16528
0
          }
16529
0
        } else if (tokenizer.code_point == '(') {
16530
          // Otherwise if tokenizer's code point is U+0028 (():
16531
          // Increment depth by 1.
16532
0
          depth++;
16533
          // If regexp position equals tokenizer's input's code point length -
16534
          // 1:
16535
0
          if (regexp_position == tokenizer.input.size() - 1) {
16536
            // Run process a tokenizing error given tokenizer, regexp start, and
16537
            // tokenizer's index.
16538
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16539
0
                    regexp_start, tokenizer.index)) {
16540
0
              return tl::unexpected(*process_error);
16541
0
            }
16542
            // Set error to true.
16543
0
            error = true;
16544
0
            break;
16545
0
          }
16546
          // Let temporary position be tokenizer's next index.
16547
0
          auto temporary_position = tokenizer.next_index;
16548
          // Run get the next code point given tokenizer.
16549
0
          tokenizer.get_next_code_point();
16550
          // If tokenizer's code point is not U+003F (?):
16551
0
          if (tokenizer.code_point != '?') {
16552
            // Run process a tokenizing error given tokenizer, regexp start, and
16553
            // tokenizer's index.
16554
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16555
0
                    regexp_start, tokenizer.index)) {
16556
0
              return tl::unexpected(*process_error);
16557
0
            }
16558
            // Set error to true.
16559
0
            error = true;
16560
0
            break;
16561
0
          }
16562
          // Set tokenizer's next index to temporary position.
16563
0
          tokenizer.next_index = temporary_position;
16564
0
        }
16565
        // Set regexp position to tokenizer's next index.
16566
0
        regexp_position = tokenizer.next_index;
16567
0
      }
16568
16569
      // If error is true continue.
16570
0
      if (error) continue;
16571
      // If depth is not zero:
16572
0
      if (depth != 0) {
16573
        // Run process a tokenizing error given tokenizer, regexp start, and
16574
        // tokenizer's index.
16575
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16576
0
                regexp_start, tokenizer.index)) {
16577
0
          return tl::unexpected(*process_error);
16578
0
        }
16579
0
        continue;
16580
0
      }
16581
      // Let regexp length be regexp position - regexp start - 1.
16582
0
      auto regexp_length = regexp_position - regexp_start - 1;
16583
      // If regexp length is zero:
16584
0
      if (regexp_length == 0) {
16585
        // Run process a tokenizing error given tokenizer, regexp start, and
16586
        // tokenizer's index.
16587
0
        if (auto process_error = tokenizer.process_tokenizing_error(
16588
0
                regexp_start, tokenizer.index)) {
16589
0
          ada_log("process_tokenizing_error failed");
16590
0
          return tl::unexpected(*process_error);
16591
0
        }
16592
0
        continue;
16593
0
      }
16594
      // Run add a token given tokenizer, "regexp", regexp position, regexp
16595
      // start, and regexp length.
16596
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
16597
0
                          regexp_length);
16598
0
      continue;
16599
0
    }
16600
    // Run add a token with default position and length given tokenizer and
16601
    // "char".
16602
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
16603
0
  }
16604
  // Run add a token with default length given tokenizer, "end", tokenizer's
16605
  // index, and tokenizer's index.
16606
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
16607
0
                                          tokenizer.index);
16608
16609
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
16610
  // Return tokenizer's token list.
16611
0
  return tokenizer.token_list;
16612
0
}
16613
16614
0
std::string escape_pattern_string(std::string_view input) {
16615
0
  ada_log("escape_pattern_string called with input=", input);
16616
0
  if (input.empty()) [[unlikely]] {
16617
0
    return "";
16618
0
  }
16619
  // Assert: input is an ASCII string.
16620
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
16621
  // Let result be the empty string.
16622
0
  std::string result{};
16623
0
  result.reserve(input.size());
16624
16625
  // TODO: Optimization opportunity: Use a lookup table
16626
0
  constexpr auto should_escape = [](const char c) {
16627
0
    return c == '+' || c == '*' || c == '?' || c == ':' || c == '{' ||
16628
0
           c == '}' || c == '(' || c == ')' || c == '\\';
16629
0
  };
16630
16631
  // While index is less than input's length:
16632
0
  for (const auto& c : input) {
16633
0
    if (should_escape(c)) {
16634
      // then append U+005C (\) to the end of result.
16635
0
      result.append("\\");
16636
0
    }
16637
16638
    // Append c to the end of result.
16639
0
    result += c;
16640
0
  }
16641
  // Return result.
16642
0
  return result;
16643
0
}
16644
16645
namespace {
16646
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
16647
  std::array<uint8_t, 256> out{};
16648
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
16649
                  '|', '/', '\\'}) {
16650
    out[c] = 1;
16651
  }
16652
  return out;
16653
}();
16654
16655
0
constexpr bool should_escape_regexp_char(char c) {
16656
0
  return escape_regexp_table[(uint8_t)c];
16657
0
}
16658
}  // namespace
16659
16660
0
std::string escape_regexp_string(std::string_view input) {
16661
  // Assert: input is an ASCII string.
16662
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
16663
  // Let result be the empty string.
16664
0
  std::string result{};
16665
0
  result.reserve(input.size());
16666
0
  for (const auto& c : input) {
16667
    // TODO: Optimize this even further
16668
0
    if (should_escape_regexp_char(c)) {
16669
0
      result.append(std::string("\\") + c);
16670
0
    } else {
16671
0
      result.push_back(c);
16672
0
    }
16673
0
  }
16674
0
  return result;
16675
0
}
16676
16677
std::string process_base_url_string(std::string_view input,
16678
0
                                    url_pattern_init::process_type type) {
16679
  // If type is not "pattern" return input.
16680
0
  if (type != url_pattern_init::process_type::pattern) {
16681
0
    return std::string(input);
16682
0
  }
16683
  // Return the result of escaping a pattern string given input.
16684
0
  return escape_pattern_string(input);
16685
0
}
16686
16687
constexpr bool is_absolute_pathname(
16688
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
16689
  // If input is the empty string, then return false.
16690
0
  if (input.empty()) [[unlikely]] {
16691
0
    return false;
16692
0
  }
16693
  // If input[0] is U+002F (/), then return true.
16694
0
  if (input.starts_with("/")) return true;
16695
  // If type is "url", then return false.
16696
0
  if (type == url_pattern_init::process_type::url) return false;
16697
  // If input's code point length is less than 2, then return false.
16698
0
  if (input.size() < 2) return false;
16699
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
16700
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
16701
  // Return false.
16702
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
16703
0
}
16704
16705
std::string generate_pattern_string(
16706
    std::vector<url_pattern_part>& part_list,
16707
0
    url_pattern_compile_component_options& options) {
16708
  // Let result be the empty string.
16709
0
  std::string result{};
16710
  // Let index list be the result of getting the indices for part list.
16711
  // For each index of index list:
16712
0
  for (size_t index = 0; index < part_list.size(); index++) {
16713
    // Let part be part list[index].
16714
0
    auto part = part_list[index];
16715
    // Let previous part be part list[index - 1] if index is greater than 0,
16716
    // otherwise let it be null.
16717
    // TODO: Optimization opportunity. Find a way to avoid making a copy here.
16718
0
    std::optional<url_pattern_part> previous_part =
16719
0
        index == 0 ? std::nullopt : std::optional(part_list[index - 1]);
16720
    // Let next part be part list[index + 1] if index is less than index list's
16721
    // size - 1, otherwise let it be null.
16722
0
    std::optional<url_pattern_part> next_part =
16723
0
        index < part_list.size() - 1 ? std::optional(part_list[index + 1])
16724
0
                                     : std::nullopt;
16725
    // If part's type is "fixed-text" then:
16726
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16727
      // If part's modifier is "none" then:
16728
0
      if (part.modifier == url_pattern_part_modifier::none) {
16729
        // Append the result of running escape a pattern string given part's
16730
        // value to the end of result.
16731
0
        result.append(escape_pattern_string(part.value));
16732
0
        continue;
16733
0
      }
16734
      // Append "{" to the end of result.
16735
0
      result += "{";
16736
      // Append the result of running escape a pattern string given part's value
16737
      // to the end of result.
16738
0
      result.append(escape_pattern_string(part.value));
16739
      // Append "}" to the end of result.
16740
0
      result += "}";
16741
      // Append the result of running convert a modifier to a string given
16742
      // part's modifier to the end of result.
16743
0
      result.append(convert_modifier_to_string(part.modifier));
16744
0
      continue;
16745
0
    }
16746
    // Let custom name be true if part's name[0] is not an ASCII digit;
16747
    // otherwise false.
16748
0
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
16749
    // Let needs grouping be true if at least one of the following are true,
16750
    // otherwise let it be false:
16751
    // - part's suffix is not the empty string.
16752
    // - part's prefix is not the empty string and is not options's prefix code
16753
    // point.
16754
0
    bool needs_grouping =
16755
0
        !part.suffix.empty() ||
16756
0
        (!part.prefix.empty() && part.prefix[0] != options.get_prefix()[0]);
16757
16758
    // If all of the following are true:
16759
    // - needs grouping is false; and
16760
    // - custom name is true; and
16761
    // - part's type is "segment-wildcard"; and
16762
    // - part's modifier is "none"; and
16763
    // - next part is not null; and
16764
    // - next part's prefix is the empty string; and
16765
    // - next part's suffix is the empty string
16766
0
    if (!needs_grouping && custom_name &&
16767
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
16768
0
        part.modifier == url_pattern_part_modifier::none &&
16769
0
        next_part.has_value() && next_part->prefix.empty() &&
16770
0
        next_part->suffix.empty()) {
16771
      // If next part's type is "fixed-text":
16772
0
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
16773
        // Set needs grouping to true if the result of running is a valid name
16774
        // code point given next part's value's first code point and the boolean
16775
        // false is true.
16776
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
16777
0
          needs_grouping = true;
16778
0
        }
16779
0
      } else {
16780
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
16781
0
        needs_grouping = !next_part->name.empty() &&
16782
0
                         unicode::is_ascii_digit(next_part->name[0]);
16783
0
      }
16784
0
    }
16785
16786
    // If all of the following are true:
16787
    // - needs grouping is false; and
16788
    // - part's prefix is the empty string; and
16789
    // - previous part is not null; and
16790
    // - previous part's type is "fixed-text"; and
16791
    // - previous part's value's last code point is options's prefix code point.
16792
    // then set needs grouping to true.
16793
0
    if (!needs_grouping && part.prefix.empty() && previous_part.has_value() &&
16794
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
16795
0
        !options.get_prefix().empty() &&
16796
0
        previous_part->value.at(previous_part->value.size() - 1) ==
16797
0
            options.get_prefix()[0]) {
16798
0
      needs_grouping = true;
16799
0
    }
16800
16801
    // Assert: part's name is not the empty string or null.
16802
0
    ADA_ASSERT_TRUE(!part.name.empty());
16803
16804
    // If needs grouping is true, then append "{" to the end of result.
16805
0
    if (needs_grouping) {
16806
0
      result.append("{");
16807
0
    }
16808
16809
    // Append the result of running escape a pattern string given part's prefix
16810
    // to the end of result.
16811
0
    result.append(escape_pattern_string(part.prefix));
16812
16813
    // If custom name is true:
16814
0
    if (custom_name) {
16815
      // Append ":" to the end of result.
16816
0
      result.append(":");
16817
      // Append part's name to the end of result.
16818
0
      result.append(part.name);
16819
0
    }
16820
16821
    // If part's type is "regexp" then:
16822
0
    if (part.type == url_pattern_part_type::REGEXP) {
16823
      // Append "(" to the end of result.
16824
0
      result.append("(");
16825
      // Append part's value to the end of result.
16826
0
      result.append(part.value);
16827
      // Append ")" to the end of result.
16828
0
      result.append(")");
16829
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
16830
0
               !custom_name) {
16831
      // Otherwise if part's type is "segment-wildcard" and custom name is
16832
      // false: Append "(" to the end of result.
16833
0
      result.append("(");
16834
      // Append the result of running generate a segment wildcard regexp given
16835
      // options to the end of result.
16836
0
      result.append(generate_segment_wildcard_regexp(options));
16837
      // Append ")" to the end of result.
16838
0
      result.append(")");
16839
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16840
      // Otherwise if part's type is "full-wildcard":
16841
      // If custom name is false and one of the following is true:
16842
      // - previous part is null; or
16843
      // - previous part's type is "fixed-text"; or
16844
      // - previous part's modifier is not "none"; or
16845
      // - needs grouping is true; or
16846
      // - part's prefix is not the empty string
16847
      // - then append "*" to the end of result.
16848
0
      if (!custom_name &&
16849
0
          (!previous_part.has_value() ||
16850
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
16851
0
           previous_part->modifier != url_pattern_part_modifier::none ||
16852
0
           needs_grouping || !part.prefix.empty())) {
16853
0
        result.append("*");
16854
0
      } else {
16855
        // Append "(" to the end of result.
16856
        // Append full wildcard regexp value to the end of result.
16857
        // Append ")" to the end of result.
16858
0
        result.append("(.*)");
16859
0
      }
16860
0
    }
16861
16862
    // If all of the following are true:
16863
    // - part's type is "segment-wildcard"; and
16864
    // - custom name is true; and
16865
    // - part's suffix is not the empty string; and
16866
    // - The result of running is a valid name code point given part's suffix's
16867
    // first code point and the boolean false is true then append U+005C (\) to
16868
    // the end of result.
16869
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
16870
0
        !part.suffix.empty() &&
16871
0
        idna::valid_name_code_point(part.suffix[0], false)) {
16872
0
      result.append("\\");
16873
0
    }
16874
16875
    // Append the result of running escape a pattern string given part's suffix
16876
    // to the end of result.
16877
0
    result.append(escape_pattern_string(part.suffix));
16878
    // If needs grouping is true, then append "}" to the end of result.
16879
0
    if (needs_grouping) result.append("}");
16880
    // Append the result of running convert a modifier to a string given part's
16881
    // modifier to the end of result.
16882
0
    result.append(convert_modifier_to_string(part.modifier));
16883
0
  }
16884
  // Return result.
16885
0
  return result;
16886
0
}
16887
}  // namespace ada::url_pattern_helpers
16888
16889
#endif  // ADA_INCLUDE_URL_PATTERN
16890
/* end file src/url_pattern_helpers.cpp */
16891
/* begin file src/url_pattern_regex.cpp */
16892
#if ADA_INCLUDE_URL_PATTERN
16893
16894
16895
namespace ada::url_pattern_regex {
16896
16897
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
16898
std::optional<std::regex> std_regex_provider::create_instance(
16899
    std::string_view pattern, bool ignore_case) {
16900
  // Let flags be an empty string.
16901
  // If options's ignore case is true then set flags to "vi".
16902
  // Otherwise set flags to "v"
16903
  auto flags = ignore_case
16904
                   ? std::regex::icase | std::regex_constants::ECMAScript
16905
                   : std::regex_constants::ECMAScript;
16906
  try {
16907
    return std::regex(pattern.data(), pattern.size(), flags);
16908
  } catch (const std::regex_error& e) {
16909
    (void)e;
16910
    ada_log("std_regex_provider::create_instance failed:", e.what());
16911
    return std::nullopt;
16912
  }
16913
}
16914
16915
std::optional<std::vector<std::optional<std::string>>>
16916
std_regex_provider::regex_search(std::string_view input,
16917
                                 const std::regex& pattern) {
16918
  std::string input_str(
16919
      input.begin(),
16920
      input.end());  // Convert string_view to string for regex_search
16921
  std::smatch match_result;
16922
  if (!std::regex_search(input_str, match_result, pattern,
16923
                         std::regex_constants::match_any)) {
16924
    return std::nullopt;
16925
  }
16926
  std::vector<std::optional<std::string>> matches;
16927
  // If input is empty, let's assume the result will be empty as well.
16928
  if (input.empty() || match_result.empty()) {
16929
    return matches;
16930
  }
16931
  matches.reserve(match_result.size());
16932
  for (size_t i = 1; i < match_result.size(); ++i) {
16933
    if (auto entry = match_result[i]; entry.matched) {
16934
      matches.emplace_back(entry.str());
16935
    }
16936
  }
16937
  return matches;
16938
}
16939
16940
bool std_regex_provider::regex_match(std::string_view input,
16941
                                     const std::regex& pattern) {
16942
  return std::regex_match(input.begin(), input.end(), pattern);
16943
}
16944
16945
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
16946
16947
}  // namespace ada::url_pattern_regex
16948
16949
#endif  // ADA_INCLUDE_URL_PATTERN
16950
/* end file src/url_pattern_regex.cpp */
16951
#endif  // ADA_INCLUDE_URL_PATTERN
16952
16953
/* begin file src/ada_c.cpp */
16954
16955
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
16956
0
  return *(ada::result<ada::url_aggregator>*)result;
16957
0
}
16958
16959
extern "C" {
16960
typedef void* ada_url;
16961
typedef void* ada_url_search_params;
16962
typedef void* ada_strings;
16963
typedef void* ada_url_search_params_keys_iter;
16964
typedef void* ada_url_search_params_values_iter;
16965
typedef void* ada_url_search_params_entries_iter;
16966
16967
struct ada_string {
16968
  const char* data;
16969
  size_t length;
16970
};
16971
16972
struct ada_owned_string {
16973
  const char* data;
16974
  size_t length;
16975
};
16976
16977
struct ada_string_pair {
16978
  ada_string key;
16979
  ada_string value;
16980
};
16981
16982
0
ada_string ada_string_create(const char* data, size_t length) {
16983
0
  ada_string out{};
16984
0
  out.data = data;
16985
0
  out.length = length;
16986
0
  return out;
16987
0
}
16988
16989
struct ada_url_components {
16990
  /*
16991
   * By using 32-bit integers, we implicitly assume that the URL string
16992
   * cannot exceed 4 GB.
16993
   *
16994
   * https://user:pass@example.com:1234/foo/bar?baz#quux
16995
   *       |     |    |          | ^^^^|       |   |
16996
   *       |     |    |          | |   |       |   `----- hash_start
16997
   *       |     |    |          | |   |       `--------- search_start
16998
   *       |     |    |          | |   `----------------- pathname_start
16999
   *       |     |    |          | `--------------------- port
17000
   *       |     |    |          `----------------------- host_end
17001
   *       |     |    `---------------------------------- host_start
17002
   *       |     `--------------------------------------- username_end
17003
   *       `--------------------------------------------- protocol_end
17004
   */
17005
  uint32_t protocol_end;
17006
  /**
17007
   * Username end is not `omitted` by default (-1) to make username and password
17008
   * getters less costly to implement.
17009
   */
17010
  uint32_t username_end;
17011
  uint32_t host_start;
17012
  uint32_t host_end;
17013
  uint32_t port;
17014
  uint32_t pathname_start;
17015
  uint32_t search_start;
17016
  uint32_t hash_start;
17017
};
17018
17019
0
ada_url ada_parse(const char* input, size_t length) noexcept {
17020
0
  return new ada::result<ada::url_aggregator>(
17021
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
17022
0
}
17023
17024
ada_url ada_parse_with_base(const char* input, size_t input_length,
17025
0
                            const char* base, size_t base_length) noexcept {
17026
0
  auto base_out =
17027
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
17028
17029
0
  if (!base_out) {
17030
0
    return new ada::result<ada::url_aggregator>(base_out);
17031
0
  }
17032
17033
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
17034
0
      std::string_view(input, input_length), &base_out.value()));
17035
0
}
17036
17037
0
bool ada_can_parse(const char* input, size_t length) noexcept {
17038
0
  return ada::can_parse(std::string_view(input, length));
17039
0
}
17040
17041
bool ada_can_parse_with_base(const char* input, size_t input_length,
17042
0
                             const char* base, size_t base_length) noexcept {
17043
0
  std::string_view base_view(base, base_length);
17044
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
17045
0
}
17046
17047
0
void ada_free(ada_url result) noexcept {
17048
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
17049
0
  delete r;
17050
0
}
17051
17052
0
ada_url ada_copy(ada_url input) noexcept {
17053
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
17054
0
  return new ada::result<ada::url_aggregator>(r);
17055
0
}
17056
17057
0
bool ada_is_valid(ada_url result) noexcept {
17058
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17059
0
  return r.has_value();
17060
0
}
17061
17062
// caller must free the result with ada_free_owned_string
17063
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
17064
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17065
0
  ada_owned_string owned{};
17066
0
  if (!r) {
17067
0
    owned.data = nullptr;
17068
0
    owned.length = 0;
17069
0
    return owned;
17070
0
  }
17071
0
  std::string out = r->get_origin();
17072
0
  owned.length = out.size();
17073
0
  owned.data = new char[owned.length];
17074
0
  memcpy((void*)owned.data, out.data(), owned.length);
17075
0
  return owned;
17076
0
}
17077
17078
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
17079
0
  delete[] owned.data;
17080
0
}
17081
17082
0
ada_string ada_get_href(ada_url result) noexcept {
17083
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17084
0
  if (!r) {
17085
0
    return ada_string_create(nullptr, 0);
17086
0
  }
17087
0
  std::string_view out = r->get_href();
17088
0
  return ada_string_create(out.data(), out.length());
17089
0
}
17090
17091
0
ada_string ada_get_username(ada_url result) noexcept {
17092
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17093
0
  if (!r) {
17094
0
    return ada_string_create(nullptr, 0);
17095
0
  }
17096
0
  std::string_view out = r->get_username();
17097
0
  return ada_string_create(out.data(), out.length());
17098
0
}
17099
17100
0
ada_string ada_get_password(ada_url result) noexcept {
17101
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17102
0
  if (!r) {
17103
0
    return ada_string_create(nullptr, 0);
17104
0
  }
17105
0
  std::string_view out = r->get_password();
17106
0
  return ada_string_create(out.data(), out.length());
17107
0
}
17108
17109
0
ada_string ada_get_port(ada_url result) noexcept {
17110
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17111
0
  if (!r) {
17112
0
    return ada_string_create(nullptr, 0);
17113
0
  }
17114
0
  std::string_view out = r->get_port();
17115
0
  return ada_string_create(out.data(), out.length());
17116
0
}
17117
17118
0
ada_string ada_get_hash(ada_url result) noexcept {
17119
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17120
0
  if (!r) {
17121
0
    return ada_string_create(nullptr, 0);
17122
0
  }
17123
0
  std::string_view out = r->get_hash();
17124
0
  return ada_string_create(out.data(), out.length());
17125
0
}
17126
17127
0
ada_string ada_get_host(ada_url result) noexcept {
17128
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17129
0
  if (!r) {
17130
0
    return ada_string_create(nullptr, 0);
17131
0
  }
17132
0
  std::string_view out = r->get_host();
17133
0
  return ada_string_create(out.data(), out.length());
17134
0
}
17135
17136
0
ada_string ada_get_hostname(ada_url result) noexcept {
17137
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17138
0
  if (!r) {
17139
0
    return ada_string_create(nullptr, 0);
17140
0
  }
17141
0
  std::string_view out = r->get_hostname();
17142
0
  return ada_string_create(out.data(), out.length());
17143
0
}
17144
17145
0
ada_string ada_get_pathname(ada_url result) noexcept {
17146
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17147
0
  if (!r) {
17148
0
    return ada_string_create(nullptr, 0);
17149
0
  }
17150
0
  std::string_view out = r->get_pathname();
17151
0
  return ada_string_create(out.data(), out.length());
17152
0
}
17153
17154
0
ada_string ada_get_search(ada_url result) noexcept {
17155
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17156
0
  if (!r) {
17157
0
    return ada_string_create(nullptr, 0);
17158
0
  }
17159
0
  std::string_view out = r->get_search();
17160
0
  return ada_string_create(out.data(), out.length());
17161
0
}
17162
17163
0
ada_string ada_get_protocol(ada_url result) noexcept {
17164
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17165
0
  if (!r) {
17166
0
    return ada_string_create(nullptr, 0);
17167
0
  }
17168
0
  std::string_view out = r->get_protocol();
17169
0
  return ada_string_create(out.data(), out.length());
17170
0
}
17171
17172
0
uint8_t ada_get_host_type(ada_url result) noexcept {
17173
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17174
0
  if (!r) {
17175
0
    return 0;
17176
0
  }
17177
0
  return r->host_type;
17178
0
}
17179
17180
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
17181
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17182
0
  if (!r) {
17183
0
    return 0;
17184
0
  }
17185
0
  return r->type;
17186
0
}
17187
17188
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
17189
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17190
0
  if (!r) {
17191
0
    return false;
17192
0
  }
17193
0
  return r->set_href(std::string_view(input, length));
17194
0
}
17195
17196
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
17197
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17198
0
  if (!r) {
17199
0
    return false;
17200
0
  }
17201
0
  return r->set_host(std::string_view(input, length));
17202
0
}
17203
17204
bool ada_set_hostname(ada_url result, const char* input,
17205
0
                      size_t length) noexcept {
17206
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17207
0
  if (!r) {
17208
0
    return false;
17209
0
  }
17210
0
  return r->set_hostname(std::string_view(input, length));
17211
0
}
17212
17213
bool ada_set_protocol(ada_url result, const char* input,
17214
0
                      size_t length) noexcept {
17215
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17216
0
  if (!r) {
17217
0
    return false;
17218
0
  }
17219
0
  return r->set_protocol(std::string_view(input, length));
17220
0
}
17221
17222
bool ada_set_username(ada_url result, const char* input,
17223
0
                      size_t length) noexcept {
17224
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17225
0
  if (!r) {
17226
0
    return false;
17227
0
  }
17228
0
  return r->set_username(std::string_view(input, length));
17229
0
}
17230
17231
bool ada_set_password(ada_url result, const char* input,
17232
0
                      size_t length) noexcept {
17233
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17234
0
  if (!r) {
17235
0
    return false;
17236
0
  }
17237
0
  return r->set_password(std::string_view(input, length));
17238
0
}
17239
17240
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
17241
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17242
0
  if (!r) {
17243
0
    return false;
17244
0
  }
17245
0
  return r->set_port(std::string_view(input, length));
17246
0
}
17247
17248
bool ada_set_pathname(ada_url result, const char* input,
17249
0
                      size_t length) noexcept {
17250
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17251
0
  if (!r) {
17252
0
    return false;
17253
0
  }
17254
0
  return r->set_pathname(std::string_view(input, length));
17255
0
}
17256
17257
/**
17258
 * Update the search/query of the URL.
17259
 *
17260
 * If a URL has `?` as the search value, passing empty string to this function
17261
 * does not remove the attribute. If you need to remove it, please use
17262
 * `ada_clear_search` method.
17263
 */
17264
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
17265
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17266
0
  if (r) {
17267
0
    r->set_search(std::string_view(input, length));
17268
0
  }
17269
0
}
17270
17271
/**
17272
 * Update the hash/fragment of the URL.
17273
 *
17274
 * If a URL has `#` as the hash value, passing empty string to this function
17275
 * does not remove the attribute. If you need to remove it, please use
17276
 * `ada_clear_hash` method.
17277
 */
17278
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
17279
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17280
0
  if (r) {
17281
0
    r->set_hash(std::string_view(input, length));
17282
0
  }
17283
0
}
17284
17285
0
void ada_clear_port(ada_url result) noexcept {
17286
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17287
0
  if (r) {
17288
0
    r->clear_port();
17289
0
  }
17290
0
}
17291
17292
/**
17293
 * Removes the hash of the URL.
17294
 *
17295
 * Despite `ada_set_hash` method, this function allows the complete
17296
 * removal of the hash attribute, even if it has a value of `#`.
17297
 */
17298
0
void ada_clear_hash(ada_url result) noexcept {
17299
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17300
0
  if (r) {
17301
0
    r->clear_hash();
17302
0
  }
17303
0
}
17304
17305
/**
17306
 * Removes the search of the URL.
17307
 *
17308
 * Despite `ada_set_search` method, this function allows the complete
17309
 * removal of the search attribute, even if it has a value of `?`.
17310
 */
17311
0
void ada_clear_search(ada_url result) noexcept {
17312
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17313
0
  if (r) {
17314
0
    r->clear_search();
17315
0
  }
17316
0
}
17317
17318
0
bool ada_has_credentials(ada_url result) noexcept {
17319
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17320
0
  if (!r) {
17321
0
    return false;
17322
0
  }
17323
0
  return r->has_credentials();
17324
0
}
17325
17326
0
bool ada_has_empty_hostname(ada_url result) noexcept {
17327
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17328
0
  if (!r) {
17329
0
    return false;
17330
0
  }
17331
0
  return r->has_empty_hostname();
17332
0
}
17333
17334
0
bool ada_has_hostname(ada_url result) noexcept {
17335
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17336
0
  if (!r) {
17337
0
    return false;
17338
0
  }
17339
0
  return r->has_hostname();
17340
0
}
17341
17342
0
bool ada_has_non_empty_username(ada_url result) noexcept {
17343
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17344
0
  if (!r) {
17345
0
    return false;
17346
0
  }
17347
0
  return r->has_non_empty_username();
17348
0
}
17349
17350
0
bool ada_has_non_empty_password(ada_url result) noexcept {
17351
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17352
0
  if (!r) {
17353
0
    return false;
17354
0
  }
17355
0
  return r->has_non_empty_password();
17356
0
}
17357
17358
0
bool ada_has_port(ada_url result) noexcept {
17359
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17360
0
  if (!r) {
17361
0
    return false;
17362
0
  }
17363
0
  return r->has_port();
17364
0
}
17365
17366
0
bool ada_has_password(ada_url result) noexcept {
17367
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17368
0
  if (!r) {
17369
0
    return false;
17370
0
  }
17371
0
  return r->has_password();
17372
0
}
17373
17374
0
bool ada_has_hash(ada_url result) noexcept {
17375
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17376
0
  if (!r) {
17377
0
    return false;
17378
0
  }
17379
0
  return r->has_hash();
17380
0
}
17381
17382
0
bool ada_has_search(ada_url result) noexcept {
17383
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17384
0
  if (!r) {
17385
0
    return false;
17386
0
  }
17387
0
  return r->has_search();
17388
0
}
17389
17390
// returns a pointer to the internal url_aggregator::url_components
17391
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
17392
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
17393
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
17394
0
  if (!r) {
17395
0
    return nullptr;
17396
0
  }
17397
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
17398
0
}
17399
17400
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
17401
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
17402
0
  ada_owned_string owned{};
17403
0
  owned.length = out.length();
17404
0
  owned.data = new char[owned.length];
17405
0
  memcpy((void*)owned.data, out.data(), owned.length);
17406
0
  return owned;
17407
0
}
17408
17409
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
17410
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
17411
0
  ada_owned_string owned{};
17412
0
  owned.length = out.size();
17413
0
  owned.data = new char[owned.length];
17414
0
  memcpy((void*)owned.data, out.data(), owned.length);
17415
0
  return owned;
17416
0
}
17417
17418
ada_url_search_params ada_parse_search_params(const char* input,
17419
0
                                              size_t length) {
17420
0
  return new ada::result<ada::url_search_params>(
17421
0
      ada::url_search_params(std::string_view(input, length)));
17422
0
}
17423
17424
0
void ada_free_search_params(ada_url_search_params result) {
17425
0
  auto* r = (ada::result<ada::url_search_params>*)result;
17426
0
  delete r;
17427
0
}
17428
17429
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
17430
0
  ada::result<ada::url_search_params>& r =
17431
0
      *(ada::result<ada::url_search_params>*)result;
17432
0
  if (!r) return ada_owned_string{nullptr, 0};
17433
0
  std::string out = r->to_string();
17434
0
  ada_owned_string owned{};
17435
0
  owned.length = out.size();
17436
0
  owned.data = new char[owned.length];
17437
0
  memcpy((void*)owned.data, out.data(), owned.length);
17438
0
  return owned;
17439
0
}
17440
17441
0
size_t ada_search_params_size(ada_url_search_params result) {
17442
0
  ada::result<ada::url_search_params>& r =
17443
0
      *(ada::result<ada::url_search_params>*)result;
17444
0
  if (!r) {
17445
0
    return 0;
17446
0
  }
17447
0
  return r->size();
17448
0
}
17449
17450
0
void ada_search_params_sort(ada_url_search_params result) {
17451
0
  ada::result<ada::url_search_params>& r =
17452
0
      *(ada::result<ada::url_search_params>*)result;
17453
0
  if (r) {
17454
0
    r->sort();
17455
0
  }
17456
0
}
17457
17458
void ada_search_params_reset(ada_url_search_params result, const char* input,
17459
0
                             size_t length) {
17460
0
  ada::result<ada::url_search_params>& r =
17461
0
      *(ada::result<ada::url_search_params>*)result;
17462
0
  if (r) {
17463
0
    r->reset(std::string_view(input, length));
17464
0
  }
17465
0
}
17466
17467
void ada_search_params_append(ada_url_search_params result, const char* key,
17468
                              size_t key_length, const char* value,
17469
0
                              size_t value_length) {
17470
0
  ada::result<ada::url_search_params>& r =
17471
0
      *(ada::result<ada::url_search_params>*)result;
17472
0
  if (r) {
17473
0
    r->append(std::string_view(key, key_length),
17474
0
              std::string_view(value, value_length));
17475
0
  }
17476
0
}
17477
17478
void ada_search_params_set(ada_url_search_params result, const char* key,
17479
                           size_t key_length, const char* value,
17480
0
                           size_t value_length) {
17481
0
  ada::result<ada::url_search_params>& r =
17482
0
      *(ada::result<ada::url_search_params>*)result;
17483
0
  if (r) {
17484
0
    r->set(std::string_view(key, key_length),
17485
0
           std::string_view(value, value_length));
17486
0
  }
17487
0
}
17488
17489
void ada_search_params_remove(ada_url_search_params result, const char* key,
17490
0
                              size_t key_length) {
17491
0
  ada::result<ada::url_search_params>& r =
17492
0
      *(ada::result<ada::url_search_params>*)result;
17493
0
  if (r) {
17494
0
    r->remove(std::string_view(key, key_length));
17495
0
  }
17496
0
}
17497
17498
void ada_search_params_remove_value(ada_url_search_params result,
17499
                                    const char* key, size_t key_length,
17500
0
                                    const char* value, size_t value_length) {
17501
0
  ada::result<ada::url_search_params>& r =
17502
0
      *(ada::result<ada::url_search_params>*)result;
17503
0
  if (r) {
17504
0
    r->remove(std::string_view(key, key_length),
17505
0
              std::string_view(value, value_length));
17506
0
  }
17507
0
}
17508
17509
bool ada_search_params_has(ada_url_search_params result, const char* key,
17510
0
                           size_t key_length) {
17511
0
  ada::result<ada::url_search_params>& r =
17512
0
      *(ada::result<ada::url_search_params>*)result;
17513
0
  if (!r) {
17514
0
    return false;
17515
0
  }
17516
0
  return r->has(std::string_view(key, key_length));
17517
0
}
17518
17519
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
17520
                                 size_t key_length, const char* value,
17521
0
                                 size_t value_length) {
17522
0
  ada::result<ada::url_search_params>& r =
17523
0
      *(ada::result<ada::url_search_params>*)result;
17524
0
  if (!r) {
17525
0
    return false;
17526
0
  }
17527
0
  return r->has(std::string_view(key, key_length),
17528
0
                std::string_view(value, value_length));
17529
0
}
17530
17531
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
17532
0
                                 size_t key_length) {
17533
0
  ada::result<ada::url_search_params>& r =
17534
0
      *(ada::result<ada::url_search_params>*)result;
17535
0
  if (!r) {
17536
0
    return ada_string_create(nullptr, 0);
17537
0
  }
17538
0
  auto found = r->get(std::string_view(key, key_length));
17539
0
  if (!found.has_value()) {
17540
0
    return ada_string_create(nullptr, 0);
17541
0
  }
17542
0
  return ada_string_create(found->data(), found->length());
17543
0
}
17544
17545
ada_strings ada_search_params_get_all(ada_url_search_params result,
17546
0
                                      const char* key, size_t key_length) {
17547
0
  ada::result<ada::url_search_params>& r =
17548
0
      *(ada::result<ada::url_search_params>*)result;
17549
0
  if (!r) {
17550
0
    return new ada::result<std::vector<std::string>>(
17551
0
        std::vector<std::string>());
17552
0
  }
17553
0
  return new ada::result<std::vector<std::string>>(
17554
0
      r->get_all(std::string_view(key, key_length)));
17555
0
}
17556
17557
ada_url_search_params_keys_iter ada_search_params_get_keys(
17558
0
    ada_url_search_params result) {
17559
0
  ada::result<ada::url_search_params>& r =
17560
0
      *(ada::result<ada::url_search_params>*)result;
17561
0
  if (!r) {
17562
0
    return new ada::result<ada::url_search_params_keys_iter>(
17563
0
        ada::url_search_params_keys_iter());
17564
0
  }
17565
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
17566
0
}
17567
17568
ada_url_search_params_values_iter ada_search_params_get_values(
17569
0
    ada_url_search_params result) {
17570
0
  ada::result<ada::url_search_params>& r =
17571
0
      *(ada::result<ada::url_search_params>*)result;
17572
0
  if (!r) {
17573
0
    return new ada::result<ada::url_search_params_values_iter>(
17574
0
        ada::url_search_params_values_iter());
17575
0
  }
17576
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
17577
0
}
17578
17579
ada_url_search_params_entries_iter ada_search_params_get_entries(
17580
0
    ada_url_search_params result) {
17581
0
  ada::result<ada::url_search_params>& r =
17582
0
      *(ada::result<ada::url_search_params>*)result;
17583
0
  if (!r) {
17584
0
    return new ada::result<ada::url_search_params_entries_iter>(
17585
0
        ada::url_search_params_entries_iter());
17586
0
  }
17587
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
17588
0
}
17589
17590
0
void ada_free_strings(ada_strings result) {
17591
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17592
0
  delete r;
17593
0
}
17594
17595
0
size_t ada_strings_size(ada_strings result) {
17596
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17597
0
  if (!r) {
17598
0
    return 0;
17599
0
  }
17600
0
  return (*r)->size();
17601
0
}
17602
17603
0
ada_string ada_strings_get(ada_strings result, size_t index) {
17604
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
17605
0
  if (!r) {
17606
0
    return ada_string_create(nullptr, 0);
17607
0
  }
17608
0
  std::string_view view = (*r)->at(index);
17609
0
  return ada_string_create(view.data(), view.length());
17610
0
}
17611
17612
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
17613
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17614
0
  delete r;
17615
0
}
17616
17617
ada_string ada_search_params_keys_iter_next(
17618
0
    ada_url_search_params_keys_iter result) {
17619
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17620
0
  if (!r) {
17621
0
    return ada_string_create(nullptr, 0);
17622
0
  }
17623
0
  auto next = (*r)->next();
17624
0
  if (!next.has_value()) {
17625
0
    return ada_string_create(nullptr, 0);
17626
0
  }
17627
0
  return ada_string_create(next->data(), next->length());
17628
0
}
17629
17630
bool ada_search_params_keys_iter_has_next(
17631
0
    ada_url_search_params_keys_iter result) {
17632
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
17633
0
  if (!r) {
17634
0
    return false;
17635
0
  }
17636
0
  return (*r)->has_next();
17637
0
}
17638
17639
void ada_free_search_params_values_iter(
17640
0
    ada_url_search_params_values_iter result) {
17641
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17642
0
  delete r;
17643
0
}
17644
17645
ada_string ada_search_params_values_iter_next(
17646
0
    ada_url_search_params_values_iter result) {
17647
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17648
0
  if (!r) {
17649
0
    return ada_string_create(nullptr, 0);
17650
0
  }
17651
0
  auto next = (*r)->next();
17652
0
  if (!next.has_value()) {
17653
0
    return ada_string_create(nullptr, 0);
17654
0
  }
17655
0
  return ada_string_create(next->data(), next->length());
17656
0
}
17657
17658
bool ada_search_params_values_iter_has_next(
17659
0
    ada_url_search_params_values_iter result) {
17660
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
17661
0
  if (!r) {
17662
0
    return false;
17663
0
  }
17664
0
  return (*r)->has_next();
17665
0
}
17666
17667
void ada_free_search_params_entries_iter(
17668
0
    ada_url_search_params_entries_iter result) {
17669
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17670
0
  delete r;
17671
0
}
17672
17673
ada_string_pair ada_search_params_entries_iter_next(
17674
0
    ada_url_search_params_entries_iter result) {
17675
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17676
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
17677
0
  auto next = (*r)->next();
17678
0
  if (!next.has_value()) {
17679
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
17680
0
  }
17681
0
  return ada_string_pair{
17682
0
      ada_string_create(next->first.data(), next->first.length()),
17683
0
      ada_string_create(next->second.data(), next->second.length())};
17684
0
}
17685
17686
bool ada_search_params_entries_iter_has_next(
17687
0
    ada_url_search_params_entries_iter result) {
17688
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
17689
0
  if (!r) {
17690
0
    return false;
17691
0
  }
17692
0
  return (*r)->has_next();
17693
0
}
17694
17695
}  // extern "C"
17696
/* end file src/ada_c.cpp */
17697
/* end file src/ada.cpp */